33 |
|
|
34 |
#include "die.h" |
#include "die.h" |
35 |
#include "linetable.h" |
#include "linetable.h" |
36 |
|
#include "varray.h" |
37 |
#include "strbuf.h" |
#include "strbuf.h" |
38 |
|
|
39 |
/* File buffer */ |
/* File buffer */ |
46 |
static char *curp; |
static char *curp; |
47 |
static char *endp; |
static char *endp; |
48 |
|
|
49 |
/* Index for line */ |
/* Offset table */ |
50 |
static int *linetable; |
VARRAY *vb; |
|
static int total_lines; |
|
|
static int active_lines; |
|
51 |
|
|
52 |
static void linetable_put(int, int); |
static void linetable_put(int, int); |
53 |
/* |
/* |
68 |
if (stat(path, &sb) < 0) |
if (stat(path, &sb) < 0) |
69 |
return -1; |
return -1; |
70 |
ib = strbuf_open(sb.st_size); |
ib = strbuf_open(sb.st_size); |
71 |
|
vb = varray_open(sizeof(int), EXPAND); |
72 |
if ((ip = fopen(path, "r")) == NULL) |
if ((ip = fopen(path, "r")) == NULL) |
73 |
return -1; |
return -1; |
74 |
lineno = 1; |
lineno = 1; |
117 |
* i) offset offset of the line |
* i) offset offset of the line |
118 |
* i) lineno line number of the line (>= 1) |
* i) lineno line number of the line (>= 1) |
119 |
*/ |
*/ |
120 |
static void |
void |
121 |
linetable_put(offset, lineno) |
linetable_put(offset, lineno) |
122 |
int offset; |
int offset; |
123 |
int lineno; |
int lineno; |
124 |
{ |
{ |
125 |
if (lineno-- <= 0) |
int *entry; |
126 |
die("line number must >= 1"); |
|
127 |
/* |
if (lineno <= 0) |
128 |
* Old implementations of realloc() may crash when a null pointer is passed. |
die("linetable_put: line number must >= 1 (lineno = %d)", lineno); |
129 |
* Therefore, we cannot use realloc(NULL, total_lines * sizeof(int)). |
entry = varray_assign(vb, lineno - 1, 1); |
130 |
*/ |
*entry = offset; |
|
if (!total_lines) { |
|
|
total_lines = EXPAND; |
|
|
linetable = (int *)malloc(total_lines * sizeof(int)); |
|
|
if (linetable == NULL) |
|
|
die("short of memory"); |
|
|
} |
|
|
if (total_lines <= lineno) { |
|
|
total_lines += (lineno > EXPAND) ? lineno : EXPAND; |
|
|
linetable = (int *)realloc(linetable, total_lines * sizeof(int)); |
|
|
if (linetable == NULL) |
|
|
die("short of memory"); |
|
|
} |
|
|
if (lineno > active_lines) |
|
|
active_lines = lineno; |
|
|
linetable[lineno] = offset; |
|
131 |
} |
} |
132 |
/* |
/* |
133 |
* linetable_get: get a line from table. |
* linetable_get: get a line from table. |
144 |
{ |
{ |
145 |
int addr; |
int addr; |
146 |
|
|
147 |
if (lineno-- <= 0) |
if (lineno <= 0) |
148 |
return NULL; |
die("linetable_get: line number must >= 1 (lineno = %d)", lineno); |
149 |
if (lineno > active_lines) |
addr = *((int *)varray_assign(vb, lineno - 1, 0)); |
|
return NULL; |
|
|
addr = linetable[lineno]; |
|
150 |
if (offset) |
if (offset) |
151 |
*offset = addr; |
*offset = addr; |
152 |
return filebuf + addr; |
return filebuf + addr; |
157 |
void |
void |
158 |
linetable_close() |
linetable_close() |
159 |
{ |
{ |
160 |
if (linetable) |
varray_close(vb); |
|
(void)free(linetable); |
|
|
linetable = NULL; |
|
|
total_lines = active_lines = 0; |
|
161 |
strbuf_close(ib); |
strbuf_close(ib); |
162 |
} |
} |
163 |
/* |
/* |
171 |
FILE *op; |
FILE *op; |
172 |
int lineno; |
int lineno; |
173 |
{ |
{ |
174 |
char *s = linetable_get(lineno, NULL); |
char *s; |
175 |
|
|
176 |
|
if (lineno <= 0) |
177 |
|
die("linetable_print: line number must >= 1 (lineno = %d)", lineno); |
178 |
|
s = linetable_get(lineno, NULL); |
179 |
if (s == NULL) |
if (s == NULL) |
180 |
return; |
return; |
181 |
while (*s != '\n') |
while (*s != '\n') |