/* * Copyright (c) 2002, 2004 Tama Communications Corporation * * This file is part of GNU GLOBAL. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifdef HAVE_CONFIG_H #include #endif #ifdef STDC_HEADERS #include #endif #ifdef HAVE_STRING_H #include #else #include #endif #include #include "die.h" #include "linetable.h" #include "varray.h" #include "strbuf.h" /* File buffer */ #define EXPAND 1024 static STRBUF *ib; static char *filebuf; static int filesize; /* File pointer */ static char *curp; static char *endp; /* Offset table */ static VARRAY *vb; static void linetable_put(int, int); /* * linetable_open: load whole of file into memory. * * i) path path * r) 0: normal * -1: cannot open file. */ int linetable_open(const char *path) { FILE *ip; struct stat sb; int lineno, offset; if (stat(path, &sb) < 0) return -1; ib = strbuf_open(sb.st_size); vb = varray_open(sizeof(int), EXPAND); if ((ip = fopen(path, "r")) == NULL) return -1; lineno = 1; offset = 0; for (offset = 0; (strbuf_fgets(ib, ip, STRBUF_APPEND), offset != strbuf_getlen(ib)); offset = strbuf_getlen(ib)) { linetable_put(offset, lineno++); } fclose(ip); curp = filebuf = strbuf_value(ib); filesize = offset; endp = filebuf + filesize; /* strbuf_close(ib); */ return 0; } /* * linetable_read: read(2) compatible routine for linetable. * * io) buf read buffer * i) size buffer size * r) ==-1: end of file * !=-1: number of bytes actually read */ int linetable_read(char *buf, int size) { int leaved = endp - curp; if (leaved <= 0) return -1; /* EOF */ if (size > leaved) size = leaved; memcpy(buf, curp, size); curp += size; return size; } /* * linetable_put: put a line into table. * * i) offset offset of the line * i) lineno line number of the line (>= 1) */ void linetable_put(int offset, int lineno) { int *entry; if (lineno <= 0) die("linetable_put: line number must >= 1 (lineno = %d)", lineno); entry = varray_assign(vb, lineno - 1, 1); *entry = offset; } /* * linetable_get: get a line from table. * * i) lineno line number of the line (>= 1) * o) offset offset of the line * if offset == NULL, nothing returned. * r) line pointer */ char * linetable_get(int lineno, int *offset) { int addr; if (lineno <= 0) die("linetable_get: line number must >= 1 (lineno = %d)", lineno); addr = *((int *)varray_assign(vb, lineno - 1, 0)); if (offset) *offset = addr; return filebuf + addr; } /* * linetable_close: close line table. */ void linetable_close(void) { varray_close(vb); strbuf_close(ib); } /* * linetable_print: print a line. * * i) op output file pointer * i) lineno line number (>= 1) */ void linetable_print(FILE *op, int lineno) { const char *s, *p; if (lineno <= 0) die("linetable_print: line number must >= 1 (lineno = %d)", lineno); s = linetable_get(lineno, NULL); if (vb->length == lineno) { /* * The last line may not include newline. */ fwrite(s, 1, endp - s, op); if (endp[-1] != '\n') fputc('\n', op); } else { p = linetable_get(lineno + 1, NULL); fwrite(s, 1, p - s, op); } }