1 /* from Unix 7th Edition sed */
2 /* Sccsid @(#)sed0.c 1.64 (gritter) 3/12/05> */
3 /*
4 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * Redistributions of source code and documentation must retain the
10 * above copyright notice, this list of conditions and the following
11 * disclaimer.
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed or owned by Caldera
18 * International, Inc.
19 * Neither the name of Caldera International, Inc. nor the names of
20 * other contributors may be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
24 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
28 * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
34 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36 #include <unistd.h>
37 #include <stdlib.h>
38 #include <locale.h>
39 #include <libgen.h>
40 #include <stdarg.h>
41 #include <wchar.h>
42 #include "sed.h"
43
44 int ABUFSIZE;
45 struct reptr **abuf;
46 int aptr;
47 char *genbuf;
48 int gbend;
49 int lbend;
50 int hend;
51 char *linebuf;
52 char *holdsp;
53 int nflag;
54 long long *tlno;
55 char *cp;
56
57 int status;
58 int multibyte;
59 int invchar;
60 int needdol;
61
62 int eargc;
63
64 struct reptr *ptrspace;
65 struct reptr *pending;
66 char *badp;
67
68 static const char CGMES[] = "\1command garbled: %s";
69 static const char TMMES[] = "Too much text: %s";
70 static const char LTL[] = "Label too long: %s";
71 static const char LINTL[] = "line too long";
72 static const char AD0MES[] = "No addresses allowed: %s";
73 static const char AD1MES[] = "Only one address allowed: %s";
74 static FILE **fcode;
75 static FILE *fin;
76 static char *lastre;
77 static wchar_t sed_seof;
78 static int PTRSIZE;
79 static int eflag;
80 static int gflag;
81 static int nlno;
82 static char **fname;
83 static int nfiles;
84 static int rep;
85 static struct label *ltab;
86 static int lab;
87 static size_t LABSIZE;
88 static int labtab = 1;
89 static int depth;
90 static char **eargv;
91 static int *cmpend;
92 static size_t DEPTH;
93 static char bad;
94 static char compfl;
95 static char *progname;
96 static char *(*ycomp)(char **);
97 static int executing;
98
99 static void fcomp(void);
100 static char *compsub(char **, char *);
101 static int rline(void);
102 static char *address(char **);
103 static int cmp(const char *, const char *);
104 static void text(char **);
105 static int search(struct label *);
106 static void dechain(void);
107 static char *ycomp_sb(char **);
108 static char *ycomp_mb(char **);
109 static void lab_inc(void);
110 static void rep_inc(void);
111 static void depth_check(void);
112 static void *srealloc(void *, size_t);
113 static void *scalloc(size_t, size_t);
114 static char *sed_compile(char **);
115 static void wfile(void);
116 static void morefiles(void);
117
118 static char *null;
119 #define check(p, buf, sz, incr, op) \
120 if (&p[1] >= &(buf)[sz]) { \
121 size_t ppos = p - buf; \
122 size_t opos = op - buf; \
123 buf = srealloc(buf, (sz += incr) * sizeof *(buf)); \
124 p = &(buf)[ppos]; \
125 if (op != NULL) \
126 op = &(buf)[opos]; \
127 }
128
129 int
main(int argc,char ** argv)130 main(int argc, char **argv)
131 {
132 int c;
133 const char optstr[] = "nf:e:g";
134
135 sed = 1;
136 progname = basename(argv[0]);
137 eargc = argc;
138 eargv = argv;
139
140 #ifdef __GLIBC__
141 putenv("POSIXLY_CORRECT=1");
142 #endif /* __GLIBC__ */
143 #if defined (SUS) || defined (SU3) || defined (S42)
144 setlocale(LC_COLLATE, "");
145 #endif /* SUS || SU3 || S42 */
146 setlocale(LC_CTYPE, "");
147 multibyte = MB_CUR_MAX > 1;
148 ycomp = multibyte ? ycomp_mb : ycomp_sb;
149 badp = &bad;
150 aptr_inc();
151 lab_inc();
152 lab_inc(); /* 0 reserved for end-pointer -> labtab = 1 */
153 growsp(NULL);
154 rep_inc();
155 pending = 0;
156 depth = 0;
157 morefiles();
158 fcode[0] = stdout;
159 nfiles = 1;
160 morefiles();
161
162 if(eargc == 1)
163 exit(0);
164 while ((c = getopt(eargc, eargv, optstr)) != EOF) {
165 switch (c) {
166 case 'n':
167 nflag++;
168 continue;
169
170 case 'f':
171 if((fin = fopen(optarg, "r")) == NULL)
172 fatal("Cannot open pattern-file: %s", optarg);
173
174 fcomp();
175 fclose(fin);
176 continue;
177
178 case 'e':
179 eflag++;
180 fcomp();
181 eflag = 0;
182 continue;
183
184 case 'g':
185 gflag++;
186 continue;
187
188 default:
189 exit(2);
190 }
191 }
192
193 eargv += optind, eargc -= optind;
194
195
196 if(compfl == 0 && *eargv) {
197 optarg = *eargv++;
198 eargc--;
199 eflag++;
200 fcomp();
201 eflag = 0;
202 }
203
204 if(depth)
205 fatal("Too many {'s");
206
207 L(labtab)->address = rep;
208
209 dechain();
210
211 /* abort(); */ /*DEBUG*/
212
213 executing++;
214 if(eargc <= 0)
215 execute((char *)NULL);
216 else while(--eargc >= 0) {
217 execute(*eargv++);
218 }
219 fclose(stdout);
220 return status;
221 }
222
223 static void
fcomp(void)224 fcomp(void)
225 {
226
227 register char *op, *tp, *q;
228 int pt, pt1;
229 int lpt;
230
231 compfl = 1;
232 op = lastre;
233
234 if(rline() < 0) return;
235 if(*linebuf == '#') {
236 if(linebuf[1] == 'n')
237 nflag = 1;
238 }
239 else {
240 cp = linebuf;
241 goto comploop;
242 }
243
244 for(;;) {
245 if(rline() < 0) break;
246
247 cp = linebuf;
248
249 comploop:
250 /* fprintf(stdout, "cp: %s\n", cp); */ /*DEBUG*/
251 while(*cp == ' ' || *cp == '\t') cp++;
252 if(*cp == '\0' || *cp == '#') continue;
253 if(*cp == ';') {
254 cp++;
255 goto comploop;
256 }
257
258 q = address(&P(rep)->ad1);
259 if(q == badp)
260 fatal(CGMES, linebuf);
261
262 if(q != 0 && q == P(rep)->ad1) {
263 if(op)
264 P(rep)->ad1 = op;
265 else
266 fatal("First RE may not be null");
267 } else if(q == 0) {
268 P(rep)->ad1 = 0;
269 } else {
270 op = P(rep)->ad1;
271 if(*cp == ',' || *cp == ';') {
272 cp++;
273 q = address(&P(rep)->ad2);
274 if(q == badp || q == 0)
275 fatal(CGMES, linebuf);
276 if(q == P(rep)->ad2)
277 P(rep)->ad2 = op;
278 else
279 op = P(rep)->ad2;
280
281 } else
282 P(rep)->ad2 = 0;
283 }
284
285 while(*cp == ' ' || *cp == '\t') cp++;
286
287 swit:
288 switch(*cp++) {
289
290 default:
291 fatal("Unrecognized command: %s", linebuf);
292 /*NOTREACHED*/
293
294 case '!':
295 P(rep)->negfl = 1;
296 goto swit;
297
298 case '{':
299 P(rep)->command = BCOM;
300 P(rep)->negfl = !(P(rep)->negfl);
301 depth_check();
302 cmpend[depth++] = rep;
303 rep_inc();
304 if(*cp == '\0') continue;
305
306 goto comploop;
307
308 case '}':
309 if(P(rep)->ad1)
310 fatal(AD0MES, linebuf);
311
312 if(--depth < 0)
313 fatal("Too many }'s");
314 P(cmpend[depth])->bptr.lb1 = rep;
315
316 continue;
317
318 case '=':
319 P(rep)->command = EQCOM;
320 if(P(rep)->ad2)
321 fatal(AD1MES, linebuf);
322 break;
323
324 case ':':
325 if(P(rep)->ad1)
326 fatal(AD0MES, linebuf);
327
328 while(*cp++ == ' ');
329 cp--;
330
331
332 tp = L(lab)->asc;
333 while((*tp++ = *cp++))
334 if(tp >= &(L(lab)->asc[sizeof
335 L(lab)->asc]))
336 fatal(LTL, linebuf);
337 *--tp = '\0';
338
339 if(lpt = search(L(lab))) {
340 if(L(lpt)->address)
341 fatal("Duplicate labels: %s",
342 linebuf);
343 } else {
344 L(lab)->chain = 0;
345 lpt = lab;
346 lab_inc();
347 }
348 L(lpt)->address = rep;
349
350 continue;
351
352 case 'a':
353 P(rep)->command = ACOM;
354 if(P(rep)->ad2)
355 fatal(AD1MES, linebuf);
356 if(*cp == '\\') cp++;
357 if(*cp++ != '\n')
358 fatal(CGMES, linebuf);
359 text(&P(rep)->bptr.re1);
360 break;
361 case 'c':
362 P(rep)->command = CCOM;
363 if(*cp == '\\') cp++;
364 if(*cp++ != ('\n'))
365 fatal(CGMES, linebuf);
366 text(&P(rep)->bptr.re1);
367 needdol = 1;
368 break;
369 case 'i':
370 P(rep)->command = ICOM;
371 if(P(rep)->ad2)
372 fatal(AD1MES, linebuf);
373 if(*cp == '\\') cp++;
374 if(*cp++ != ('\n'))
375 fatal(CGMES, linebuf);
376 text(&P(rep)->bptr.re1);
377 break;
378
379 case 'g':
380 P(rep)->command = GCOM;
381 break;
382
383 case 'G':
384 P(rep)->command = CGCOM;
385 break;
386
387 case 'h':
388 P(rep)->command = HCOM;
389 break;
390
391 case 'H':
392 P(rep)->command = CHCOM;
393 break;
394
395 case 't':
396 P(rep)->command = TCOM;
397 goto jtcommon;
398
399 case 'b':
400 P(rep)->command = BCOM;
401 jtcommon:
402 while(*cp++ == ' ');
403 cp--;
404
405 if(*cp == '\0') {
406 if((pt = L(labtab)->chain) != 0) {
407 while((pt1 = P(pt)->bptr.lb1) != 0)
408 pt = pt1;
409 P(pt)->bptr.lb1 = rep;
410 } else
411 L(labtab)->chain = rep;
412 break;
413 }
414 tp = L(lab)->asc;
415 while((*tp++ = *cp++))
416 if(tp >= &(L(lab)->asc[sizeof
417 L(lab)->asc]))
418 fatal(LTL, linebuf);
419 cp--;
420 *--tp = '\0';
421
422 if(lpt = search(L(lab))) {
423 if(L(lpt)->address) {
424 P(rep)->bptr.lb1 = L(lpt)->address;
425 } else {
426 pt = L(lpt)->chain;
427 while((pt1 = P(pt)->bptr.lb1) != 0)
428 pt = pt1;
429 P(pt)->bptr.lb1 = rep;
430 }
431 } else {
432 L(lab)->chain = rep;
433 L(lab)->address = 0;
434 lab_inc();
435 }
436 break;
437
438 case 'n':
439 P(rep)->command = NCOM;
440 break;
441
442 case 'N':
443 P(rep)->command = CNCOM;
444 break;
445
446 case 'p':
447 P(rep)->command = PCOM;
448 break;
449
450 case 'P':
451 P(rep)->command = CPCOM;
452 break;
453
454 case 'r':
455 P(rep)->command = RCOM;
456 if(P(rep)->ad2)
457 fatal(AD1MES, linebuf);
458 #if !defined (SUS) && !defined (SU3)
459 if(*cp++ != ' ')
460 fatal(CGMES, linebuf);
461 #else /* SUS, SU3 */
462 while (*cp == ' ' || *cp == '\t')
463 cp++;
464 #endif /* SUS, SU3 */
465 text(&P(rep)->bptr.re1);
466 break;
467
468 case 'd':
469 P(rep)->command = DCOM;
470 break;
471
472 case 'D':
473 P(rep)->command = CDCOM;
474 P(rep)->bptr.lb1 = 1;
475 break;
476
477 case 'q':
478 P(rep)->command = QCOM;
479 if(P(rep)->ad2)
480 fatal(AD1MES, linebuf);
481 break;
482
483 case 'l':
484 P(rep)->command = LCOM;
485 break;
486
487 case 's':
488 P(rep)->command = SCOM;
489 sed_seof = fetch(&cp);
490 q = sed_compile(&P(rep)->bptr.re1);
491 if(q == badp)
492 fatal(CGMES, linebuf);
493 if(q == P(rep)->bptr.re1) {
494 if (op == NULL)
495 fatal("First RE may not be null");
496 P(rep)->bptr.re1 = op;
497 } else {
498 op = P(rep)->bptr.re1;
499 }
500
501 if(compsub(&P(rep)->rhs, &P(rep)->nsub) == badp)
502 fatal(CGMES, linebuf);
503 sloop: if(*cp == 'g') {
504 cp++;
505 P(rep)->gfl = -1;
506 goto sloop;
507 } else if(gflag)
508 P(rep)->gfl = -1;
509 if (*cp >= '0' && *cp <= '9') {
510 while (*cp >= '0' && *cp <= '9') {
511 if (P(rep)->gfl == -1)
512 P(rep)->gfl = 0;
513 P(rep)->gfl = P(rep)->gfl * 10
514 + *cp++ - '0';
515 }
516 goto sloop;
517 }
518 #if !defined (SUS) && !defined (SU3)
519 if (P(rep)->gfl > 0 && P(rep)->gfl > 512)
520 fatal("Suffix too large - 512 max: %s", linebuf);
521 #endif
522
523 if(*cp == 'p') {
524 cp++;
525 P(rep)->pfl = 1;
526 goto sloop;
527 }
528
529 if(*cp == 'P') {
530 cp++;
531 P(rep)->pfl = 2;
532 goto sloop;
533 }
534
535 if(*cp == 'w') {
536 cp++;
537 wfile();
538 }
539 break;
540
541 case 'w':
542 P(rep)->command = WCOM;
543 wfile();
544 break;
545
546 case 'x':
547 P(rep)->command = XCOM;
548 break;
549
550 case 'y':
551 P(rep)->command = YCOM;
552 sed_seof = fetch(&cp);
553 if (ycomp(&P(rep)->bptr.re1) == badp)
554 fatal(CGMES, linebuf);
555 break;
556
557 }
558 rep_inc();
559
560 if(*cp++ != '\0') {
561 if(cp[-1] == ';')
562 goto comploop;
563 fatal(CGMES, linebuf);
564 }
565
566 }
567 P(rep)->command = 0;
568 lastre = op;
569 }
570
571 static char *
compsub(char ** rhsbuf,char * nsubp)572 compsub(char **rhsbuf, char *nsubp)
573 {
574 register char *p, *op, *oq;
575 char *q;
576 wint_t c;
577 size_t sz = 32;
578
579 *rhsbuf = smalloc(sz);
580 p = *rhsbuf;
581 q = cp;
582 *nsubp = 0;
583 for(;;) {
584 op = p;
585 oq = q;
586 if((c = fetch(&q)) == '\\') {
587 check(p, *rhsbuf, sz, 32, op)
588 *p = '\\';
589 oq = q;
590 c = fetch(&q);
591 do {
592 check(p, *rhsbuf, sz, 32, op)
593 *++p = *oq++;
594 } while (oq < q);
595 if(c > nbra + '0' && c <= '9')
596 return(badp);
597 if (c > *nsubp + '0' && c <= '9')
598 *nsubp = c - '0';
599 check(p, *rhsbuf, sz, 32, op)
600 p++;
601 continue;
602 } else {
603 do {
604 check(p, *rhsbuf, sz, 32, op)
605 *p++ = *oq++;
606 } while (oq < q);
607 p--;
608 }
609 if(c == sed_seof) {
610 check(p, *rhsbuf, sz, 32, op)
611 *op++ = '\0';
612 cp = q;
613 return(op);
614 }
615 check(p, *rhsbuf, sz, 32, op)
616 if(*p++ == '\0') {
617 return(badp);
618 }
619
620 }
621 }
622
623 #define rlinechk() if (c >= lbend-2) \
624 growsp(LINTL)
625
626 static int
rline(void)627 rline(void)
628 {
629 register char *q;
630 register int c;
631 register int t;
632 static char *saveq;
633
634 c = -1;
635
636 if(eflag) {
637 if(eflag > 0) {
638 eflag = -1;
639 q = optarg;
640 rlinechk();
641 while(linebuf[++c] = *q++) {
642 rlinechk();
643 if(linebuf[c] == '\\') {
644 if((linebuf[++c] = *q++) == '\0') {
645 rlinechk();
646 saveq = 0;
647 return(-1);
648 } else
649 continue;
650 }
651 if(linebuf[c] == '\n') {
652 linebuf[c] = '\0';
653 saveq = q;
654 return(1);
655 }
656 }
657 saveq = 0;
658 return(1);
659 }
660 if((q = saveq) == 0) return(-1);
661
662 while(linebuf[++c] = *q++) {
663 rlinechk();
664 if(linebuf[c] == '\\') {
665 if((linebuf[++c] = *q++) == '0') {
666 rlinechk();
667 saveq = 0;
668 return(-1);
669 } else
670 continue;
671 }
672 if(linebuf[c] == '\n') {
673 linebuf[c] = '\0';
674 saveq = q;
675 return(1);
676 }
677 }
678 saveq = 0;
679 return(1);
680 }
681
682 while((t = getc(fin)) != EOF) {
683 rlinechk();
684 linebuf[++c] = (char)t;
685 if(linebuf[c] == '\\') {
686 t = getc(fin);
687 rlinechk();
688 linebuf[++c] = (char)t;
689 }
690 else if(linebuf[c] == '\n') {
691 linebuf[c] = '\0';
692 return(1);
693 }
694 }
695 linebuf[++c] = '\0';
696 return(-1);
697 }
698
699 static char *
address(char ** expbuf)700 address(char **expbuf)
701 {
702 register char *rcp, *ep;
703 long long lno;
704
705 *expbuf = NULL;
706 if(*cp == '$') {
707 cp++;
708 ep = *expbuf = smalloc(2 * sizeof *expbuf);
709 *ep++ = CEND;
710 *ep++ = ceof;
711 needdol = 1;
712 return(ep);
713 }
714
715 if(*cp == '/' || *cp == '\\') {
716 if (*cp == '\\')
717 cp++;
718 sed_seof = fetch(&cp);
719 return(sed_compile(expbuf));
720 }
721
722 rcp = cp;
723 lno = 0;
724
725 while(*rcp >= '0' && *rcp <= '9')
726 lno = lno*10 + *rcp++ - '0';
727
728 if(rcp > cp) {
729 if (nlno > 020000000000 ||
730 (tlno = realloc(tlno, (nlno+1)*sizeof *tlno)) == NULL)
731 fatal("Too many line numbers");
732 ep = *expbuf = smalloc(6 * sizeof *expbuf);
733 *ep++ = CLNUM;
734 slno(ep, nlno);
735 tlno[nlno++] = lno;
736 *ep++ = ceof;
737 cp = rcp;
738 return(ep);
739 }
740 return(0);
741 }
742
743 static int
cmp(const char * a,const char * b)744 cmp(const char *a, const char *b)
745 {
746 register const char *ra, *rb;
747
748 ra = a - 1;
749 rb = b - 1;
750
751 while(*++ra == *++rb)
752 if(*ra == '\0') return(0);
753 return(1);
754 }
755
756 static void
text(char ** textbuf)757 text(char **textbuf)
758 {
759 register char *p, *oq;
760 char *q;
761 size_t sz = 128;
762
763 *textbuf = smalloc(sz);
764 p = *textbuf;
765 q = cp;
766 for(;;) {
767
768 oq = q;
769 if(fetch(&q) == '\\') {
770 oq = q;
771 fetch(&q);
772 }
773 while(oq < q)
774 *p++ = *oq++;
775 if(p[-1] == '\0') {
776 cp = --q;
777 return;
778 }
779 check(p, *textbuf, sz, 128, null)
780 }
781 }
782
783 static int
search(struct label * ptr)784 search(struct label *ptr)
785 {
786 struct label *rp;
787
788 rp = L(labtab);
789 while(rp < ptr) {
790 if(cmp(rp->asc, ptr->asc) == 0)
791 return(rp - L(labtab) + 1);
792 rp++;
793 }
794
795 return(0);
796 }
797
798
799 static void
dechain(void)800 dechain(void)
801 {
802 struct label *lptr;
803 int rptr, trptr;
804
805 for(lptr = L(labtab); lptr < L(lab); lptr++) {
806
807 if(lptr->address == 0)
808 fatal("Undefined label: %s", lptr->asc);
809
810 if(lptr->chain) {
811 rptr = lptr->chain;
812 while((trptr = P(rptr)->bptr.lb1) != 0) {
813 P(rptr)->bptr.lb1 = lptr->address;
814 rptr = trptr;
815 }
816 P(rptr)->bptr.lb1 = lptr->address;
817 }
818 }
819 }
820
821 static char *
ycomp_sb(char ** expbuf)822 ycomp_sb(char **expbuf)
823 {
824 register int c, d;
825 register char *ep, *tsp;
826 char *sp;
827
828 *expbuf = smalloc(0400);
829 ep = *expbuf;
830 for(c = 0; !(c & 0400); c++)
831 ep[c] = '\0';
832 sp = cp;
833 for(tsp = cp; *tsp != sed_seof; tsp++) {
834 if(*tsp == '\\')
835 tsp++;
836 if(*tsp == '\n' || *tsp == '\0')
837 return(badp);
838 }
839 tsp++;
840
841 while((c = *sp++ & 0377) != sed_seof) {
842 if(c == '\\') {
843 c = *sp == 'n' ? '\n' : *sp;
844 sp++;
845 }
846 if((ep[c] = d = *tsp++ & 0377) == '\\') {
847 ep[c] = *tsp == 'n' ? '\n' : *tsp;
848 tsp++;
849 }
850 if(d != '\\' && ep[c] == sed_seof || ep[c] == '\0')
851 return(badp);
852 }
853 if(*tsp != sed_seof)
854 return(badp);
855 cp = ++tsp;
856
857 for(c = 0; !(c & 0400); c++)
858 if(ep[c] == 0)
859 ep[c] = (char)c;
860
861 return(ep + 0400);
862 }
863
864 static char *
ycomp_mb(char ** expbuf)865 ycomp_mb(char **expbuf)
866 {
867 struct yitem **yt, *yp;
868 register wint_t c, d;
869 char *otsp, *tsp, *sp, *mp;
870
871 tsp = sp = cp;
872 while ((c = fetch(&tsp)) != sed_seof) {
873 if (c == '\\')
874 c = fetch(&tsp);
875 if (c == '\n' || c == '\0')
876 return badp;
877 }
878 yt = scalloc(200, sizeof *yt);
879 while ((c = fetch(&sp)) != sed_seof) {
880 if (c == '\\') {
881 if ((d = fetch(&sp)) == 'n')
882 c = '\n';
883 else
884 c = d;
885 }
886 otsp = tsp;
887 d = fetch(&tsp);
888 yp = ylook(c, yt, 1);
889 yp->y_oc = c;
890 if ((yp->y_yc = d) == '\\') {
891 otsp = tsp;
892 if ((c = fetch(&tsp)) == 'n')
893 yp->y_yc = '\n';
894 else
895 yp->y_yc = c;
896 }
897 if (d != '\\' && yp->y_yc == sed_seof || yp->y_yc == '\0')
898 return badp;
899 mp = yp->y_mc;
900 if (yp->y_yc != '\n')
901 while (otsp < tsp)
902 *mp++ = *otsp++;
903 else
904 *mp++ = '\n';
905 *mp = '\0';
906 }
907 if (fetch(&tsp) != sed_seof)
908 return badp;
909 cp = tsp;
910 *expbuf = (char *)yt;
911 return &(*expbuf)[1];
912 }
913
914 static void
rep_inc(void)915 rep_inc(void)
916 {
917 register char *p;
918 const int chunk = 16;
919
920 if (++rep >= PTRSIZE) {
921 ptrspace = srealloc(ptrspace,
922 (PTRSIZE += chunk) * sizeof *ptrspace);
923 for (p = (char *)&ptrspace[PTRSIZE - chunk];
924 p < (char *)&ptrspace[PTRSIZE]; p++)
925 *p = '\0';
926 }
927 }
928
929 static void
lab_inc(void)930 lab_inc(void)
931 {
932 register char *p;
933 const int chunk = 8;
934
935 if (++lab >= LABSIZE) {
936 ltab = srealloc(ltab, (LABSIZE += chunk) * sizeof *ltab);
937 for (p = (char *)<ab[LABSIZE - chunk];
938 p < (char *)<ab[LABSIZE]; p++)
939 *p = '\0';
940 }
941 }
942
943 void
aptr_inc(void)944 aptr_inc(void)
945 {
946 register char *p;
947 const int chunk = 8;
948
949 if (++aptr > ABUFSIZE) {
950 abuf = srealloc(abuf, (ABUFSIZE += chunk) * sizeof *abuf);
951 for (p = (char *)&abuf[ABUFSIZE - chunk];
952 p < (char *)&abuf[ABUFSIZE]; p++)
953 *p = '\0';
954 }
955 }
956
957 static void
depth_check(void)958 depth_check(void)
959 {
960 if (depth + 1 > DEPTH)
961 cmpend = srealloc(cmpend, (DEPTH += 8) * sizeof *cmpend);
962 }
963
964 void
nonfatal(const char * afmt,...)965 nonfatal(const char *afmt, ...)
966 {
967 va_list ap;
968 const char *fmt;
969
970 if (*afmt == '\1') {
971 fprintf(stderr, "%s: ", progname);
972 fmt = &afmt[1];
973 } else
974 fmt = afmt;
975 va_start(ap, afmt);
976 vfprintf(stderr, fmt, ap);
977 va_end(ap);
978 fputc('\n', stderr);
979 status |= 1;
980 }
981
982 void
fatal(const char * afmt,...)983 fatal(const char *afmt, ...)
984 {
985 va_list ap;
986 const char *fmt;
987
988 if (*afmt == '\1') {
989 fprintf(stderr, "%s: ", progname);
990 fmt = &afmt[1];
991 } else
992 fmt = afmt;
993 va_start(ap, afmt);
994 vfprintf(stderr, fmt, ap);
995 va_end(ap);
996 fputc('\n', stderr);
997 exit(2);
998 }
999
1000 static void *
srealloc(void * vp,size_t nbytes)1001 srealloc(void *vp, size_t nbytes)
1002 {
1003 void *p;
1004
1005 if ((p = realloc(vp, nbytes)) == NULL)
1006 fatal(TMMES, linebuf);
1007 return p;
1008 }
1009
1010 void *
smalloc(size_t nbytes)1011 smalloc(size_t nbytes)
1012 {
1013 return srealloc(NULL, nbytes);
1014 }
1015
1016 static void *
scalloc(size_t nmemb,size_t size)1017 scalloc(size_t nmemb, size_t size)
1018 {
1019 void *p;
1020
1021 if ((p = calloc(nmemb, size)) == NULL)
1022 fatal(TMMES, linebuf);
1023 return p;
1024 }
1025
1026 #if defined (SUS) || defined (SU3) || defined (S42)
1027 static char *
sed_compile(char ** ep)1028 sed_compile(char **ep)
1029 {
1030 struct re_emu *re;
1031 static char *pat;
1032 static size_t patsz;
1033 register char *p, *oc;
1034 wint_t c, d;
1035
1036 if (*cp != sed_seof)
1037 nbra = 0;
1038 if (patsz == 0)
1039 pat = smalloc(patsz = 32);
1040 p = pat;
1041 do {
1042 oc = cp;
1043 if ((c = fetch(&cp)) == sed_seof)
1044 *p = '\0';
1045 else if (c == '\\') {
1046 oc = cp;
1047 if ((c = fetch(&cp)) == 'n')
1048 *p = '\n';
1049 else {
1050 check(p, pat, patsz, 32, null);
1051 *p++ = '\\';
1052 if (c == '(')
1053 nbra++;
1054 goto normchar;
1055 }
1056 } else if (c == '[') {
1057 check(p, pat, patsz, 32, null);
1058 *p++ = c;
1059 d = WEOF;
1060 do {
1061 oc = cp;
1062 c = fetch(&cp);
1063 if (c == '\0')
1064 goto normchar;
1065 do {
1066 check(p, pat, patsz, 32, null);
1067 *p++ = *oc++;
1068 } while (oc < cp);
1069 if (d == '[' && (c == ':' || c == '.' ||
1070 c == '=')) {
1071 d = c;
1072 do {
1073 oc = cp;
1074 c = fetch(&cp);
1075 if (c == '\0')
1076 goto normchar;
1077 do {
1078 check(p, pat, patsz,32,
1079 null);
1080 *p++ = *oc++;
1081 } while (oc < cp);
1082 } while (c != d || peek(&cp) != ']');
1083 oc = cp;
1084 c = fetch(&cp);
1085 do {
1086 check(p, pat, patsz, 32, null);
1087 *p++ = *oc++;
1088 } while (oc < cp);
1089 c = WEOF; /* == reset d and continue */
1090 }
1091 d = c;
1092 } while (c != ']');
1093 p--;
1094 } else {
1095 normchar: do {
1096 check(p, pat, patsz, 32, null)
1097 *p++ = *oc++;
1098 } while (oc < cp);
1099 p--;
1100 }
1101 check(p, pat, patsz, 32, null);
1102 } while (*p++ != '\0');
1103 re = scalloc(1, sizeof *re);
1104 *ep = (char *)re;
1105 if (*pat == '^')
1106 **ep = 1;
1107 if (*pat != '\0') {
1108 int reflags = 0;
1109
1110 #ifdef REG_ANGLES
1111 reflags |= REG_ANGLES;
1112 #endif /* REG_ANGLES */
1113 #if defined (SU3) && defined (REG_AVOIDNULL)
1114 reflags |= REG_AVOIDNULL;
1115 #endif /* SU3 && AVOIDNULL */
1116 if (regcomp(&re->r_preg, pat, reflags) != 0)
1117 re = (struct re_emu *)badp;
1118 } else
1119 **ep = 2;
1120 p = (char *)re;
1121 if (p != badp && *pat)
1122 p++;
1123 return p;
1124 }
1125 #else /* !SUS, !SU3, !S42 */
1126 static char *
sed_compile(char ** ep)1127 sed_compile(char **ep)
1128 {
1129 extern char *compile(char *, char *, char *, int);
1130 register char *p;
1131 size_t sz;
1132
1133 for (sz = 0, p = cp; *p; p++)
1134 if (*p == '[')
1135 sz += 32;
1136 sz += 2 * (p - cp) + 5;
1137 *ep = smalloc(sz);
1138 (*ep)[1] = '\0';
1139 p = compile(NULL, &(*ep)[1], &(*ep)[sz], sed_seof);
1140 if (p == &(*ep)[1])
1141 return *ep;
1142 **ep = circf;
1143 return p;
1144 }
1145 #endif /* !SUS, !SU3, !S42 */
1146
1147 wint_t
wc_get(char ** sc,int move)1148 wc_get(char **sc, int move)
1149 {
1150 wint_t c;
1151 char *p = *sc;
1152 wchar_t wcbuf;
1153 int len;
1154
1155 if ((*p & 0200) == 0) {
1156 c = *p;
1157 p += (len = 1);
1158 invchar = 0;
1159 } else if ((len = mbtowc(&wcbuf, p, MB_LEN_MAX)) < 0) {
1160 if (!executing)
1161 fatal("invalid multibyte character: %s", p);
1162 c = (*p++ & 0377);
1163 mbtowc(NULL, NULL, 0);
1164 invchar = 1;
1165 } else if (len == 0) {
1166 c = '\0';
1167 p++;
1168 invchar = 0;
1169 } else {
1170 c = wcbuf;
1171 p += len;
1172 invchar = 0;
1173 }
1174 if (move)
1175 *sc = p;
1176 return c;
1177 }
1178
1179 /*
1180 * Note that this hash is not optimized to distribute the items
1181 * equally to all buckets. y commands typically handle only a
1182 * small part of the alphabet, thus most characters will have
1183 * no entry in the hash table. If no list exists in the bucket
1184 * for the hash of these characters, the function can return
1185 * quickly.
1186 */
1187 #define yhash(c) (c & 0177)
1188
1189 struct yitem *
ylook(wint_t c,struct yitem ** yt,int make)1190 ylook(wint_t c, struct yitem **yt, int make)
1191 {
1192 struct yitem *yp;
1193 int h;
1194
1195 yp = yt[h = yhash(c)];
1196 while (yp != NULL) {
1197 if (yp->y_oc == c)
1198 break;
1199 yp = yp->y_nxt;
1200 }
1201 if (make && yp == NULL) {
1202 yp = scalloc(1, sizeof *yp);
1203 yp->y_oc = c;
1204 yp->y_nxt = yt[h];
1205 yt[h] = yp;
1206 }
1207 return yp;
1208 }
1209
1210 void
growsp(const char * msg)1211 growsp(const char *msg)
1212 {
1213 const int incr = 128;
1214 int olbend, ogbend, ohend;
1215
1216 olbend = lbend;
1217 ogbend = gbend;
1218 ohend = hend;
1219 if ((linebuf = realloc(linebuf, lbend += incr)) == NULL ||
1220 (genbuf = realloc(genbuf, gbend += incr)) == NULL ||
1221 (holdsp = realloc(holdsp, hend += incr)) == NULL)
1222 fatal(msg ? msg : "Cannot malloc space");
1223 while (olbend < lbend)
1224 linebuf[olbend++] = '\0';
1225 while (ogbend < gbend)
1226 genbuf[ogbend++] = '\0';
1227 while (ohend < hend)
1228 holdsp[ohend++] = '\0';
1229 }
1230
1231 static void
wfile(void)1232 wfile(void)
1233 {
1234 int i;
1235
1236 #if !defined (SUS) && !defined (SU3)
1237 if(*cp++ != ' ')
1238 fatal(CGMES, linebuf);
1239 #else /* SUS, SU3 */
1240 while (*cp == ' ' || *cp == '\t')
1241 cp++;
1242 #endif /* SUS, SU3 */
1243
1244 text(&fname[nfiles]);
1245 for(i = nfiles - 1; i >= 0; i--)
1246 if(fname[i] != NULL && cmp(fname[nfiles], fname[i]) == 0) {
1247 P(rep)->fcode = fcode[i];
1248 free(fname[nfiles]);
1249 return;
1250 }
1251
1252 if((P(rep)->fcode = fopen(fname[nfiles], "w")) == NULL)
1253 fatal("Cannot create %s", fname[nfiles]);
1254 fcode[nfiles++] = P(rep)->fcode;
1255 morefiles();
1256 }
1257
1258 static void
morefiles(void)1259 morefiles(void)
1260 {
1261 if ((fname = realloc(fname, (nfiles+1) * sizeof *fname)) == 0 ||
1262 (fcode = realloc(fcode, (nfiles+1) * sizeof *fcode)) == 0)
1263 fatal("Too many files in w commands");
1264 fname[nfiles] = 0;
1265 fcode[nfiles] = 0;
1266 }
1267