Lines 64-84
Link Here
|
64 |
int lh_ref; |
64 |
int lh_ref; |
65 |
} *labels[LHSZ]; |
65 |
} *labels[LHSZ]; |
66 |
|
66 |
|
67 |
static char *compile_addr(char *, struct s_addr *); |
67 |
static const char *compile_addr(const char *, struct s_addr *); |
68 |
static char *compile_ccl(char **, char *); |
68 |
static char *compile_ccl(const char **, char *); |
69 |
static char *compile_delimited(char *, char *, int); |
69 |
static const char *compile_delimited(const char *, char *, int); |
70 |
static char *compile_flags(char *, struct s_subst *); |
70 |
static const char *compile_flags(const char *, struct s_subst *); |
71 |
static regex_t *compile_re(char *, int); |
71 |
static const regex_t *compile_re(const char *, int); |
72 |
static char *compile_subst(char *, struct s_subst *); |
72 |
static const char *compile_subst(const char *, struct s_subst *); |
73 |
static char *compile_text(void); |
73 |
static char *compile_text(size_t *); |
74 |
static char *compile_tr(char *, struct s_tr **); |
74 |
static const char *compile_tr(const char *, struct s_tr **); |
75 |
static struct s_command |
75 |
static struct s_command |
76 |
**compile_stream(struct s_command **); |
76 |
**compile_stream(struct s_command **); |
77 |
static char *duptoeol(char *, const char *); |
77 |
static char *duptoeol(const char *, const char *, size_t *); |
78 |
static void enterlabel(struct s_command *); |
78 |
static void enterlabel(struct s_command *); |
79 |
static struct s_command |
79 |
static struct s_command |
80 |
*findlabel(char *); |
80 |
*findlabel(const char *); |
81 |
static void fixuplabel(struct s_command *, struct s_command *); |
81 |
static void fixuplabel(struct s_command *, const struct s_command *); |
82 |
static void uselabel(void); |
82 |
static void uselabel(void); |
83 |
|
83 |
|
84 |
/* |
84 |
/* |
Lines 144-183
Link Here
|
144 |
err(1, "malloc"); |
144 |
err(1, "malloc"); |
145 |
} |
145 |
} |
146 |
|
146 |
|
147 |
#define EATSPACE() do { \ |
147 |
#define EATSPACE() do { \ |
148 |
if (p) \ |
148 |
while (*p && isspace((unsigned char)*p)) \ |
149 |
while (*p && isspace((unsigned char)*p)) \ |
149 |
p++; \ |
150 |
p++; \ |
|
|
151 |
} while (0) |
150 |
} while (0) |
152 |
|
151 |
|
|
|
152 |
#define EATSPACEN() do { \ |
153 |
while (*p && *p != '\n' && isspace((unsigned char)*p)) \ |
154 |
p++; \ |
155 |
} while (0) |
156 |
|
153 |
static struct s_command ** |
157 |
static struct s_command ** |
154 |
compile_stream(struct s_command **link) |
158 |
compile_stream(struct s_command **link) |
155 |
{ |
159 |
{ |
156 |
char *p; |
160 |
const char *p; |
157 |
static char lbuf[_POSIX2_LINE_MAX + 1]; /* To save stack */ |
|
|
158 |
struct s_command *cmd, *cmd2, *stack; |
161 |
struct s_command *cmd, *cmd2, *stack; |
159 |
struct s_format *fp; |
162 |
struct s_format *fp; |
160 |
char re[_POSIX2_LINE_MAX + 1]; |
163 |
char re[_POSIX2_LINE_MAX + 1]; |
161 |
int naddr; /* Number of addresses */ |
164 |
int naddr; /* Number of addresses */ |
162 |
|
165 |
|
163 |
stack = 0; |
166 |
stack = NULL; |
164 |
for (;;) { |
167 |
for (;;) { |
165 |
if ((p = cu_fgets(lbuf, sizeof(lbuf), NULL)) == NULL) { |
168 |
if ((p = cu_fgets(NULL)) == NULL) { |
166 |
if (stack != 0) |
169 |
if (stack != NULL) |
167 |
errx(1, "%lu: %s: unexpected EOF (pending }'s)", |
170 |
errx(1, "%lu: %s: unexpected EOF (pending }'s)", |
168 |
linenum, fname); |
171 |
linenum, fname); |
169 |
return (link); |
172 |
return (link); |
170 |
} |
173 |
} |
171 |
|
174 |
|
172 |
semicolon: EATSPACE(); |
175 |
semicolon: EATSPACEN(); |
173 |
if (p) { |
176 |
switch (*p) { |
174 |
if (*p == '#' || *p == '\0') |
177 |
case '#': case '\0': case '\n': |
175 |
continue; |
178 |
continue; /* to next command-unit */ |
176 |
else if (*p == ';') { |
179 |
case ';': |
177 |
p++; |
180 |
p++; |
178 |
goto semicolon; |
181 |
goto semicolon; |
179 |
} |
|
|
180 |
} |
182 |
} |
|
|
183 |
|
181 |
if ((*link = cmd = malloc(sizeof(struct s_command))) == NULL) |
184 |
if ((*link = cmd = malloc(sizeof(struct s_command))) == NULL) |
182 |
err(1, "malloc"); |
185 |
err(1, "malloc"); |
183 |
link = &cmd->next; |
186 |
link = &cmd->next; |
Lines 208-214
Link Here
|
208 |
cmd->a1 = cmd->a2 = 0; |
211 |
cmd->a1 = cmd->a2 = 0; |
209 |
|
212 |
|
210 |
nonsel: /* Now parse the command */ |
213 |
nonsel: /* Now parse the command */ |
211 |
if (!*p) |
214 |
if (*p == '\0' || *p == '\n') |
212 |
errx(1, "%lu: %s: command expected", linenum, fname); |
215 |
errx(1, "%lu: %s: command expected", linenum, fname); |
213 |
cmd->code = *p; |
216 |
cmd->code = *p; |
214 |
for (fp = cmd_fmts; fp->code; fp++) |
217 |
for (fp = cmd_fmts; fp->code; fp++) |
Lines 215-221
Link Here
|
215 |
if (fp->code == *p) |
218 |
if (fp->code == *p) |
216 |
break; |
219 |
break; |
217 |
if (!fp->code) |
220 |
if (!fp->code) |
218 |
errx(1, "%lu: %s: invalid command code %c", linenum, fname, *p); |
221 |
errx(1, "%lu: %s: invalid command code %c (%s)", linenum, fname, *p, p); |
219 |
if (naddr > fp->naddr) |
222 |
if (naddr > fp->naddr) |
220 |
errx(1, |
223 |
errx(1, |
221 |
"%lu: %s: command %c expects up to %d address(es), found %d", |
224 |
"%lu: %s: command %c expects up to %d address(es), found %d", |
Lines 228-238
Link Here
|
228 |
goto nonsel; |
231 |
goto nonsel; |
229 |
case GROUP: /* { */ |
232 |
case GROUP: /* { */ |
230 |
p++; |
233 |
p++; |
231 |
EATSPACE(); |
234 |
EATSPACEN(); |
232 |
cmd->next = stack; |
235 |
cmd->next = stack; |
233 |
stack = cmd; |
236 |
stack = cmd; |
234 |
link = &cmd->u.c; |
237 |
link = &cmd->u.c; |
235 |
if (*p) |
238 |
if (*p != '\0' && *p != '\n') |
236 |
goto semicolon; |
239 |
goto semicolon; |
237 |
break; |
240 |
break; |
238 |
case ENDGROUP: |
241 |
case ENDGROUP: |
Lines 241-247
Link Here
|
241 |
* group is really just a noop. |
244 |
* group is really just a noop. |
242 |
*/ |
245 |
*/ |
243 |
cmd->nonsel = 1; |
246 |
cmd->nonsel = 1; |
244 |
if (stack == 0) |
247 |
if (stack == NULL) |
245 |
errx(1, "%lu: %s: unexpected }", linenum, fname); |
248 |
errx(1, "%lu: %s: unexpected }", linenum, fname); |
246 |
cmd2 = stack; |
249 |
cmd2 = stack; |
247 |
stack = cmd2->next; |
250 |
stack = cmd2->next; |
Lines 249-261
Link Here
|
249 |
/*FALLTHROUGH*/ |
252 |
/*FALLTHROUGH*/ |
250 |
case EMPTY: /* d D g G h H l n N p P q x = \0 */ |
253 |
case EMPTY: /* d D g G h H l n N p P q x = \0 */ |
251 |
p++; |
254 |
p++; |
252 |
EATSPACE(); |
255 |
EATSPACEN(); |
253 |
if (*p == ';') { |
256 |
if (*p == ';') { |
254 |
p++; |
257 |
p++; |
255 |
link = &cmd->next; |
258 |
link = &cmd->next; |
256 |
goto semicolon; |
259 |
goto semicolon; |
257 |
} |
260 |
} |
258 |
if (*p) |
261 |
if (*p != '\0' && *p != '\n') |
259 |
errx(1, "%lu: %s: extra characters at the end of %c command", |
262 |
errx(1, "%lu: %s: extra characters at the end of %c command", |
260 |
linenum, fname, cmd->code); |
263 |
linenum, fname, cmd->code); |
261 |
break; |
264 |
break; |
Lines 266-277
Link Here
|
266 |
errx(1, |
269 |
errx(1, |
267 |
"%lu: %s: command %c expects \\ followed by text", linenum, fname, cmd->code); |
270 |
"%lu: %s: command %c expects \\ followed by text", linenum, fname, cmd->code); |
268 |
p++; |
271 |
p++; |
269 |
EATSPACE(); |
272 |
EATSPACEN(); |
270 |
if (*p) |
273 |
if (*p != '\n') |
271 |
errx(1, |
274 |
errx(1, |
272 |
"%lu: %s: extra characters after \\ at the end of %c command", |
275 |
"%lu: %s: extra characters (%c) after \\ at the end of %c command", |
273 |
linenum, fname, cmd->code); |
276 |
linenum, fname, *p, cmd->code); |
274 |
cmd->t = compile_text(); |
277 |
cmd->t = compile_text(&cmd->tlen); |
275 |
break; |
278 |
break; |
276 |
case COMMENT: /* \0 # */ |
279 |
case COMMENT: /* \0 # */ |
277 |
break; |
280 |
break; |
Lines 280-289
Link Here
|
280 |
EATSPACE(); |
283 |
EATSPACE(); |
281 |
if (*p == '\0') |
284 |
if (*p == '\0') |
282 |
errx(1, "%lu: %s: filename expected", linenum, fname); |
285 |
errx(1, "%lu: %s: filename expected", linenum, fname); |
283 |
cmd->t = duptoeol(p, "w command"); |
286 |
cmd->t = duptoeol(p, "w command", &cmd->tlen); |
284 |
if (aflag) |
287 |
if (aflag) |
285 |
cmd->u.fd = -1; |
288 |
cmd->u.fd = -1; |
286 |
else if ((cmd->u.fd = open(p, |
289 |
else if ((cmd->u.fd = open(cmd->t, |
287 |
O_WRONLY|O_APPEND|O_CREAT|O_TRUNC, |
290 |
O_WRONLY|O_APPEND|O_CREAT|O_TRUNC, |
288 |
DEFFILEMODE)) == -1) |
291 |
DEFFILEMODE)) == -1) |
289 |
err(1, "%s", p); |
292 |
err(1, "%s", p); |
Lines 294-320
Link Here
|
294 |
if (*p == '\0') |
297 |
if (*p == '\0') |
295 |
errx(1, "%lu: %s: filename expected", linenum, fname); |
298 |
errx(1, "%lu: %s: filename expected", linenum, fname); |
296 |
else |
299 |
else |
297 |
cmd->t = duptoeol(p, "read command"); |
300 |
cmd->t = duptoeol(p, "read command", &cmd->tlen); |
298 |
break; |
301 |
break; |
299 |
case BRANCH: /* b t */ |
302 |
case BRANCH: /* b t */ |
300 |
p++; |
303 |
p++; |
301 |
EATSPACE(); |
304 |
EATSPACEN(); |
302 |
if (*p == '\0') |
305 |
if (*p == '\0' || *p == '\n') |
303 |
cmd->t = NULL; |
306 |
cmd->t = NULL; |
304 |
else |
307 |
else |
305 |
cmd->t = duptoeol(p, "branch"); |
308 |
cmd->t = duptoeol(p, "branch", &cmd->tlen); |
306 |
break; |
309 |
break; |
307 |
case LABEL: /* : */ |
310 |
case LABEL: /* : */ |
308 |
p++; |
311 |
p++; |
309 |
EATSPACE(); |
312 |
EATSPACE(); |
310 |
cmd->t = duptoeol(p, "label"); |
313 |
cmd->t = duptoeol(p, "label", &cmd->tlen); |
311 |
if (strlen(p) == 0) |
314 |
if (cmd->t[0] == '\0') |
312 |
errx(1, "%lu: %s: empty label", linenum, fname); |
315 |
errx(1, "%lu: %s: empty label", linenum, fname); |
313 |
enterlabel(cmd); |
316 |
enterlabel(cmd); |
314 |
break; |
317 |
break; |
315 |
case SUBST: /* s */ |
318 |
case SUBST: /* s */ |
316 |
p++; |
319 |
p++; |
317 |
if (*p == '\0' || *p == '\\') |
320 |
if (*p == '\0' || *p == '\\' || *p == '\n') |
318 |
errx(1, |
321 |
errx(1, |
319 |
"%lu: %s: substitute pattern can not be delimited by newline or backslash", |
322 |
"%lu: %s: substitute pattern can not be delimited by newline or backslash", |
320 |
linenum, fname); |
323 |
linenum, fname); |
Lines 325-345
Link Here
|
325 |
errx(1, |
328 |
errx(1, |
326 |
"%lu: %s: unterminated substitute pattern", linenum, fname); |
329 |
"%lu: %s: unterminated substitute pattern", linenum, fname); |
327 |
|
330 |
|
328 |
/* Compile RE with no case sensitivity temporarily */ |
|
|
329 |
if (*re == '\0') |
330 |
cmd->u.s->re = NULL; |
331 |
else |
332 |
cmd->u.s->re = compile_re(re, 0); |
333 |
--p; |
331 |
--p; |
334 |
p = compile_subst(p, cmd->u.s); |
332 |
p = compile_subst(p, cmd->u.s); |
335 |
p = compile_flags(p, cmd->u.s); |
333 |
p = compile_flags(p, cmd->u.s); |
336 |
|
334 |
|
337 |
/* Recompile RE with case sensitivity from "I" flag if any */ |
335 |
if (*re != '\0') |
338 |
if (*re == '\0') |
|
|
339 |
cmd->u.s->re = NULL; |
340 |
else |
341 |
cmd->u.s->re = compile_re(re, cmd->u.s->icase); |
336 |
cmd->u.s->re = compile_re(re, cmd->u.s->icase); |
|
|
337 |
|
342 |
EATSPACE(); |
338 |
EATSPACE(); |
|
|
339 |
|
343 |
if (*p == ';') { |
340 |
if (*p == ';') { |
344 |
p++; |
341 |
p++; |
345 |
link = &cmd->next; |
342 |
link = &cmd->next; |
Lines 372-379
Link Here
|
372 |
* in the case of a non-terminated string. The character array d is filled |
369 |
* in the case of a non-terminated string. The character array d is filled |
373 |
* with the processed string. |
370 |
* with the processed string. |
374 |
*/ |
371 |
*/ |
375 |
static char * |
372 |
static const char * |
376 |
compile_delimited(char *p, char *d, int is_tr) |
373 |
compile_delimited(const char *p, char *d, int is_tr) |
377 |
{ |
374 |
{ |
378 |
char c; |
375 |
char c; |
379 |
|
376 |
|
Lines 416-425
Link Here
|
416 |
|
413 |
|
417 |
/* compile_ccl: expand a POSIX character class */ |
414 |
/* compile_ccl: expand a POSIX character class */ |
418 |
static char * |
415 |
static char * |
419 |
compile_ccl(char **sp, char *t) |
416 |
compile_ccl(const char **sp, char *t) |
420 |
{ |
417 |
{ |
421 |
int c, d; |
418 |
int c, d; |
422 |
char *s = *sp; |
419 |
const char *s = *sp; |
423 |
|
420 |
|
424 |
*t++ = *s++; |
421 |
*t++ = *s++; |
425 |
if (*s == '^') |
422 |
if (*s == '^') |
Lines 441-448
Link Here
|
441 |
* regular expression. |
438 |
* regular expression. |
442 |
* Cflags are passed to regcomp. |
439 |
* Cflags are passed to regcomp. |
443 |
*/ |
440 |
*/ |
444 |
static regex_t * |
441 |
static const regex_t * |
445 |
compile_re(char *re, int case_insensitive) |
442 |
compile_re(const char *re, int case_insensitive) |
446 |
{ |
443 |
{ |
447 |
regex_t *rep; |
444 |
regex_t *rep; |
448 |
int eval, flags; |
445 |
int eval, flags; |
Lines 466-479
Link Here
|
466 |
* point to a saved copy of it. Nsub is the number of parenthesized regular |
463 |
* point to a saved copy of it. Nsub is the number of parenthesized regular |
467 |
* expressions. |
464 |
* expressions. |
468 |
*/ |
465 |
*/ |
469 |
static char * |
466 |
static const char * |
470 |
compile_subst(char *p, struct s_subst *s) |
467 |
compile_subst(const char *p, struct s_subst *s) |
471 |
{ |
468 |
{ |
472 |
static char lbuf[_POSIX2_LINE_MAX + 1]; |
|
|
473 |
int asize, size; |
469 |
int asize, size; |
474 |
u_char ref; |
470 |
u_char ref; |
475 |
char c, *text, *op, *sp; |
471 |
char c, *text, *op, *sp; |
476 |
int more = 1, sawesc = 0; |
472 |
int more = 0, sawesc = 0; |
477 |
|
473 |
|
478 |
c = *p++; /* Terminator character */ |
474 |
c = *p++; /* Terminator character */ |
479 |
if (c == '\0') |
475 |
if (c == '\0') |
Lines 487-493
Link Here
|
487 |
size = 0; |
483 |
size = 0; |
488 |
do { |
484 |
do { |
489 |
op = sp = text + size; |
485 |
op = sp = text + size; |
490 |
for (; *p; p++) { |
486 |
for (; *p != '\0' && *p != '\n'; p++) { |
491 |
if (*p == '\\' || sawesc) { |
487 |
if (*p == '\\' || sawesc) { |
492 |
/* |
488 |
/* |
493 |
* If this is a continuation from the last |
489 |
* If this is a continuation from the last |
Lines 509-515
Link Here
|
509 |
*/ |
505 |
*/ |
510 |
sawesc = 1; |
506 |
sawesc = 1; |
511 |
p--; |
507 |
p--; |
512 |
continue; |
508 |
break; |
|
|
509 |
} else if (*p == '\n') { |
510 |
*sp++ = '\n'; |
511 |
break; |
513 |
} else if (strchr("123456789", *p) != NULL) { |
512 |
} else if (strchr("123456789", *p) != NULL) { |
514 |
*sp++ = '\\'; |
513 |
*sp++ = '\\'; |
515 |
ref = *p - '0'; |
514 |
ref = *p - '0'; |
Lines 523-530
Link Here
|
523 |
*sp++ = '\\'; |
522 |
*sp++ = '\\'; |
524 |
} else if (*p == c) { |
523 |
} else if (*p == c) { |
525 |
if (*++p == '\0' && more) { |
524 |
if (*++p == '\0' && more) { |
526 |
if (cu_fgets(lbuf, sizeof(lbuf), &more)) |
525 |
const char *nextp; |
527 |
p = lbuf; |
526 |
|
|
|
527 |
nextp = cu_fgets(&more); |
528 |
if (nextp != NULL) |
529 |
p = nextp; |
528 |
} |
530 |
} |
529 |
*sp++ = '\0'; |
531 |
*sp++ = '\0'; |
530 |
size += sp - op; |
532 |
size += sp - op; |
Lines 544-550
Link Here
|
544 |
if ((text = realloc(text, asize)) == NULL) |
546 |
if ((text = realloc(text, asize)) == NULL) |
545 |
err(1, "realloc"); |
547 |
err(1, "realloc"); |
546 |
} |
548 |
} |
547 |
} while (cu_fgets(p = lbuf, sizeof(lbuf), &more)); |
549 |
} while ((p = cu_fgets(&more))); |
548 |
errx(1, "%lu: %s: unterminated substitute in regular expression", |
550 |
errx(1, "%lu: %s: unterminated substitute in regular expression", |
549 |
linenum, fname); |
551 |
linenum, fname); |
550 |
/* NOTREACHED */ |
552 |
/* NOTREACHED */ |
Lines 553-564
Link Here
|
553 |
/* |
555 |
/* |
554 |
* Compile the flags of the s command |
556 |
* Compile the flags of the s command |
555 |
*/ |
557 |
*/ |
556 |
static char * |
558 |
static const char * |
557 |
compile_flags(char *p, struct s_subst *s) |
559 |
compile_flags(const char *p, struct s_subst *s) |
558 |
{ |
560 |
{ |
559 |
int gn; /* True if we have seen g or n */ |
561 |
int gn; /* True if we have seen g or n */ |
560 |
unsigned long nval; |
562 |
unsigned long nval; |
561 |
char wfile[_POSIX2_LINE_MAX + 1], *q, *eq; |
563 |
char *q; |
562 |
|
564 |
|
563 |
s->n = 1; /* Default */ |
565 |
s->n = 1; /* Default */ |
564 |
s->p = 0; |
566 |
s->p = 0; |
Lines 566-572
Link Here
|
566 |
s->wfd = -1; |
568 |
s->wfd = -1; |
567 |
s->icase = 0; |
569 |
s->icase = 0; |
568 |
for (gn = 0;;) { |
570 |
for (gn = 0;;) { |
569 |
EATSPACE(); /* EXTENSION */ |
571 |
EATSPACEN(); /* EXTENSION */ |
570 |
switch (*p) { |
572 |
switch (*p) { |
571 |
case 'g': |
573 |
case 'g': |
572 |
if (gn) |
574 |
if (gn) |
Lines 594-606
Link Here
|
594 |
"%lu: %s: more than one number or 'g' in substitute flags", linenum, fname); |
596 |
"%lu: %s: more than one number or 'g' in substitute flags", linenum, fname); |
595 |
gn = 1; |
597 |
gn = 1; |
596 |
errno = 0; |
598 |
errno = 0; |
597 |
nval = strtol(p, &p, 10); |
599 |
nval = strtol(p, &q, 10); |
598 |
if (errno == ERANGE || nval > INT_MAX) |
600 |
if (errno == ERANGE || nval > INT_MAX) |
599 |
errx(1, |
601 |
errx(1, |
600 |
"%lu: %s: overflow in the 'N' substitute flag", linenum, fname); |
602 |
"%lu: %s: overflow in the 'N' substitute flag", linenum, fname); |
601 |
s->n = nval; |
603 |
s->n = nval; |
602 |
p--; |
604 |
p = q; |
603 |
break; |
605 |
continue; |
604 |
case 'w': |
606 |
case 'w': |
605 |
p++; |
607 |
p++; |
606 |
#ifdef HISTORIC_PRACTICE |
608 |
#ifdef HISTORIC_PRACTICE |
Lines 610-636
Link Here
|
610 |
} |
612 |
} |
611 |
#endif |
613 |
#endif |
612 |
EATSPACE(); |
614 |
EATSPACE(); |
613 |
q = wfile; |
615 |
s->wfile = duptoeol(p, "w flag", NULL); |
614 |
eq = wfile + sizeof(wfile) - 1; |
616 |
if (!aflag && (s->wfd = open(s->wfile, |
615 |
while (*p) { |
|
|
616 |
if (*p == '\n') |
617 |
break; |
618 |
if (q >= eq) |
619 |
err(1, "wfile too long"); |
620 |
*q++ = *p++; |
621 |
} |
622 |
*q = '\0'; |
623 |
if (q == wfile) |
624 |
errx(1, "%lu: %s: no wfile specified", linenum, fname); |
625 |
s->wfile = strdup(wfile); |
626 |
if (!aflag && (s->wfd = open(wfile, |
627 |
O_WRONLY|O_APPEND|O_CREAT|O_TRUNC, |
617 |
O_WRONLY|O_APPEND|O_CREAT|O_TRUNC, |
628 |
DEFFILEMODE)) == -1) |
618 |
DEFFILEMODE)) == -1) |
629 |
err(1, "%s", wfile); |
619 |
err(1, "%s", s->wfile); |
630 |
return (p); |
620 |
return (p); |
631 |
default: |
621 |
default: |
632 |
errx(1, "%lu: %s: bad flag in substitute command: '%c'", |
622 |
errx(1, "%lu: %s: bad flag in substitute command: '%c' (%.10s)", |
633 |
linenum, fname, *p); |
623 |
linenum, fname, *p, p); |
634 |
break; |
624 |
break; |
635 |
} |
625 |
} |
636 |
p++; |
626 |
p++; |
Lines 640-647
Link Here
|
640 |
/* |
630 |
/* |
641 |
* Compile a translation set of strings into a lookup table. |
631 |
* Compile a translation set of strings into a lookup table. |
642 |
*/ |
632 |
*/ |
643 |
static char * |
633 |
static const char * |
644 |
compile_tr(char *p, struct s_tr **py) |
634 |
compile_tr(const char *p, struct s_tr **py) |
645 |
{ |
635 |
{ |
646 |
struct s_tr *y; |
636 |
struct s_tr *y; |
647 |
int i; |
637 |
int i; |
Lines 652-658
Link Here
|
652 |
mbstate_t mbs1, mbs2; |
642 |
mbstate_t mbs1, mbs2; |
653 |
|
643 |
|
654 |
if ((*py = y = malloc(sizeof(*y))) == NULL) |
644 |
if ((*py = y = malloc(sizeof(*y))) == NULL) |
655 |
err(1, NULL); |
645 |
err(1, "malloc"); |
656 |
y->multis = NULL; |
646 |
y->multis = NULL; |
657 |
y->nmultis = 0; |
647 |
y->nmultis = 0; |
658 |
|
648 |
|
Lines 672-682
Link Here
|
672 |
op = old; |
662 |
op = old; |
673 |
oldlen = mbsrtowcs(NULL, &op, 0, NULL); |
663 |
oldlen = mbsrtowcs(NULL, &op, 0, NULL); |
674 |
if (oldlen == (size_t)-1) |
664 |
if (oldlen == (size_t)-1) |
675 |
err(1, NULL); |
665 |
err(1, "mbsrtowcs"); |
676 |
np = new; |
666 |
np = new; |
677 |
newlen = mbsrtowcs(NULL, &np, 0, NULL); |
667 |
newlen = mbsrtowcs(NULL, &np, 0, NULL); |
678 |
if (newlen == (size_t)-1) |
668 |
if (newlen == (size_t)-1) |
679 |
err(1, NULL); |
669 |
err(1, "mbsrtowcs"); |
680 |
if (newlen != oldlen) |
670 |
if (newlen != oldlen) |
681 |
errx(1, "%lu: %s: transform strings are not the same length", |
671 |
errx(1, "%lu: %s: transform strings are not the same length", |
682 |
linenum, fname); |
672 |
linenum, fname); |
Lines 715-721
Link Here
|
715 |
y->multis = realloc(y->multis, |
705 |
y->multis = realloc(y->multis, |
716 |
(y->nmultis + 1) * sizeof(*y->multis)); |
706 |
(y->nmultis + 1) * sizeof(*y->multis)); |
717 |
if (y->multis == NULL) |
707 |
if (y->multis == NULL) |
718 |
err(1, NULL); |
708 |
err(1, "realloc"); |
719 |
i = y->nmultis++; |
709 |
i = y->nmultis++; |
720 |
y->multis[i].fromlen = oclen; |
710 |
y->multis[i].fromlen = oclen; |
721 |
memcpy(y->multis[i].from, op, oclen); |
711 |
memcpy(y->multis[i].from, op, oclen); |
Lines 733-756
Link Here
|
733 |
* Compile the text following an a or i command. |
723 |
* Compile the text following an a or i command. |
734 |
*/ |
724 |
*/ |
735 |
static char * |
725 |
static char * |
736 |
compile_text(void) |
726 |
compile_text(size_t *ptlen) |
737 |
{ |
727 |
{ |
738 |
int asize, esc_nl, size; |
728 |
int asize, esc_nl, size; |
739 |
char *text, *p, *op, *s; |
729 |
char *text, *s; |
740 |
char lbuf[_POSIX2_LINE_MAX + 1]; |
730 |
const char *p, *op; |
741 |
|
731 |
|
742 |
asize = 2 * _POSIX2_LINE_MAX + 1; |
732 |
asize = 2 * _POSIX2_LINE_MAX + 1; |
743 |
if ((text = malloc(asize)) == NULL) |
733 |
if ((text = malloc(asize)) == NULL) |
744 |
err(1, "malloc"); |
734 |
err(1, "malloc"); |
745 |
size = 0; |
735 |
size = 0; |
746 |
while (cu_fgets(lbuf, sizeof(lbuf), NULL)) { |
736 |
while ((p = cu_fgets(NULL))) { |
747 |
op = s = text + size; |
737 |
op = s = text + size; |
748 |
p = lbuf; |
738 |
EATSPACEN(); |
749 |
EATSPACE(); |
|
|
750 |
for (esc_nl = 0; *p != '\0'; p++) { |
739 |
for (esc_nl = 0; *p != '\0'; p++) { |
751 |
if (*p == '\\' && p[1] != '\0' && *++p == '\n') |
740 |
if (*p == '\\' && p[1] != '\0' && *++p == '\n') |
752 |
esc_nl = 1; |
741 |
esc_nl = 1; |
753 |
*s++ = *p; |
742 |
*s++ = *p; |
|
|
743 |
if (*p == '\n') |
744 |
break; |
754 |
} |
745 |
} |
755 |
size += s - op; |
746 |
size += s - op; |
756 |
if (!esc_nl) { |
747 |
if (!esc_nl) { |
Lines 764-772
Link Here
|
764 |
} |
755 |
} |
765 |
} |
756 |
} |
766 |
text[size] = '\0'; |
757 |
text[size] = '\0'; |
767 |
if ((p = realloc(text, size + 1)) == NULL) |
758 |
if ((text = realloc(text, size + 1)) == NULL) |
768 |
err(1, "realloc"); |
759 |
err(1, "realloc"); |
769 |
return (p); |
760 |
*ptlen = size; |
|
|
761 |
return (text); |
770 |
} |
762 |
} |
771 |
|
763 |
|
772 |
/* |
764 |
/* |
Lines 773-780
Link Here
|
773 |
* Get an address and return a pointer to the first character after |
765 |
* Get an address and return a pointer to the first character after |
774 |
* it. Fill the structure pointed to according to the address. |
766 |
* it. Fill the structure pointed to according to the address. |
775 |
*/ |
767 |
*/ |
776 |
static char * |
768 |
static const char * |
777 |
compile_addr(char *p, struct s_addr *a) |
769 |
compile_addr(const char *p, struct s_addr *a) |
778 |
{ |
770 |
{ |
779 |
char *end, re[_POSIX2_LINE_MAX + 1]; |
771 |
char *end, re[_POSIX2_LINE_MAX + 1]; |
780 |
int icase; |
772 |
int icase; |
Lines 828-849
Link Here
|
828 |
* Return a copy of all the characters up to \n or \0. |
820 |
* Return a copy of all the characters up to \n or \0. |
829 |
*/ |
821 |
*/ |
830 |
static char * |
822 |
static char * |
831 |
duptoeol(char *s, const char *ctype) |
823 |
duptoeol(const char *s, const char *ctype, size_t *ptlen) |
832 |
{ |
824 |
{ |
833 |
size_t len; |
825 |
size_t len; |
834 |
int ws; |
826 |
int ws; |
835 |
char *p, *start; |
827 |
char *p; |
|
|
828 |
const char *start; |
836 |
|
829 |
|
837 |
ws = 0; |
830 |
ws = 0; |
838 |
for (start = s; *s != '\0' && *s != '\n'; ++s) |
831 |
for (start = s; *s != '\0' && *s != '\n'; ++s) |
839 |
ws = isspace((unsigned char)*s); |
832 |
ws = isspace((unsigned char)*s); |
840 |
*s = '\0'; |
|
|
841 |
if (ws) |
833 |
if (ws) |
842 |
warnx("%lu: %s: whitespace after %s", linenum, fname, ctype); |
834 |
warnx("%lu: %s: whitespace after %s", linenum, fname, ctype); |
843 |
len = s - start + 1; |
835 |
len = s - start; |
844 |
if ((p = malloc(len)) == NULL) |
836 |
if ((p = malloc(len + 1)) == NULL) |
845 |
err(1, "malloc"); |
837 |
err(1, "malloc"); |
846 |
return (memmove(p, start, len)); |
838 |
memmove(p, start, len); |
|
|
839 |
p[len] = '\0'; |
840 |
if (ptlen != NULL) |
841 |
*ptlen = len; |
842 |
return p; |
847 |
} |
843 |
} |
848 |
|
844 |
|
849 |
/* |
845 |
/* |
Lines 854-860
Link Here
|
854 |
* TODO: Remove } nodes |
850 |
* TODO: Remove } nodes |
855 |
*/ |
851 |
*/ |
856 |
static void |
852 |
static void |
857 |
fixuplabel(struct s_command *cp, struct s_command *end) |
853 |
fixuplabel(struct s_command *cp, const struct s_command *end) |
858 |
{ |
854 |
{ |
859 |
|
855 |
|
860 |
for (; cp != end; cp = cp->next) |
856 |
for (; cp != end; cp = cp->next) |
Lines 871-877
Link Here
|
871 |
break; |
867 |
break; |
872 |
} |
868 |
} |
873 |
if ((cp->u.c = findlabel(cp->t)) == NULL) |
869 |
if ((cp->u.c = findlabel(cp->t)) == NULL) |
874 |
errx(1, "%lu: %s: undefined label '%s'", linenum, fname, cp->t); |
870 |
errx(1, "%lu: %s: %c: undefined label '%s'", linenum, fname, cp->code, cp->t); |
875 |
free(cp->t); |
871 |
free(cp->t); |
876 |
break; |
872 |
break; |
877 |
case '{': |
873 |
case '{': |
Lines 911-923
Link Here
|
911 |
* list cp. L is excluded from the search. Return NULL if not found. |
907 |
* list cp. L is excluded from the search. Return NULL if not found. |
912 |
*/ |
908 |
*/ |
913 |
static struct s_command * |
909 |
static struct s_command * |
914 |
findlabel(char *name) |
910 |
findlabel(const char *name) |
915 |
{ |
911 |
{ |
916 |
struct labhash *lh; |
912 |
struct labhash *lh; |
917 |
u_char *p; |
913 |
const u_char *p; |
918 |
u_int h, c; |
914 |
u_int h, c; |
919 |
|
915 |
|
920 |
for (h = 0, p = (u_char *)name; (c = *p) != 0; p++) |
916 |
for (h = 0, p = (const u_char *)name; (c = *p) != 0; p++) |
921 |
h = (h << 5) + h + c; |
917 |
h = (h << 5) + h + c; |
922 |
for (lh = labels[h & LHMASK]; lh != NULL; lh = lh->lh_next) { |
918 |
for (lh = labels[h & LHMASK]; lh != NULL; lh = lh->lh_next) { |
923 |
if (lh->lh_hash == h && strcmp(name, lh->lh_cmd->t) == 0) { |
919 |
if (lh->lh_hash == h && strcmp(name, lh->lh_cmd->t) == 0) { |