/* */
This source file includes following definitions.
- linetable_open
- linetable_read
- linetable_put
- linetable_get
- linetable_close
- linetable_print
1 /*
2 * Copyright (c) 2002, 2004 Tama Communications Corporation
3 *
4 * This file is part of GNU GLOBAL.
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 #ifdef STDC_HEADERS
24 #include <stdlib.h>
25 #endif
26 #ifdef HAVE_STRING_H
27 #include <string.h>
28 #else
29 #include <strings.h>
30 #endif
31 #include <sys/stat.h>
32
33 #include "die.h"
34 #include "linetable.h"
35 #include "varray.h"
36 #include "strbuf.h"
37
38 /** @name File buffer */
39 /** @{ */
40 #define EXPAND 1024
41 static STRBUF *ib;
42 static char *filebuf;
43 static int filesize;
44 /** @} */
45
46 /** @name File pointer */
47 /** @{ */
48 static char *curp;
49 static char *endp;
50 /** @} */
51
52 /** Offset table */
53 static VARRAY *vb;
54
55 static void linetable_put(int, int);
56 /**
57 * linetable_open: load whole of file into memory.
58 *
59 * @param[in] path path
60 * @return 0: normal <br>
61 * -1: cannot open file.
62 */
63 int
64 linetable_open(const char *path)
65 {
66 FILE *ip;
67 struct stat sb;
68 int lineno, offset;
69
70 if (stat(path, &sb) < 0)
71 return -1;
72 ib = strbuf_open(sb.st_size);
73 vb = varray_open(sizeof(int), EXPAND);
74 if ((ip = fopen(path, "r")) == NULL)
75 return -1;
76 lineno = 1;
77 offset = 0;
78 for (offset = 0;
79 (strbuf_fgets(ib, ip, STRBUF_APPEND), offset != strbuf_getlen(ib));
80 offset = strbuf_getlen(ib))
81 {
82 linetable_put(offset, lineno++);
83 }
84 fclose(ip);
85 curp = filebuf = strbuf_value(ib);
86 filesize = offset;
87 endp = filebuf + filesize;
88 /* strbuf_close(ib); */
89
90 return 0;
91 }
92 /**
93 * linetable_read: @XREF{read,2} compatible routine for linetable.
94 *
95 * @param[in,out] buf read buffer
96 * @param[in] size buffer size
97 * @return ==-1: end of file <br>
98 * !=-1: number of bytes actually read
99 */
100 int
101 linetable_read(char *buf, int size)
102 {
103 int leaved = endp - curp;
104
105 if (leaved <= 0)
106 return -1; /* EOF */
107 if (size > leaved)
108 size = leaved;
109 memcpy(buf, curp, size);
110 curp += size;
111
112 return size;
113 }
114 /**
115 * linetable_put: put a line into table.
116 *
117 * @param[in] offset offset of the line
118 * @param[in] lineno line number of the line (\>= 1)
119 */
120 void
121 linetable_put(int offset, int lineno)
122 {
123 int *entry;
124
125 if (lineno <= 0)
126 die("linetable_put: line number must >= 1 (lineno = %d)", lineno);
127 entry = varray_assign(vb, lineno - 1, 1);
128 *entry = offset;
129 }
130 /**
131 * linetable_get: get a line from table.
132 *
133 * @param[in] lineno line number of the line (\>= 1)
134 * @param[out] offset offset of the line <br>
135 * if @CODE{offset == NULL}, nothing returned.
136 * @return line pointer
137 */
138 char *
139 linetable_get(int lineno, int *offset)
140 {
141 int addr;
142
143 if (lineno <= 0)
144 die("linetable_get: line number must >= 1 (lineno = %d)", lineno);
145 addr = *((int *)varray_assign(vb, lineno - 1, 0));
146 if (offset)
147 *offset = addr;
148 return filebuf + addr;
149 }
150 /**
151 * linetable_close: close line table.
152 */
153 void
154 linetable_close(void)
155 {
156 varray_close(vb);
157 strbuf_close(ib);
158 }
159 /**
160 * linetable_print: print a line.
161 *
162 * @param[in] op output file pointer
163 * @param[in] lineno line number (\>= 1)
164 */
165 void
166 linetable_print(FILE *op, int lineno)
167 {
168 const char *s, *p;
169
170 if (lineno <= 0)
171 die("linetable_print: line number must >= 1 (lineno = %d)", lineno);
172 s = linetable_get(lineno, NULL);
173 if (vb->length == lineno) {
174 /*
175 * The last line may not include newline.
176 */
177 fwrite(s, 1, endp - s, op);
178 if (endp[-1] != '\n')
179 fputc('\n', op);
180 } else {
181 p = linetable_get(lineno + 1, NULL);
182 fwrite(s, 1, p - s, op);
183 }
184 }
/* */