8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / ucbcmd / sed / sed0.c
blob5be6112e36f40aa66e1756196b577edcc0a722ce
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1984 AT&T */
27 /* All Rights Reserved */
29 #include <stdio.h>
30 #include <sys/param.h>
31 #include "sed.h"
33 #define NWFILES 11 /* 10 plus one for standard output */
34 FILE *fin;
35 FILE *fcode[NWFILES];
36 char *lastre;
37 char sseof;
38 union reptr *ptrend;
39 int eflag;
40 extern int nbra;
41 char linebuf[LBSIZE+1];
42 int gflag;
43 int nlno;
44 char *fname[NWFILES];
45 int nfiles;
46 union reptr ptrspace[PTRSIZE];
47 union reptr *rep;
48 char *cp;
49 char respace[RESIZE];
50 struct label ltab[LABSIZE];
51 struct label *lab;
52 struct label *labend;
53 int depth;
54 int eargc;
55 char **eargv;
56 union reptr **cmpend[DEPTH];
58 #define CCEOF 22
60 struct label *labtab = ltab;
62 char ETMES[] = "Extra text at end of command: %s";
63 char SMMES[] = "Space missing before filename: %s";
64 char TMMES[] = "Too much command text: %s";
65 char LTL[] = "Label too long: %s";
66 char AD0MES[] = "No addresses allowed: %s";
67 char AD1MES[] = "Only one address allowed: %s";
68 char TOOBIG[] = "Suffix too large - 512 max: %s";
70 extern int sed; /* IMPORTANT flag !!! */
71 extern char *comple();
73 extern char *malloc();
75 static void dechain(void);
76 static void fcomp(void);
78 int
79 main(int argc, char *argv[])
81 int flag_found = 0;
83 sed = 1;
84 eargc = argc;
85 eargv = argv;
87 aptr = abuf;
88 lab = labtab + 1; /* 0 reserved for end-pointer */
89 rep = ptrspace;
90 rep->r1.ad1 = respace;
91 lcomend = &genbuf[71];
92 ptrend = &ptrspace[PTRSIZE];
93 labend = &labtab[LABSIZE];
94 lnum = 0;
95 pending = 0;
96 depth = 0;
97 spend = linebuf;
98 hspend = holdsp; /* Avoid "bus error" under "H" cmd. */
99 fcode[0] = stdout;
100 fname[0] = "";
101 nfiles = 1;
103 if(eargc == 1)
104 exit(0);
107 setlocale(LC_ALL, ""); /* get locale environment */
109 while (--eargc > 0 && (++eargv)[0][0] == '-')
110 switch (eargv[0][1]) {
112 case 'n':
113 nflag++;
114 continue;
116 case 'f':
117 flag_found = 1;
118 if(eargc-- <= 0) exit(2);
120 if((fin = fopen(*++eargv, "r")) == NULL) {
121 (void) fprintf(stderr, "sed: ");
122 perror(*eargv);
123 exit(2);
126 fcomp();
127 (void) fclose(fin);
128 continue;
130 case 'e':
131 flag_found = 1;
132 eflag++;
133 fcomp();
134 eflag = 0;
135 continue;
137 case 'g':
138 gflag++;
139 continue;
141 default:
142 (void) fprintf(stderr, "sed: Unknown flag: %c\n", eargv[0][1]);
143 exit(2);
147 if(rep == ptrspace && !flag_found) {
148 eargv--;
149 eargc++;
150 eflag++;
151 fcomp();
152 eargv++;
153 eargc--;
154 eflag = 0;
157 if(depth)
158 comperr("Too many {'s");
160 labtab->address = rep;
162 dechain();
164 if(eargc <= 0)
165 execute((char *)NULL);
166 else while(--eargc >= 0) {
167 execute(*eargv++);
169 (void) fclose(stdout);
170 return (0);
173 static void
174 fcomp(void)
177 char *p, *op, *tp;
178 char *address();
179 union reptr *pt, *pt1;
180 int i, ii;
181 struct label *lpt;
182 char fnamebuf[MAXPATHLEN];
184 op = lastre;
186 if(rline(linebuf, &linebuf[LBSIZE+1]) < 0) return;
187 if(*linebuf == '#') {
188 if(linebuf[1] == 'n')
189 nflag = 1;
191 else {
192 cp = linebuf;
193 goto comploop;
196 for(;;) {
197 if(rline(linebuf, &linebuf[LBSIZE+1]) < 0) break;
199 cp = linebuf;
201 comploop:
202 /* (void) fprintf(stderr, "cp: %s\n", cp); DEBUG */
203 while(*cp == ' ' || *cp == '\t') cp++;
204 if(*cp == '\0' || *cp == '#') continue;
205 if(*cp == ';') {
206 cp++;
207 goto comploop;
210 p = address(rep->r1.ad1);
212 if(p == rep->r1.ad1) {
213 if(op)
214 rep->r1.ad1 = op;
215 else
216 comperr("First RE may not be null: %s");
217 } else if(p == 0) {
218 p = rep->r1.ad1;
219 rep->r1.ad1 = 0;
220 } else {
221 op = rep->r1.ad1;
222 if(*cp == ',' || *cp == ';') {
223 cp++;
224 rep->r1.ad2 = p;
225 p = address(rep->r1.ad2);
226 if(p == 0)
227 comperr("Illegal line number: %s");
228 if(p == rep->r1.ad2)
229 rep->r1.ad2 = op;
230 else
231 op = rep->r1.ad2;
233 } else
234 rep->r1.ad2 = 0;
237 if(p > &respace[RESIZE-1])
238 comperr(TMMES);
240 while(*cp == ' ' || *cp == '\t') cp++;
242 swit:
243 switch(*cp++) {
245 default:
246 comperr("Unrecognized command: %s");
248 case '!':
249 rep->r1.negfl = 1;
250 goto swit;
252 case '{':
253 rep->r1.command = BCOM;
254 rep->r1.negfl = !(rep->r1.negfl);
255 cmpend[depth++] = &rep->r2.lb1;
256 if(++rep >= ptrend)
257 comperr("Too many commands: %s");
258 rep->r1.ad1 = p;
259 if(*cp == '\0') continue;
261 goto comploop;
263 case '}':
264 if(rep->r1.ad1)
265 comperr(AD0MES);
267 if(--depth < 0)
268 comperr("Too many }'s");
269 *cmpend[depth] = rep;
271 rep->r1.ad1 = p;
272 continue;
274 case '=':
275 rep->r1.command = EQCOM;
276 if(rep->r1.ad2)
277 comperr(AD1MES);
278 break;
280 case ':':
281 if(rep->r1.ad1)
282 comperr(AD0MES);
284 while(*cp++ == ' ');
285 cp--;
288 tp = lab->asc;
289 while((*tp++ = *cp++))
290 if(tp >= &(lab->asc[9]))
291 comperr(LTL);
292 *--tp = '\0';
294 if(lpt = search(lab)) {
295 if(lpt->address)
296 comperr("Duplicate labels: %s");
297 } else {
298 lab->chain = 0;
299 lpt = lab;
300 if(++lab >= labend)
301 comperr("Too many labels: %s");
303 lpt->address = rep;
304 rep->r1.ad1 = p;
306 continue;
308 case 'a':
309 rep->r1.command = ACOM;
310 if(rep->r1.ad2)
311 comperr(AD1MES);
312 if(*cp == '\\') cp++;
313 if(*cp++ != '\n')
314 comperr(ETMES);
315 rep->r1.re1 = p;
316 if ((p = text(rep->r1.re1, &respace[RESIZE-1])) == NULL)
317 comperr(TMMES);
318 break;
319 case 'c':
320 rep->r1.command = CCOM;
321 if(*cp == '\\') cp++;
322 if(*cp++ != ('\n'))
323 comperr(ETMES);
324 rep->r1.re1 = p;
325 if ((p = text(rep->r1.re1, &respace[RESIZE-1])) == NULL)
326 comperr(TMMES);
327 break;
328 case 'i':
329 rep->r1.command = ICOM;
330 if(rep->r1.ad2)
331 comperr(AD1MES);
332 if(*cp == '\\') cp++;
333 if(*cp++ != ('\n'))
334 comperr(ETMES);
335 rep->r1.re1 = p;
336 if ((p = text(rep->r1.re1, &respace[RESIZE-1])) == NULL)
337 comperr(TMMES);
338 break;
340 case 'g':
341 rep->r1.command = GCOM;
342 break;
344 case 'G':
345 rep->r1.command = CGCOM;
346 break;
348 case 'h':
349 rep->r1.command = HCOM;
350 break;
352 case 'H':
353 rep->r1.command = CHCOM;
354 break;
356 case 't':
357 rep->r1.command = TCOM;
358 goto jtcommon;
360 case 'b':
361 rep->r1.command = BCOM;
362 jtcommon:
363 while(*cp++ == ' ');
364 cp--;
366 if(*cp == '\0') {
367 if(pt = labtab->chain) {
368 while(pt1 = pt->r2.lb1)
369 pt = pt1;
370 pt->r2.lb1 = rep;
371 } else
372 labtab->chain = rep;
373 break;
375 tp = lab->asc;
376 while((*tp++ = *cp++))
377 if(tp >= &(lab->asc[9]))
378 comperr(LTL);
379 cp--;
380 *--tp = '\0';
382 if(lpt = search(lab)) {
383 if(lpt->address) {
384 rep->r2.lb1 = lpt->address;
385 } else {
386 pt = lpt->chain;
387 while(pt1 = pt->r2.lb1)
388 pt = pt1;
389 pt->r2.lb1 = rep;
391 } else {
392 lab->chain = rep;
393 lab->address = 0;
394 if(++lab >= labend)
395 comperr("Too many labels: %s");
397 break;
399 case 'n':
400 rep->r1.command = NCOM;
401 break;
403 case 'N':
404 rep->r1.command = CNCOM;
405 break;
407 case 'p':
408 rep->r1.command = PCOM;
409 break;
411 case 'P':
412 rep->r1.command = CPCOM;
413 break;
415 case 'r':
416 rep->r1.command = RCOM;
417 if(rep->r1.ad2)
418 comperr(AD1MES);
419 if(*cp++ != ' ')
420 comperr(SMMES);
421 rep->r1.re1 = p;
422 if ((p = text(rep->r1.re1, &respace[RESIZE-1])) == NULL)
423 comperr(TMMES);
424 break;
426 case 'd':
427 rep->r1.command = DCOM;
428 break;
430 case 'D':
431 rep->r1.command = CDCOM;
432 rep->r2.lb1 = ptrspace;
433 break;
435 case 'q':
436 rep->r1.command = QCOM;
437 if(rep->r1.ad2)
438 comperr(AD1MES);
439 break;
441 case 'l':
442 rep->r1.command = LCOM;
443 break;
445 case 's':
446 rep->r1.command = SCOM;
447 sseof = *cp++;
448 rep->r1.re1 = p;
449 p = comple((char *) 0, rep->r1.re1, &respace[RESIZE-1], sseof);
450 if(p == rep->r1.re1) {
451 if(op)
452 rep->r1.re1 = op;
453 else
454 comperr("First RE may not be null: %s");
455 } else
456 op = rep->r1.re1;
457 rep->r1.rhs = p;
459 p = compsub(rep->r1.rhs);
461 if(*cp == 'g') {
462 cp++;
463 rep->r1.gfl = 999;
464 } else if(gflag)
465 rep->r1.gfl = 999;
467 if(*cp >= '1' && *cp <= '9')
468 {i = *cp - '0';
469 cp++;
470 while(1)
471 {ii = *cp;
472 if(ii < '0' || ii > '9') break;
473 i = i*10 + ii - '0';
474 if(i > 512)
475 comperr(TOOBIG);
476 cp++;
478 rep->r1.gfl = i;
481 if(*cp == 'p') {
482 cp++;
483 rep->r1.pfl = 1;
486 if(*cp == 'P') {
487 cp++;
488 rep->r1.pfl = 2;
491 if(*cp == 'w') {
492 cp++;
493 if(*cp++ != ' ')
494 comperr(SMMES);
495 if (text(fnamebuf, &fnamebuf[MAXPATHLEN]) == NULL)
496 comperr("File name too long: %s");
497 for(i = nfiles - 1; i >= 0; i--)
498 if(strcmp(fnamebuf,fname[i]) == 0) {
499 rep->r1.fcode = fcode[i];
500 goto done;
502 if(nfiles >= NWFILES)
503 comperr("Too many files in w commands: %s");
505 i = strlen(fnamebuf) + 1;
506 if ((fname[nfiles] = malloc((unsigned)i)) == NULL) {
507 (void) fprintf(stderr, "sed: Out of memory\n");
508 exit(2);
510 (void) strcpy(fname[nfiles], fnamebuf);
511 if((rep->r1.fcode = fopen(fname[nfiles], "w")) == NULL) {
512 (void) fprintf(stderr, "sed: Cannot open ");
513 perror(fname[nfiles]);
514 exit(2);
516 fcode[nfiles++] = rep->r1.fcode;
518 break;
520 case 'w':
521 rep->r1.command = WCOM;
522 if(*cp++ != ' ')
523 comperr(SMMES);
524 if (text(fnamebuf, &fnamebuf[MAXPATHLEN]) == NULL)
525 comperr("File name too long: %s");
526 for(i = nfiles - 1; i >= 0; i--)
527 if(strcmp(fnamebuf, fname[i]) == 0) {
528 rep->r1.fcode = fcode[i];
529 goto done;
531 if(nfiles >= NWFILES)
532 comperr("Too many files in w commands: %s");
534 i = strlen(fnamebuf) + 1;
535 if ((fname[nfiles] = malloc((unsigned)i)) == NULL) {
536 (void) fprintf(stderr, "sed: Out of memory\n");
537 exit(2);
539 (void) strcpy(fname[nfiles], fnamebuf);
540 if((rep->r1.fcode = fopen(fname[nfiles], "w")) == NULL) {
541 (void) fprintf(stderr, "sed: Cannot create ");
542 perror(fname[nfiles]);
543 exit(2);
545 fcode[nfiles++] = rep->r1.fcode;
546 break;
548 case 'x':
549 rep->r1.command = XCOM;
550 break;
552 case 'y':
553 rep->r1.command = YCOM;
554 sseof = *cp++;
555 rep->r1.re1 = p;
556 p = ycomp(rep->r1.re1);
557 break;
560 done:
561 if(++rep >= ptrend)
562 comperr("Too many commands, last: %s");
564 rep->r1.ad1 = p;
566 if(*cp++ != '\0') {
567 if(cp[-1] == ';')
568 goto comploop;
569 comperr(ETMES);
572 rep->r1.command = 0;
573 lastre = op;
576 char *compsub(rhsbuf)
577 char *rhsbuf;
579 char *p, *q;
581 p = rhsbuf;
582 q = cp;
583 for(;;) {
584 if(p > &respace[RESIZE-1])
585 comperr(TMMES);
586 if((*p = *q++) == '\\') {
587 p++;
588 if(p > &respace[RESIZE-1])
589 comperr(TMMES);
590 *p = *q++;
591 if(*p > nbra + '0' && *p <= '9')
592 comperr("``\\digit'' out of range: %s");
593 p++;
594 continue;
596 if(*p == sseof) {
597 *p++ = '\0';
598 cp = q;
599 return(p);
601 if(*p++ == '\0')
602 comperr("Ending delimiter missing on substitution: %s");
608 rline(lbuf, lbend)
609 char *lbuf;
610 char *lbend;
612 char *p, *q;
613 int t;
614 static char *saveq;
616 p = lbuf;
618 if(eflag) {
619 if(eflag > 0) {
620 eflag = -1;
621 if(--eargc <= 0)
622 exit(2);
623 q = *++eargv;
624 while((t = *q++) != '\0') {
625 if(t == '\n') {
626 saveq = q;
627 goto out1;
629 if (p < lbend)
630 *p++ = t;
631 if(t == '\\') {
632 if((t = *q++) == '\0') {
633 saveq = 0;
634 return(-1);
636 if (p < lbend)
637 *p++ = t;
640 saveq = 0;
642 out1:
643 if (p == lbend)
644 comperr("Command line too long");
645 *p = '\0';
646 return(1);
648 if((q = saveq) == 0) return(-1);
650 while((t = *q++) != '\0') {
651 if(t == '\n') {
652 saveq = q;
653 goto out2;
655 if(p < lbend)
656 *p++ = t;
657 if(t == '\\') {
658 if((t = *q++) == '\0') {
659 saveq = 0;
660 return(-1);
662 if (p < lbend)
663 *p++ = t;
666 saveq = 0;
668 out2:
669 if (p == lbend)
670 comperr("Command line too long");
671 *p = '\0';
672 return(1);
675 while((t = getc(fin)) != EOF) {
676 if(t == '\n') {
677 if (p == lbend)
678 comperr("Command line too long");
679 *p = '\0';
680 return(1);
682 if (p < lbend)
683 *p++ = t;
684 if(t == '\\') {
685 if((t = getc(fin)) == EOF)
686 break;
687 if(p < lbend)
688 *p++ = t;
691 if(ferror(fin)) {
692 perror("sed: Error reading pattern file");
693 exit(2);
695 return(-1);
698 char *address(expbuf)
699 char *expbuf;
701 char *rcp;
702 long long lno;
704 if(*cp == '$') {
705 if (expbuf > &respace[RESIZE-2])
706 comperr(TMMES);
707 cp++;
708 *expbuf++ = CEND;
709 *expbuf++ = CCEOF;
710 return(expbuf);
712 if (*cp == '/' || *cp == '\\' ) {
713 if ( *cp == '\\' )
714 cp++;
715 sseof = *cp++;
716 return(comple((char *) 0, expbuf, &respace[RESIZE-1], sseof));
719 rcp = cp;
720 lno = 0;
722 while(*rcp >= '0' && *rcp <= '9')
723 lno = lno*10 + *rcp++ - '0';
725 if(rcp > cp) {
726 if (expbuf > &respace[RESIZE-3])
727 comperr(TMMES);
728 *expbuf++ = CLNUM;
729 *expbuf++ = nlno;
730 tlno[nlno++] = lno;
731 if(nlno >= NLINES)
732 comperr("Too many line numbers: %s");
733 *expbuf++ = CCEOF;
734 cp = rcp;
735 return(expbuf);
737 return(0);
740 char *text(textbuf, tbend)
741 char *textbuf;
742 char *tbend;
744 char *p, *q;
746 p = textbuf;
747 q = cp;
748 #ifndef S5EMUL
750 * Strip off indentation from text to be inserted.
752 while(*q == '\t' || *q == ' ') q++;
753 #endif
754 for(;;) {
756 if(p > tbend)
757 return(NULL); /* overflowed the buffer */
758 if((*p = *q++) == '\\')
759 *p = *q++;
760 if(*p == '\0') {
761 cp = --q;
762 return(++p);
764 #ifndef S5EMUL
766 * Strip off indentation from text to be inserted.
768 if(*p == '\n') {
769 while(*q == '\t' || *q == ' ') q++;
771 #endif
772 p++;
777 struct label *search(ptr)
778 struct label *ptr;
780 struct label *rp;
782 rp = labtab;
783 while(rp < ptr) {
784 if(strcmp(rp->asc, ptr->asc) == 0)
785 return(rp);
786 rp++;
789 return(0);
793 static void
794 dechain(void)
796 struct label *lptr;
797 union reptr *rptr, *trptr;
799 for(lptr = labtab; lptr < lab; lptr++) {
801 if(lptr->address == 0) {
802 (void) fprintf(stderr, "sed: Undefined label: %s\n", lptr->asc);
803 exit(2);
806 if(lptr->chain) {
807 rptr = lptr->chain;
808 while(trptr = rptr->r2.lb1) {
809 rptr->r2.lb1 = lptr->address;
810 rptr = trptr;
812 rptr->r2.lb1 = lptr->address;
817 char *ycomp(expbuf)
818 char *expbuf;
820 char c;
821 char *ep, *tsp;
822 int i;
823 char *sp;
825 ep = expbuf;
826 if(ep + 0377 > &respace[RESIZE-1])
827 comperr(TMMES);
828 sp = cp;
829 for(tsp = cp; (c = *tsp) != sseof; tsp++) {
830 if(c == '\\')
831 tsp++;
832 if(c == '\0' || c == '\n')
833 comperr("Ending delimiter missing on string: %s");
835 tsp++;
837 while((c = *sp++) != sseof) {
838 c &= 0377;
839 if(c == '\\' && *sp == 'n') {
840 sp++;
841 c = '\n';
843 if((ep[c] = *tsp++) == '\\' && *tsp == 'n') {
844 ep[c] = '\n';
845 tsp++;
847 if(ep[c] == sseof || ep[c] == '\0')
848 comperr("Transform strings not the same size: %s");
850 if(*tsp != sseof) {
851 if(*tsp == '\0')
852 comperr("Ending delimiter missing on string: %s");
853 else
854 comperr("Transform strings not the same size: %s");
856 cp = ++tsp;
858 for(i = 0; i < 0400; i++)
859 if(ep[i] == 0)
860 ep[i] = i;
862 return(ep + 0400);
865 void
866 comperr(char *msg)
868 (void) fprintf(stderr, "sed: ");
869 (void) fprintf(stderr, msg, linebuf);
870 (void) putc('\n', stderr);
871 exit(2);