View | Details | Raw Unified | Return to bug 195929 | Differences between
and this patch

Collapse All | Expand All

(-)Makefile (-1 / +1 lines)
Lines 6-12 Link Here
6
PROG=	sed
6
PROG=	sed
7
SRCS=	compile.c main.c misc.c process.c
7
SRCS=	compile.c main.c misc.c process.c
8
8
9
WARNS?=	2
9
WARNS?=	5
10
10
11
.if ${MK_TESTS} != "no"
11
.if ${MK_TESTS} != "no"
12
SUBDIR+= tests
12
SUBDIR+= tests
(-)compile.c (-90 / +104 lines)
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       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 */
165
	int stackdepth = 0;
162
166
163
	stack = 0;
167
	stack = NULL;
164
	for (;;) {
168
	for (;;) {
165
		if ((p = cu_fgets(lbuf, sizeof(lbuf), NULL)) == NULL) {
169
		if ((p = cu_fgets(NULL)) == NULL) {
166
			if (stack != 0)
170
			if (stack != NULL)
167
				errx(1, "%lu: %s: unexpected EOF (pending }'s)",
171
				errx(1, "%lu: %s: unexpected EOF (pending }'s)",
168
							linenum, fname);
172
							linenum, fname);
169
			return (link);
173
			return (link);
170
		}
174
		}
171
175
172
semicolon:	EATSPACE();
176
semicolon:	EATSPACEN();
173
		if (p) {
177
		switch (*p) {
174
			if (*p == '#' || *p == '\0')
178
		case '#': case '\0': case '\n':
175
				continue;
179
			continue;	/* to next command-unit */
176
			else if (*p == ';') {
180
		case ';':
177
				p++;
181
			p++;
178
				goto semicolon;
182
			goto semicolon;
179
			}
180
		}
183
		}
184
181
		if ((*link = cmd = malloc(sizeof(struct s_command))) == NULL)
185
		if ((*link = cmd = malloc(sizeof(struct s_command))) == NULL)
182
			err(1, "malloc");
186
			err(1, "malloc");
183
		link = &cmd->next;
187
		link = &cmd->next;
Lines 208-214 Link Here
208
			cmd->a1 = cmd->a2 = 0;
212
			cmd->a1 = cmd->a2 = 0;
209
213
210
nonsel:		/* Now parse the command */
214
nonsel:		/* Now parse the command */
211
		if (!*p)
215
		if (*p == '\0' || *p == '\n')
212
			errx(1, "%lu: %s: command expected", linenum, fname);
216
			errx(1, "%lu: %s: command expected", linenum, fname);
213
		cmd->code = *p;
217
		cmd->code = *p;
214
		for (fp = cmd_fmts; fp->code; fp++)
218
		for (fp = cmd_fmts; fp->code; fp++)
Lines 215-221 Link Here
215
			if (fp->code == *p)
219
			if (fp->code == *p)
216
				break;
220
				break;
217
		if (!fp->code)
221
		if (!fp->code)
218
			errx(1, "%lu: %s: invalid command code %c", linenum, fname, *p);
222
			errx(1, "%lu: %s: invalid command code %c (%s)", linenum, fname, *p, p);
219
		if (naddr > fp->naddr)
223
		if (naddr > fp->naddr)
220
			errx(1,
224
			errx(1,
221
				"%lu: %s: command %c expects up to %d address(es), found %d",
225
				"%lu: %s: command %c expects up to %d address(es), found %d",
Lines 228-238 Link Here
228
			goto nonsel;
232
			goto nonsel;
229
		case GROUP:			/* { */
233
		case GROUP:			/* { */
230
			p++;
234
			p++;
231
			EATSPACE();
235
			EATSPACEN();
232
			cmd->next = stack;
236
			cmd->next = stack;
233
			stack = cmd;
237
			stack = cmd;
234
			link = &cmd->u.c;
238
			link = &cmd->u.c;
235
			if (*p)
239
			if (*p != '\0' && *p != '\n')
236
				goto semicolon;
240
				goto semicolon;
237
			break;
241
			break;
238
		case ENDGROUP:
242
		case ENDGROUP:
Lines 241-247 Link Here
241
			 * group is really just a noop.
245
			 * group is really just a noop.
242
			 */
246
			 */
243
			cmd->nonsel = 1;
247
			cmd->nonsel = 1;
244
			if (stack == 0)
248
			if (stack == NULL)
245
				errx(1, "%lu: %s: unexpected }", linenum, fname);
249
				errx(1, "%lu: %s: unexpected }", linenum, fname);
246
			cmd2 = stack;
250
			cmd2 = stack;
247
			stack = cmd2->next;
251
			stack = cmd2->next;
Lines 249-261 Link Here
249
			/*FALLTHROUGH*/
253
			/*FALLTHROUGH*/
250
		case EMPTY:		/* d D g G h H l n N p P q x = \0 */
254
		case EMPTY:		/* d D g G h H l n N p P q x = \0 */
251
			p++;
255
			p++;
252
			EATSPACE();
256
			EATSPACEN();
253
			if (*p == ';') {
257
			if (*p == ';') {
254
				p++;
258
				p++;
255
				link = &cmd->next;
259
				link = &cmd->next;
256
				goto semicolon;
260
				goto semicolon;
257
			}
261
			}
258
			if (*p)
262
			if (*p != '\0' && *p != '\n')
259
				errx(1, "%lu: %s: extra characters at the end of %c command",
263
				errx(1, "%lu: %s: extra characters at the end of %c command",
260
						linenum, fname, cmd->code);
264
						linenum, fname, cmd->code);
261
			break;
265
			break;
Lines 266-277 Link Here
266
				errx(1,
270
				errx(1,
267
"%lu: %s: command %c expects \\ followed by text", linenum, fname, cmd->code);
271
"%lu: %s: command %c expects \\ followed by text", linenum, fname, cmd->code);
268
			p++;
272
			p++;
269
			EATSPACE();
273
			EATSPACEN();
270
			if (*p)
274
			if (*p != '\n')
271
				errx(1,
275
				errx(1,
272
				"%lu: %s: extra characters after \\ at the end of %c command",
276
				"%lu: %s: extra characters (%c) after \\ at the end of %c command",
273
				linenum, fname, cmd->code);
277
				linenum, fname, *p, cmd->code);
274
			cmd->t = compile_text();
278
			cmd->t = compile_text(&cmd->tlen);
275
			break;
279
			break;
276
		case COMMENT:			/* \0 # */
280
		case COMMENT:			/* \0 # */
277
			break;
281
			break;
Lines 280-289 Link Here
280
			EATSPACE();
284
			EATSPACE();
281
			if (*p == '\0')
285
			if (*p == '\0')
282
				errx(1, "%lu: %s: filename expected", linenum, fname);
286
				errx(1, "%lu: %s: filename expected", linenum, fname);
283
			cmd->t = duptoeol(p, "w command");
287
			cmd->t = duptoeol(p, "w command", &cmd->tlen);
284
			if (aflag)
288
			if (aflag)
285
				cmd->u.fd = -1;
289
				cmd->u.fd = -1;
286
			else if ((cmd->u.fd = open(p,
290
			else if ((cmd->u.fd = open(cmd->t,
287
			    O_WRONLY|O_APPEND|O_CREAT|O_TRUNC,
291
			    O_WRONLY|O_APPEND|O_CREAT|O_TRUNC,
288
			    DEFFILEMODE)) == -1)
292
			    DEFFILEMODE)) == -1)
289
				err(1, "%s", p);
293
				err(1, "%s", p);
Lines 294-320 Link Here
294
			if (*p == '\0')
298
			if (*p == '\0')
295
				errx(1, "%lu: %s: filename expected", linenum, fname);
299
				errx(1, "%lu: %s: filename expected", linenum, fname);
296
			else
300
			else
297
				cmd->t = duptoeol(p, "read command");
301
				cmd->t = duptoeol(p, "read command", &cmd->tlen);
298
			break;
302
			break;
299
		case BRANCH:			/* b t */
303
		case BRANCH:			/* b t */
300
			p++;
304
			p++;
301
			EATSPACE();
305
			EATSPACEN();
302
			if (*p == '\0')
306
			if (*p == '\0' || *p == '\n')
303
				cmd->t = NULL;
307
				cmd->t = NULL;
304
			else
308
			else
305
				cmd->t = duptoeol(p, "branch");
309
				cmd->t = duptoeol(p, "branch", &cmd->tlen);
306
			break;
310
			break;
307
		case LABEL:			/* : */
311
		case LABEL:			/* : */
308
			p++;
312
			p++;
309
			EATSPACE();
313
			EATSPACE();
310
			cmd->t = duptoeol(p, "label");
314
			cmd->t = duptoeol(p, "label", &cmd->tlen);
311
			if (strlen(p) == 0)
315
			if (cmd->t[0] == '\0')
312
				errx(1, "%lu: %s: empty label", linenum, fname);
316
				errx(1, "%lu: %s: empty label", linenum, fname);
313
			enterlabel(cmd);
317
			enterlabel(cmd);
314
			break;
318
			break;
315
		case SUBST:			/* s */
319
		case SUBST:			/* s */
316
			p++;
320
			p++;
317
			if (*p == '\0' || *p == '\\')
321
			if (*p == '\0' || *p == '\\' || *p == '\n')
318
				errx(1,
322
				errx(1,
319
"%lu: %s: substitute pattern can not be delimited by newline or backslash",
323
"%lu: %s: substitute pattern can not be delimited by newline or backslash",
320
					linenum, fname);
324
					linenum, fname);
Lines 339-345 Link Here
339
				cmd->u.s->re = NULL;
343
				cmd->u.s->re = NULL;
340
			else
344
			else
341
				cmd->u.s->re = compile_re(re, cmd->u.s->icase);
345
				cmd->u.s->re = compile_re(re, cmd->u.s->icase);
342
			EATSPACE();
343
			if (*p == ';') {
346
			if (*p == ';') {
344
				p++;
347
				p++;
345
				link = &cmd->next;
348
				link = &cmd->next;
Lines 372-379 Link Here
372
 * in the case of a non-terminated string.  The character array d is filled
375
 * in the case of a non-terminated string.  The character array d is filled
373
 * with the processed string.
376
 * with the processed string.
374
 */
377
 */
375
static char *
378
static const char *
376
compile_delimited(char *p, char *d, int is_tr)
379
compile_delimited(const char *p, char *d, int is_tr)
377
{
380
{
378
	char c;
381
	char c;
379
382
Lines 416-425 Link Here
416
419
417
/* compile_ccl: expand a POSIX character class */
420
/* compile_ccl: expand a POSIX character class */
418
static char *
421
static char *
419
compile_ccl(char **sp, char *t)
422
compile_ccl(const char **sp, char *t)
420
{
423
{
421
	int c, d;
424
	int c, d;
422
	char *s = *sp;
425
	const char *s = *sp;
423
426
424
	*t++ = *s++;
427
	*t++ = *s++;
425
	if (*s == '^')
428
	if (*s == '^')
Lines 442-448 Link Here
442
 * Cflags are passed to regcomp.
445
 * Cflags are passed to regcomp.
443
 */
446
 */
444
static regex_t *
447
static regex_t *
445
compile_re(char *re, int case_insensitive)
448
compile_re(const char *re, int case_insensitive)
446
{
449
{
447
	regex_t *rep;
450
	regex_t *rep;
448
	int eval, flags;
451
	int eval, flags;
Lines 466-479 Link Here
466
 * point to a saved copy of it.  Nsub is the number of parenthesized regular
469
 * point to a saved copy of it.  Nsub is the number of parenthesized regular
467
 * expressions.
470
 * expressions.
468
 */
471
 */
469
static char *
472
static const char *
470
compile_subst(char *p, struct s_subst *s)
473
compile_subst(const char *p, struct s_subst *s)
471
{
474
{
472
	static char lbuf[_POSIX2_LINE_MAX + 1];
473
	int asize, size;
475
	int asize, size;
474
	u_char ref;
476
	u_char ref;
475
	char c, *text, *op, *sp;
477
	char c, *text, *op, *sp;
476
	int more = 1, sawesc = 0;
478
	int more = 0, sawesc = 0;
477
479
478
	c = *p++;			/* Terminator character */
480
	c = *p++;			/* Terminator character */
479
	if (c == '\0')
481
	if (c == '\0')
Lines 487-493 Link Here
487
	size = 0;
489
	size = 0;
488
	do {
490
	do {
489
		op = sp = text + size;
491
		op = sp = text + size;
490
		for (; *p; p++) {
492
		for (; *p != '\0' && *p != '\n'; p++) {
491
			if (*p == '\\' || sawesc) {
493
			if (*p == '\\' || sawesc) {
492
				/*
494
				/*
493
				 * If this is a continuation from the last
495
				 * If this is a continuation from the last
Lines 509-515 Link Here
509
					 */
511
					 */
510
					sawesc = 1;
512
					sawesc = 1;
511
					p--;
513
					p--;
512
					continue;
514
					break;
515
				} else if (*p == '\n') {
516
					*sp++ = '\n';
517
					break;
513
				} else if (strchr("123456789", *p) != NULL) {
518
				} else if (strchr("123456789", *p) != NULL) {
514
					*sp++ = '\\';
519
					*sp++ = '\\';
515
					ref = *p - '0';
520
					ref = *p - '0';
Lines 522-530 Link Here
522
				} else if (*p == '&' || *p == '\\')
527
				} else if (*p == '&' || *p == '\\')
523
					*sp++ = '\\';
528
					*sp++ = '\\';
524
			} else if (*p == c) {
529
			} else if (*p == c) {
525
				if (*++p == '\0' && more) {
530
				if ((*++p == '\0' || *p == '\n') && more) {
526
					if (cu_fgets(lbuf, sizeof(lbuf), &more))
531
					const char *nextp;
527
						p = lbuf;
532
533
					nextp = cu_fgets(&more);
534
					if (nextp != NULL)
535
						p = nextp;
528
				}
536
				}
529
				*sp++ = '\0';
537
				*sp++ = '\0';
530
				size += sp - op;
538
				size += sp - op;
Lines 532-537 Link Here
532
					err(1, "realloc");
540
					err(1, "realloc");
533
				return (p);
541
				return (p);
534
			} else if (*p == '\n') {
542
			} else if (*p == '\n') {
543
				break;
535
				errx(1,
544
				errx(1,
536
"%lu: %s: unescaped newline inside substitute pattern", linenum, fname);
545
"%lu: %s: unescaped newline inside substitute pattern", linenum, fname);
537
				/* NOTREACHED */
546
				/* NOTREACHED */
Lines 544-550 Link Here
544
			if ((text = realloc(text, asize)) == NULL)
553
			if ((text = realloc(text, asize)) == NULL)
545
				err(1, "realloc");
554
				err(1, "realloc");
546
		}
555
		}
547
	} while (cu_fgets(p = lbuf, sizeof(lbuf), &more));
556
	} while ((p = cu_fgets(&more)));
548
	errx(1, "%lu: %s: unterminated substitute in regular expression",
557
	errx(1, "%lu: %s: unterminated substitute in regular expression",
549
			linenum, fname);
558
			linenum, fname);
550
	/* NOTREACHED */
559
	/* NOTREACHED */
Lines 553-560 Link Here
553
/*
562
/*
554
 * Compile the flags of the s command
563
 * Compile the flags of the s command
555
 */
564
 */
556
static char *
565
static const char *
557
compile_flags(char *p, struct s_subst *s)
566
compile_flags(const char *p, struct s_subst *s)
558
{
567
{
559
	int gn;			/* True if we have seen g or n */
568
	int gn;			/* True if we have seen g or n */
560
	unsigned long nval;
569
	unsigned long nval;
Lines 566-572 Link Here
566
	s->wfd = -1;
575
	s->wfd = -1;
567
	s->icase = 0;
576
	s->icase = 0;
568
	for (gn = 0;;) {
577
	for (gn = 0;;) {
569
		EATSPACE();			/* EXTENSION */
578
		EATSPACEN();			/* EXTENSION */
570
		switch (*p) {
579
		switch (*p) {
571
		case 'g':
580
		case 'g':
572
			if (gn)
581
			if (gn)
Lines 594-605 Link Here
594
"%lu: %s: more than one number or 'g' in substitute flags", linenum, fname);
603
"%lu: %s: more than one number or 'g' in substitute flags", linenum, fname);
595
			gn = 1;
604
			gn = 1;
596
			errno = 0;
605
			errno = 0;
597
			nval = strtol(p, &p, 10);
606
			nval = strtol(p, &q, 10);
598
			if (errno == ERANGE || nval > INT_MAX)
607
			if (errno == ERANGE || nval > INT_MAX)
599
				errx(1,
608
				errx(1,
600
"%lu: %s: overflow in the 'N' substitute flag", linenum, fname);
609
"%lu: %s: overflow in the 'N' substitute flag", linenum, fname);
601
			s->n = nval;
610
			s->n = nval;
602
			p--;
611
			p = q - 1;
603
			break;
612
			break;
604
		case 'w':
613
		case 'w':
605
			p++;
614
			p++;
Lines 637-644 Link Here
637
/*
646
/*
638
 * Compile a translation set of strings into a lookup table.
647
 * Compile a translation set of strings into a lookup table.
639
 */
648
 */
640
static char *
649
static const char *
641
compile_tr(char *p, struct s_tr **py)
650
compile_tr(const char *p, struct s_tr **py)
642
{
651
{
643
	struct s_tr *y;
652
	struct s_tr *y;
644
	int i;
653
	int i;
Lines 730-753 Link Here
730
 * Compile the text following an a or i command.
739
 * Compile the text following an a or i command.
731
 */
740
 */
732
static char *
741
static char *
733
compile_text(void)
742
compile_text(size_t *ptlen)
734
{
743
{
735
	int asize, esc_nl, size;
744
	int asize, esc_nl, size;
736
	char *text, *p, *op, *s;
745
	char *text, *s;
737
	char lbuf[_POSIX2_LINE_MAX + 1];
746
	const char *p, *op;
738
747
739
	asize = 2 * _POSIX2_LINE_MAX + 1;
748
	asize = 2 * _POSIX2_LINE_MAX + 1;
740
	if ((text = malloc(asize)) == NULL)
749
	if ((text = malloc(asize)) == NULL)
741
		err(1, "malloc");
750
		err(1, "malloc");
742
	size = 0;
751
	size = 0;
743
	while (cu_fgets(lbuf, sizeof(lbuf), NULL)) {
752
	while ((p = cu_fgets(NULL))) {
744
		op = s = text + size;
753
		op = s = text + size;
745
		p = lbuf;
746
		EATSPACE();
754
		EATSPACE();
747
		for (esc_nl = 0; *p != '\0'; p++) {
755
		for (esc_nl = 0; *p != '\0'; p++) {
748
			if (*p == '\\' && p[1] != '\0' && *++p == '\n')
756
			if (*p == '\\' && p[1] != '\0' && *++p == '\n')
749
				esc_nl = 1;
757
				esc_nl = 1;
750
			*s++ = *p;
758
			*s++ = *p;
759
			if (*p == '\n')
760
				break;
751
		}
761
		}
752
		size += s - op;
762
		size += s - op;
753
		if (!esc_nl) {
763
		if (!esc_nl) {
Lines 761-769 Link Here
761
		}
771
		}
762
	}
772
	}
763
	text[size] = '\0';
773
	text[size] = '\0';
764
	if ((p = realloc(text, size + 1)) == NULL)
774
	if ((text = realloc(text, size + 1)) == NULL)
765
		err(1, "realloc");
775
		err(1, "realloc");
766
	return (p);
776
	*ptlen = size;
777
	return (text);
767
}
778
}
768
779
769
/*
780
/*
Lines 770-777 Link Here
770
 * Get an address and return a pointer to the first character after
781
 * Get an address and return a pointer to the first character after
771
 * it.  Fill the structure pointed to according to the address.
782
 * it.  Fill the structure pointed to according to the address.
772
 */
783
 */
773
static char *
784
static const char *
774
compile_addr(char *p, struct s_addr *a)
785
compile_addr(const char *p, struct s_addr *a)
775
{
786
{
776
	char *end, re[_POSIX2_LINE_MAX + 1];
787
	char *end, re[_POSIX2_LINE_MAX + 1];
777
	int icase;
788
	int icase;
Lines 825-846 Link Here
825
 *	Return a copy of all the characters up to \n or \0.
836
 *	Return a copy of all the characters up to \n or \0.
826
 */
837
 */
827
static char *
838
static char *
828
duptoeol(char *s, const char *ctype)
839
duptoeol(const char *s, const char *ctype, size_t *ptlen)
829
{
840
{
830
	size_t len;
841
	size_t len;
831
	int ws;
842
	int ws;
832
	char *p, *start;
843
	char *p;
844
	const char *start;
833
845
834
	ws = 0;
846
	ws = 0;
835
	for (start = s; *s != '\0' && *s != '\n'; ++s)
847
	for (start = s; *s != '\0' && *s != '\n'; ++s)
836
		ws = isspace((unsigned char)*s);
848
		ws = isspace((unsigned char)*s);
837
	*s = '\0';
838
	if (ws)
849
	if (ws)
839
		warnx("%lu: %s: whitespace after %s", linenum, fname, ctype);
850
		warnx("%lu: %s: whitespace after %s", linenum, fname, ctype);
840
	len = s - start + 1;
851
	len = s - start;
841
	if ((p = malloc(len)) == NULL)
852
	if ((p = malloc(len + 1)) == NULL)
842
		err(1, "malloc");
853
		err(1, "malloc");
843
	return (memmove(p, start, len));
854
	memmove(p, start, len);
855
	p[len] = '\0';
856
	*ptlen = len;
857
	return p;
844
}
858
}
845
859
846
/*
860
/*
Lines 851-857 Link Here
851
 * TODO: Remove } nodes
865
 * TODO: Remove } nodes
852
 */
866
 */
853
static void
867
static void
854
fixuplabel(struct s_command *cp, struct s_command *end)
868
fixuplabel(struct s_command *cp, const struct s_command *end)
855
{
869
{
856
870
857
	for (; cp != end; cp = cp->next)
871
	for (; cp != end; cp = cp->next)
Lines 868-874 Link Here
868
				break;
882
				break;
869
			}
883
			}
870
			if ((cp->u.c = findlabel(cp->t)) == NULL)
884
			if ((cp->u.c = findlabel(cp->t)) == NULL)
871
				errx(1, "%lu: %s: undefined label '%s'", linenum, fname, cp->t);
885
				errx(1, "%lu: %s: %c: undefined label '%s'", linenum, fname, cp->code, cp->t);
872
			free(cp->t);
886
			free(cp->t);
873
			break;
887
			break;
874
		case '{':
888
		case '{':
Lines 908-914 Link Here
908
 * list cp.  L is excluded from the search.  Return NULL if not found.
922
 * list cp.  L is excluded from the search.  Return NULL if not found.
909
 */
923
 */
910
static struct s_command *
924
static struct s_command *
911
findlabel(char *name)
925
findlabel(const char *name)
912
{
926
{
913
	struct labhash *lh;
927
	struct labhash *lh;
914
	u_char *p;
928
	u_char *p;
(-)defs.h (+1 lines)
Lines 94-99 Link Here
94
	struct s_addr *a1, *a2;			/* Start and end address */
94
	struct s_addr *a1, *a2;			/* Start and end address */
95
	u_long startline;			/* Start line number or zero */
95
	u_long startline;			/* Start line number or zero */
96
	char *t;				/* Text for : a c i r w */
96
	char *t;				/* Text for : a c i r w */
97
	size_t tlen;				/* Length of the text */
97
	union {
98
	union {
98
		struct s_command *c;		/* Command(s) for b t { */
99
		struct s_command *c;		/* Command(s) for b t { */
99
		struct s_subst *s;		/* Substitute command */
100
		struct s_subst *s;		/* Substitute command */
(-)extern.h (-2 / +2 lines)
Lines 48-56 Link Here
48
void	 cfclose(struct s_command *, struct s_command *);
48
void	 cfclose(struct s_command *, struct s_command *);
49
void	 compile(void);
49
void	 compile(void);
50
void	 cspace(SPACE *, const char *, size_t, enum e_spflag);
50
void	 cspace(SPACE *, const char *, size_t, enum e_spflag);
51
char	*cu_fgets(char *, int, int *);
51
const char	*cu_fgets(int *);
52
int	 mf_fgets(SPACE *, enum e_spflag);
52
int	 mf_fgets(SPACE *, enum e_spflag);
53
int	 lastline(void);
53
int	 lastline(void);
54
void	 process(void);
54
void	 process(void);
55
void	 resetstate(void);
55
void	 resetstate(void);
56
char	*strregerror(int, regex_t *);
56
const char	*strregerror(int, const regex_t *);
(-)main.c (-39 / +32 lines)
Lines 73-79 Link Here
73
struct s_compunit {
73
struct s_compunit {
74
	struct s_compunit *next;
74
	struct s_compunit *next;
75
	enum e_cut {CU_FILE, CU_STRING} type;
75
	enum e_cut {CU_FILE, CU_STRING} type;
76
	char *s;			/* Pointer to string or fname */
76
	const char *s;			/* Pointer to string or fname */
77
};
77
};
78
78
79
/*
79
/*
Lines 86-92 Link Here
86
 * Linked list of files to be processed
86
 * Linked list of files to be processed
87
 */
87
 */
88
struct s_flist {
88
struct s_flist {
89
	char *fname;
89
	const char *fname;
90
	struct s_flist *next;
90
	struct s_flist *next;
91
};
91
};
92
92
Lines 117-124 Link Here
117
static const char *inplace;	/* Inplace edit file extension. */
117
static const char *inplace;	/* Inplace edit file extension. */
118
u_long linenum;
118
u_long linenum;
119
119
120
static void add_compunit(enum e_cut, char *);
120
static void add_compunit(enum e_cut, const char *);
121
static void add_file(char *);
121
static void add_file(const char *);
122
static void usage(void);
122
static void usage(void);
123
123
124
int
124
int
Lines 214-227 Link Here
214
 * Like fgets, but go through the chain of compilation units chaining them
209
 * Like fgets, but go through the chain of compilation units chaining them
215
 * together.  Empty strings and files are ignored.
210
 * together.  Empty strings and files are ignored.
216
 */
211
 */
217
char *
212
const char *
218
cu_fgets(char *buf, int n, int *more)
213
cu_fgets(int *more)
219
{
214
{
220
	static enum {ST_EOF, ST_FILE, ST_STRING} state = ST_EOF;
215
	static enum {ST_EOF, ST_FILE, ST_STRING} state = ST_EOF;
221
	static FILE *f;		/* Current open file */
216
	static FILE *f;		/* Current open file */
222
	static char *s;		/* Current pointer inside string */
217
	static const char *s;	/* Current pointer inside string */
223
	static char string_ident[30];
218
	static char string_ident[30], *lastresult;
219
	static size_t lastsize;
224
	char *p;
220
	char *p;
221
	const char *start;
225
222
226
again:
223
again:
227
	switch (state) {
224
	switch (state) {
Lines 251-264 Link Here
251
			goto again;
248
			goto again;
252
		}
249
		}
253
	case ST_FILE:
250
	case ST_FILE:
254
		if ((p = fgets(buf, n, f)) != NULL) {
251
		p = lastresult;
252
		if (getline(&p, &lastsize, f) != -1) {
255
			linenum++;
253
			linenum++;
256
			if (linenum == 1 && buf[0] == '#' && buf[1] == 'n')
254
			if (linenum == 1 && p[0] == '#' && p[1] == 'n')
257
				nflag = 1;
255
				nflag = 1;
258
			if (more != NULL)
256
			if (more != NULL)
259
				*more = !feof(f);
257
				*more = !feof(f);
260
			return (p);
258
			return (lastresult = p);
261
		}
259
		} else if (ferror(f))
260
			err(1, "%s", script->s);
262
		script = script->next;
261
		script = script->next;
263
		(void)fclose(f);
262
		(void)fclose(f);
264
		state = ST_EOF;
263
		state = ST_EOF;
Lines 266-304 Link Here
266
	case ST_STRING:
265
	case ST_STRING:
267
		if (linenum == 0 && s[0] == '#' && s[1] == 'n')
266
		if (linenum == 0 && s[0] == '#' && s[1] == 'n')
268
			nflag = 1;
267
			nflag = 1;
269
		p = buf;
268
		else if (s[0] == '\0') {
269
			state = ST_EOF;
270
			script = script->next;
271
			goto again;
272
		}
273
		start = s;
270
		for (;;) {
274
		for (;;) {
271
			if (n-- <= 1) {
272
				*p = '\0';
273
				linenum++;
274
				if (more != NULL)
275
					*more = 1;
276
				return (buf);
277
			}
278
			switch (*s) {
275
			switch (*s) {
279
			case '\0':
276
			case '\0':
280
				state = ST_EOF;
277
				state = ST_EOF;
281
				if (s == script->s) {
278
				script = script->next;
282
					script = script->next;
279
				/* FALLTHROUGH */
283
					goto again;
284
				} else {
285
					script = script->next;
286
					*p = '\0';
287
					linenum++;
288
					if (more != NULL)
289
						*more = 0;
290
					return (buf);
291
				}
292
			case '\n':
280
			case '\n':
293
				*p++ = '\n';
294
				*p = '\0';
295
				s++;
281
				s++;
296
				linenum++;
282
				linenum++;
297
				if (more != NULL)
283
				if (more != NULL)
298
					*more = 0;
284
					*more = 0;
299
				return (buf);
285
				return (start);
300
			default:
286
			default:
301
				*p++ = *s++;
287
				s++;
302
			}
288
			}
303
		}
289
		}
304
	}
290
	}
Lines 400-412 Link Here
400
				    sizeof(oldfname));
386
				    sizeof(oldfname));
401
				len = strlcat(oldfname, inplace,
387
				len = strlcat(oldfname, inplace,
402
				    sizeof(oldfname));
388
				    sizeof(oldfname));
403
				if (len > sizeof(oldfname))
389
				if ((size_t)len > sizeof(oldfname))
404
					errx(1, "%s: name too long", fname);
390
					errx(1, "%s: name too long", fname);
405
			}
391
			}
406
			len = snprintf(tmpfname, sizeof(tmpfname),
392
			len = snprintf(tmpfname, sizeof(tmpfname),
407
			    "%s/.!%ld!%s", dirname(fname), (long)getpid(),
393
			    "%s/.!%ld!%s", dirname(fname), (long)getpid(),
408
			    basename(fname));
394
			    basename(fname));
409
			if (len >= sizeof(tmpfname))
395
			if (len < 0)
396
				err(1, "snprintf");
397
			if ((size_t)len >= sizeof(tmpfname))
410
				errx(1, "%s: name too long", fname);
398
				errx(1, "%s: name too long", fname);
411
			unlink(tmpfname);
399
			unlink(tmpfname);
412
			if ((outfile = fopen(tmpfname, "w")) == NULL)
400
			if ((outfile = fopen(tmpfname, "w")) == NULL)
Lines 452-458 Link Here
452
 * Add a compilation unit to the linked list
440
 * Add a compilation unit to the linked list
453
 */
441
 */
454
static void
442
static void
455
add_compunit(enum e_cut type, char *s)
443
add_compunit(enum e_cut type, const char *s)
456
{
444
{
457
	struct s_compunit *cu;
445
	struct s_compunit *cu;
458
446
Lines 469-475 Link Here
469
 * Add a file to the linked list
457
 * Add a file to the linked list
470
 */
458
 */
471
static void
459
static void
472
add_file(char *s)
460
add_file(const char *s)
473
{
461
{
474
	struct s_flist *fp;
462
	struct s_flist *fp;
475
463
(-)misc.c (-2 / +2 lines)
Lines 55-62 Link Here
55
 * because of the silly semantics of regerror (we can never know the size of
55
 * because of the silly semantics of regerror (we can never know the size of
56
 * the buffer).
56
 * the buffer).
57
 */
57
 */
58
char *
58
const char *
59
strregerror(int errcode, regex_t *preg)
59
strregerror(int errcode, const regex_t *preg)
60
{
60
{
61
	static char *oe;
61
	static char *oe;
62
	size_t s;
62
	size_t s;
(-)process.c (-13 / +13 lines)
Lines 67-78 Link Here
67
#define	hsl		HS.len
67
#define	hsl		HS.len
68
68
69
static __inline int	 applies(struct s_command *);
69
static __inline int	 applies(struct s_command *);
70
static void		 do_tr(struct s_tr *);
70
static void		 do_tr(const struct s_tr *);
71
static void		 flush_appends(void);
71
static void		 flush_appends(void);
72
static void		 lputs(char *, size_t);
72
static void		 lputs(const char *, size_t);
73
static __inline int	 regexec_e(regex_t *, const char *, int, int, size_t);
73
static __inline int	 regexec_e(const regex_t *, const char *, int, int, size_t);
74
static void		 regsub(SPACE *, char *, char *);
74
static void		 regsub(SPACE *, const char *, const char *);
75
static int		 substitute(struct s_command *);
75
static int		 substitute(const struct s_command *);
76
76
77
struct s_appends *appends;	/* Array of pointers to strings to append. */
77
struct s_appends *appends;	/* Array of pointers to strings to append. */
78
static int appendx;		/* Index into appends array. */
78
static int appendx;		/* Index into appends array. */
Lines 81-87 Link Here
81
static int lastaddr;		/* Set by applies if last address of a range. */
81
static int lastaddr;		/* Set by applies if last address of a range. */
82
static int sdone;		/* If any substitutes since last line input. */
82
static int sdone;		/* If any substitutes since last line input. */
83
				/* Iov structure for 'w' commands. */
83
				/* Iov structure for 'w' commands. */
84
static regex_t *defpreg;
84
static const regex_t *defpreg;
85
size_t maxnsub;
85
size_t maxnsub;
86
regmatch_t *match;
86
regmatch_t *match;
87
87
Lines 119-125 Link Here
119
						err(1, "realloc");
119
						err(1, "realloc");
120
				appends[appendx].type = AP_STRING;
120
				appends[appendx].type = AP_STRING;
121
				appends[appendx].s = cp->t;
121
				appends[appendx].s = cp->t;
122
				appends[appendx].len = strlen(cp->t);
122
				appends[appendx].len = cp->tlen;
123
				appendx++;
123
				appendx++;
124
				break;
124
				break;
125
			case 'b':
125
			case 'b':
Lines 209-215 Link Here
209
						err(1, "realloc");
209
						err(1, "realloc");
210
				appends[appendx].type = AP_FILE;
210
				appends[appendx].type = AP_FILE;
211
				appends[appendx].s = cp->t;
211
				appends[appendx].s = cp->t;
212
				appends[appendx].len = strlen(cp->t);
212
				appends[appendx].len = cp->tlen;
213
				appendx++;
213
				appendx++;
214
				break;
214
				break;
215
			case 's':
215
			case 's':
Lines 365-371 Link Here
365
 *	and then swap them.
365
 *	and then swap them.
366
 */
366
 */
367
static int
367
static int
368
substitute(struct s_command *cp)
368
substitute(const struct s_command *cp)
369
{
369
{
370
	SPACE tspace;
370
	SPACE tspace;
371
	regex_t *re;
371
	regex_t *re;
Lines 476-482 Link Here
476
 *	Perform translation ('y' command) in the pattern space.
476
 *	Perform translation ('y' command) in the pattern space.
477
 */
477
 */
478
static void
478
static void
479
do_tr(struct s_tr *y)
479
do_tr(const struct s_tr *y)
480
{
480
{
481
	SPACE tmp;
481
	SPACE tmp;
482
	char c, *p;
482
	char c, *p;
Lines 565-571 Link Here
565
}
565
}
566
566
567
static void
567
static void
568
lputs(char *s, size_t len)
568
lputs(const char *s, size_t len)
569
{
569
{
570
	static const char escapes[] = "\\\a\b\f\r\t\v";
570
	static const char escapes[] = "\\\a\b\f\r\t\v";
571
	int c, col, width;
571
	int c, col, width;
Lines 645-651 Link Here
645
}
645
}
646
646
647
static __inline int
647
static __inline int
648
regexec_e(regex_t *preg, const char *string, int eflags, int nomatch,
648
regexec_e(const regex_t *preg, const char *string, int eflags, int nomatch,
649
	size_t slen)
649
	size_t slen)
650
{
650
{
651
	int eval;
651
	int eval;
Lines 677-683 Link Here
677
 * Based on a routine by Henry Spencer
677
 * Based on a routine by Henry Spencer
678
 */
678
 */
679
static void
679
static void
680
regsub(SPACE *sp, char *string, char *src)
680
regsub(SPACE *sp, const char *string, const char *src)
681
{
681
{
682
	int len, no;
682
	int len, no;
683
	char c, *dst;
683
	char c, *dst;

Return to bug 195929