]> git.lizzy.rs Git - plan9front.git/blob - sys/src/ape/cmd/sed/sed0.c
be117aabad5c5097874a37ea74db557dc4a93ed2
[plan9front.git] / sys / src / ape / cmd / sed / sed0.c
1 #include <stdlib.h>
2 #include <unistd.h>
3 #include <stdio.h>
4 #include "sed.h"
5
6 struct label    *labtab = ltab;
7 char    CGMES[] = "sed: Command garbled: %s\n";
8 char    TMMES[] = "sed: Too much text: %s\n";
9 char    LTL[]   = "sed: Label too long: %s\n";
10 char    AD0MES[]        = "sed: No addresses allowed: %s\n";
11 char    AD1MES[]        = "sed: Only one address allowed: %s\n";
12 uchar   bittab[]  = {
13                 1,
14                 2,
15                 4,
16                 8,
17                 16,
18                 32,
19                 64,
20                 128
21         };
22
23 main(int argc, char **argv)
24 {
25
26         eargc = argc;
27         eargv = (uchar**)argv;
28
29         badp = &bad;
30         aptr = abuf;
31         hspend = holdsp;
32         lab = labtab + 1;       /* 0 reserved for end-pointer */
33         rep = ptrspace;
34         rep->r1.ad1 = respace;
35         lbend = &linebuf[LBSIZE];
36         hend = &holdsp[LBSIZE];
37         lcomend = &genbuf[64];
38         ptrend = &ptrspace[PTRSIZE];
39         reend = &respace[RESIZE];
40         labend = &labtab[LABSIZE];
41         lnum = 0;
42         pending = 0;
43         depth = 0;
44         spend = linebuf;
45         hspend = holdsp;
46         fcode[0] = stdout;
47         nfiles = 1;
48         lastre = NULL;
49
50         if(eargc == 1)
51                 exit(0);
52
53
54         while (--eargc > 0 && (++eargv)[0][0] == '-')
55                 switch (eargv[0][1]) {
56
57                 case 'n':
58                         nflag++;
59                         continue;
60
61                 case 'f':
62                         if(eargc-- <= 0)        exit(2);
63
64                         if((fin = fopen((char*)(*++eargv), "r")) == NULL) {
65                                 fprintf(stderr, "sed: Cannot open pattern-file: %s\n", *eargv);
66                                 exit(2);
67                         }
68
69                         fcomp();
70                         fclose(fin);
71                         continue;
72
73                 case 'e':
74                         eflag++;
75                         fcomp();
76                         eflag = 0;
77                         continue;
78
79                 case 'g':
80                         gflag++;
81                         continue;
82
83                 default:
84                         fprintf(stderr, "sed: Unknown flag: %c\n", eargv[0][1]);
85                         continue;
86                 }
87
88
89         if(compfl == 0) {
90                 eargv--;
91                 eargc++;
92                 eflag++;
93                 fcomp();
94                 eargv++;
95                 eargc--;
96                 eflag = 0;
97         }
98
99         if(depth) {
100                 fprintf(stderr, "sed: Too many {'s\n");
101                 exit(2);
102         }
103
104         labtab->address = rep;
105
106         dechain();
107
108 /*      abort();        /*DEBUG*/
109
110         if(eargc <= 0)
111                 execute((uchar *)NULL);
112         else while(--eargc >= 0) {
113                 execute(*eargv++);
114         }
115         fclose(stdout);
116         exit(0);
117 }
118 void
119 fcomp(void)
120 {
121
122         uchar   *p, *op, *tp;
123     uchar *address(uchar*);
124         union reptr     *pt, *pt1;
125         int     i;
126         struct label    *lpt;
127
128         compfl = 1;
129         op = lastre;
130
131         if(rline(linebuf) < 0) {
132                 lastre = op;
133                 return;
134         }
135         if(*linebuf == '#') {
136                 if(linebuf[1] == 'n')
137                         nflag = 1;
138         }
139         else {
140                 cp = linebuf;
141                 goto comploop;
142         }
143
144         for(;;) {
145                 if(rline(linebuf) < 0)  break;
146
147                 cp = linebuf;
148
149 comploop:
150 /*      fprintf(stdout, "cp: %s\n", cp);        /*DEBUG*/
151                 while(*cp == ' ' || *cp == '\t')        cp++;
152                 if(*cp == '\0' || *cp == '#')           continue;
153                 if(*cp == ';') {
154                         cp++;
155                         goto comploop;
156                 }
157
158                 p = address(rep->r1.ad1);
159                 if(p == badp) {
160                         fprintf(stderr, CGMES, linebuf);
161                         exit(2);
162                 }
163
164                 if(p == 0) {
165                         p = rep->r1.ad1;
166                         rep->r1.ad1 = 0;
167                 } else {
168                         if(p == rep->r1.ad1) {
169                                 if(op)
170                                         rep->r1.ad1 = op;
171                                 else {
172                                         fprintf(stderr, "sed: First RE may not be null\n");
173                                         exit(2);
174                                 }
175                         }
176                         if(*rep->r1.ad1 != CLNUM && *rep->r1.ad1 != CEND)
177                                 op = rep->r1.ad1;
178                         if(*cp == ',' || *cp == ';') {
179                                 cp++;
180                                 if((rep->r1.ad2 = p) > reend) {
181                                         fprintf(stderr, TMMES, linebuf);
182                                         exit(2);
183                                 }
184                                 p = address(rep->r1.ad2);
185                                 if(p == badp || p == 0) {
186                                         fprintf(stderr, CGMES, linebuf);
187                                         exit(2);
188                                 }
189                                 if(p == rep->r1.ad2)
190                                         rep->r1.ad2 = op;
191                                 else{
192                                 if(*rep->r1.ad2 != CLNUM && *rep->r1.ad2 != CEND)
193                                         op = rep->r1.ad2;
194                                 }
195
196                         } else
197                                 rep->r1.ad2 = 0;
198                 }
199
200                 if(p > reend) {
201                         fprintf(stderr, "sed: Too much text: %s\n", linebuf);
202                         exit(2);
203                 }
204
205                 while(*cp == ' ' || *cp == '\t')        cp++;
206
207 swit:
208                 switch(*cp++) {
209
210                         default:
211 /*fprintf(stderr, "cp = %d; *cp = %o\n", cp - linebuf, *cp);*/
212                                 fprintf(stderr, "sed: Unrecognized command: %s\n", linebuf);
213                                 exit(2);
214
215                         case '!':
216                                 rep->r1.negfl = 1;
217                                 goto swit;
218
219                         case '{':
220                                 rep->r1.command = BCOM;
221                                 rep->r1.negfl = !(rep->r1.negfl);
222                                 cmpend[depth++] = &rep->r2.lb1;
223                                 if(++rep >= ptrend) {
224                                         fprintf(stderr, "sed: Too many commands: %s\n", linebuf);
225                                         exit(2);
226                                 }
227                                 rep->r1.ad1 = p;
228                                 if(*cp == '\0') continue;
229
230                                 goto comploop;
231
232                         case '}':
233                                 if(rep->r1.ad1) {
234                                         fprintf(stderr, AD0MES, linebuf);
235                                         exit(2);
236                                 }
237
238                                 if(--depth < 0) {
239                                         fprintf(stderr, "sed: Too many }'s\n");
240                                         exit(2);
241                                 }
242                                 *cmpend[depth] = rep;
243
244                                 rep->r1.ad1 = p;
245                                 if(*cp == 0)    continue;
246                                 goto comploop;
247
248                         case '=':
249                                 rep->r1.command = EQCOM;
250                                 if(rep->r1.ad2) {
251                                         fprintf(stderr, AD1MES, linebuf);
252                                         exit(2);
253                                 }
254                                 break;
255
256                         case ':':
257                                 if(rep->r1.ad1) {
258                                         fprintf(stderr, AD0MES, linebuf);
259                                         exit(2);
260                                 }
261
262                                 while(*cp++ == ' ');
263                                 cp--;
264
265
266                                 tp = lab->asc;
267                                 while((*tp = *cp++) && *tp != ';')
268                                         if(++tp >= &(lab->asc[8])) {
269                                                 fprintf(stderr, LTL, linebuf);
270                                                 exit(2);
271                                         }
272                                 *tp = '\0';
273                                 if(*lab->asc == 0) {
274                                         fprintf(stderr, CGMES, linebuf);
275                                         exit(2);
276                                 }
277
278                                 if(lpt = search(lab)) {
279                                         if(lpt->address) {
280                                                 fprintf(stderr, "sed: Duplicate labels: %s\n", linebuf);
281                                                 exit(2);
282                                         }
283                                 } else {
284                                         lab->chain = 0;
285                                         lpt = lab;
286                                         if(++lab >= labend) {
287                                                 fprintf(stderr, "sed: Too many labels: %s\n", linebuf);
288                                                 exit(2);
289                                         }
290                                 }
291                                 lpt->address = rep;
292                                 rep->r1.ad1 = p;
293
294                                 continue;
295
296                         case 'a':
297                                 rep->r1.command = ACOM;
298                                 if(rep->r1.ad2) {
299                                         fprintf(stderr, AD1MES, linebuf);
300                                         exit(2);
301                                 }
302                                 if(*cp == '\\') cp++;
303                                 if(*cp++ != '\n') {
304                                         fprintf(stderr, CGMES, linebuf);
305                                         exit(2);
306                                 }
307                                 rep->r1.re1 = p;
308                                 p = text(rep->r1.re1);
309                                 break;
310                         case 'c':
311                                 rep->r1.command = CCOM;
312                                 if(*cp == '\\') cp++;
313                                 if(*cp++ != ('\n')) {
314                                         fprintf(stderr, CGMES, linebuf);
315                                         exit(2);
316                                 }
317                                 rep->r1.re1 = p;
318                                 p = text(rep->r1.re1);
319                                 break;
320                         case 'i':
321                                 rep->r1.command = ICOM;
322                                 if(rep->r1.ad2) {
323                                         fprintf(stderr, AD1MES, linebuf);
324                                         exit(2);
325                                 }
326                                 if(*cp == '\\') cp++;
327                                 if(*cp++ != ('\n')) {
328                                         fprintf(stderr, CGMES, linebuf);
329                                         exit(2);
330                                 }
331                                 rep->r1.re1 = p;
332                                 p = text(rep->r1.re1);
333                                 break;
334
335                         case 'g':
336                                 rep->r1.command = GCOM;
337                                 break;
338
339                         case 'G':
340                                 rep->r1.command = CGCOM;
341                                 break;
342
343                         case 'h':
344                                 rep->r1.command = HCOM;
345                                 break;
346
347                         case 'H':
348                                 rep->r1.command = CHCOM;
349                                 break;
350
351                         case 't':
352                                 rep->r1.command = TCOM;
353                                 goto jtcommon;
354
355                         case 'b':
356                                 rep->r1.command = BCOM;
357 jtcommon:
358                                 while(*cp++ == ' ');
359                                 cp--;
360
361                                 if(*cp == '\0') {
362                                         if(pt = labtab->chain) {
363                                                 while(pt1 = pt->r2.lb1)
364                                                         pt = pt1;
365                                                 pt->r2.lb1 = rep;
366                                         } else
367                                                 labtab->chain = rep;
368                                         break;
369                                 }
370                                 tp = lab->asc;
371                                 while((*tp = *cp++) && *tp != ';')
372                                         if(++tp >= &(lab->asc[8])) {
373                                                 fprintf(stderr, LTL, linebuf);
374                                                 exit(2);
375                                         }
376                                 cp--;
377                                 *tp = '\0';
378                                 if(*lab->asc == 0) {
379                                         fprintf(stderr, CGMES, linebuf);
380                                         exit(2);
381                                 }
382
383                                 if(lpt = search(lab)) {
384                                         if(lpt->address) {
385                                                 rep->r2.lb1 = lpt->address;
386                                         } else {
387                                                 pt = lpt->chain;
388                                                 while(pt1 = pt->r2.lb1)
389                                                         pt = pt1;
390                                                 pt->r2.lb1 = rep;
391                                         }
392                                 } else {
393                                         lab->chain = rep;
394                                         lab->address = 0;
395                                         if(++lab >= labend) {
396                                                 fprintf(stderr, "sed: Too many labels: %s\n", linebuf);
397                                                 exit(2);
398                                         }
399                                 }
400                                 break;
401
402                         case 'n':
403                                 rep->r1.command = NCOM;
404                                 break;
405
406                         case 'N':
407                                 rep->r1.command = CNCOM;
408                                 break;
409
410                         case 'p':
411                                 rep->r1.command = PCOM;
412                                 break;
413
414                         case 'P':
415                                 rep->r1.command = CPCOM;
416                                 break;
417
418                         case 'r':
419                                 rep->r1.command = RCOM;
420                                 if(rep->r1.ad2) {
421                                         fprintf(stderr, AD1MES, linebuf);
422                                         exit(2);
423                                 }
424                                 if(*cp++ != ' ') {
425                                         fprintf(stderr, CGMES, linebuf);
426                                         exit(2);
427                                 }
428                                 rep->r1.re1 = p;
429                                 p = text(rep->r1.re1);
430                                 break;
431
432                         case 'd':
433                                 rep->r1.command = DCOM;
434                                 break;
435
436                         case 'D':
437                                 rep->r1.command = CDCOM;
438                                 rep->r2.lb1 = ptrspace;
439                                 break;
440
441                         case 'q':
442                                 rep->r1.command = QCOM;
443                                 if(rep->r1.ad2) {
444                                         fprintf(stderr, AD1MES, linebuf);
445                                         exit(2);
446                                 }
447                                 break;
448
449                         case 'l':
450                                 rep->r1.command = LCOM;
451                                 break;
452
453                         case 's':
454                                 rep->r1.command = SCOM;
455                                 seof = *cp++;
456                                 rep->r1.re1 = p;
457                                 p = compile(rep->r1.re1);
458                                 if(p == badp) {
459                                         fprintf(stderr, CGMES, linebuf);
460                                         exit(2);
461                                 }
462                                 if(p == rep->r1.re1) {
463                                         if(op == NULL) {
464                                                 fprintf(stderr, "sed: First RE may not be null.\n");
465                                                 exit(2);
466                                         }
467                                         rep->r1.re1 = op;
468                                 } else {
469                                         op = rep->r1.re1;
470                                 }
471
472                                 if((rep->r1.rhs = p) > reend) {
473                                         fprintf(stderr, TMMES, linebuf);
474                                         exit(2);
475                                 }
476
477                                 if((p = compsub(rep->r1.rhs)) == badp) {
478                                         fprintf(stderr, CGMES, linebuf);
479                                         exit(2);
480                                 }
481                                 if(*cp == 'g') {
482                                         cp++;
483                                         rep->r1.gfl++;
484                                 } else if(gflag)
485                                         rep->r1.gfl++;
486
487                                 if(*cp == 'p') {
488                                         cp++;
489                                         rep->r1.pfl = 1;
490                                 }
491
492                                 if(*cp == 'P') {
493                                         cp++;
494                                         rep->r1.pfl = 2;
495                                 }
496
497                                 if(*cp == 'w') {
498                                         cp++;
499                                         if(*cp++ !=  ' ') {
500                                                 fprintf(stderr, CGMES, linebuf);
501                                                 exit(2);
502                                         }
503                                         if(nfiles >= MAXFILES) {
504                                                 fprintf(stderr, "sed: Too many files in w commands 1 \n");
505                                                 exit(2);
506                                         }
507
508                                         text((uchar*)fname[nfiles]);
509                                         for(i = nfiles - 1; i >= 0; i--)
510                                                 if(cmp((uchar*)fname[nfiles],(uchar*)fname[i]) == 0) {
511                                                         rep->r1.fcode = fcode[i];
512                                                         goto done;
513                                                 }
514                                         if((rep->r1.fcode = fopen(fname[nfiles], "w")) == NULL) {
515                                                 fprintf(stderr, "sed: Cannot open %s\n", fname[nfiles]);
516                                                 exit(2);
517                                         }
518                                         fcode[nfiles++] = rep->r1.fcode;
519                                 }
520                                 break;
521
522                         case 'w':
523                                 rep->r1.command = WCOM;
524                                 if(*cp++ != ' ') {
525                                         fprintf(stderr, CGMES, linebuf);
526                                         exit(2);
527                                 }
528                                 if(nfiles >= MAXFILES){
529                                         fprintf(stderr, "sed: Too many files in w commands 2 \n");
530                                         fprintf(stderr, "nfiles = %d; MAXF = %d\n", nfiles, MAXFILES);
531                                         exit(2);
532                                 }
533
534                                 text((uchar*)fname[nfiles]);
535                                 for(i = nfiles - 1; i >= 0; i--)
536                                         if(cmp((uchar*)fname[nfiles], (uchar*)fname[i]) == 0) {
537                                                 rep->r1.fcode = fcode[i];
538                                                 goto done;
539                                         }
540
541                                 if((rep->r1.fcode = fopen(fname[nfiles], "w")) == NULL) {
542                                         fprintf(stderr, "sed: Cannot create %s\n", fname[nfiles]);
543                                         exit(2);
544                                 }
545                                 fcode[nfiles++] = rep->r1.fcode;
546                                 break;
547
548                         case 'x':
549                                 rep->r1.command = XCOM;
550                                 break;
551
552                         case 'y':
553                                 rep->r1.command = YCOM;
554                                 seof = *cp++;
555                                 rep->r1.re1 = p;
556                                 p = ycomp(rep->r1.re1);
557                                 if(p == badp) {
558                                         fprintf(stderr, CGMES, linebuf);
559                                         exit(2);
560                                 }
561                                 if(p > reend) {
562                                         fprintf(stderr, TMMES, linebuf);
563                                         exit(2);
564                                 }
565                                 break;
566
567                 }
568 done:
569                 if(++rep >= ptrend) {
570                         fprintf(stderr, "sed: Too many commands, last: %s\n", linebuf);
571                         exit(2);
572                 }
573
574                 rep->r1.ad1 = p;
575
576                 if(*cp++ != '\0') {
577                         if(cp[-1] == ';')
578                                 goto comploop;
579                         fprintf(stderr, CGMES, linebuf);
580                         exit(2);
581                 }
582
583         }
584 }
585
586 uchar   *
587 compsub(uchar *rhsbuf)
588 {
589         uchar   *p, *q, *r;
590         p = rhsbuf;
591         q = cp;
592         for(;;) {
593                 if((*p = *q++) == '\\') {
594                         *++p = *q++;
595                         if(*p >= '1' && *p <= '9' && *p > numbra + '0')
596                                 return(badp);
597                         if(*p == 'n')
598                                 *--p = '\n';
599                 } else if(*p == seof) {
600                         *p++ = '\0';
601                         cp = q;
602                         return(p);
603                 }
604                 if(*p++ == '\0') {
605                         return(badp);
606                 }
607
608         }
609 }
610
611 uchar *
612 compile(uchar *expbuf)
613 {
614         int c;
615         uchar *ep, *sp;
616         uchar   neg;
617         uchar *lastep, *cstart;
618         int cclcnt;
619         int     closed;
620         uchar   bracket[NBRA], *bracketp;
621
622         if(*cp == seof) {
623                 cp++;
624                 return(expbuf);
625         }
626
627         ep = expbuf;
628         lastep = 0;
629         bracketp = bracket;
630         closed = numbra = 0;
631         sp = cp;
632         if (*sp == '^') {
633                 *ep++ = 1;
634                 sp++;
635         } else {
636                 *ep++ = 0;
637         }
638         for (;;) {
639                 if (ep >= reend) {
640                         cp = sp;
641                         return(badp);
642                 }
643                 if((c = *sp++) == seof) {
644                         if(bracketp != bracket) {
645                                 cp = sp;
646                                 return(badp);
647                         }
648                         cp = sp;
649                         *ep++ = CEOF;
650                         return(ep);
651                 }
652                 if(c != '*')
653                         lastep = ep;
654                 switch (c) {
655
656                 case '\\':
657                         if((c = *sp++) == '(') {
658                                 if(numbra >= NBRA) {
659                                         cp = sp;
660                                         return(badp);
661                                 }
662                                 *bracketp++ = numbra;
663                                 *ep++ = CBRA;
664                                 *ep++ = numbra++;
665                                 continue;
666                         }
667                         if(c == ')') {
668                                 if(bracketp <= bracket) {
669                                         cp = sp;
670                                         return(badp);
671                                 }
672                                 *ep++ = CKET;
673                                 *ep++ = *--bracketp;
674                                 closed++;
675                                 continue;
676                         }
677
678                         if(c >= '1' && c <= '9') {
679                                 if((c -= '1') >= closed)
680                                         return(badp);
681         
682                                 *ep++ = CBACK;
683                                 *ep++ = c;
684                                 continue;
685                         }
686                         if(c == '\n') {
687                                 cp = sp;
688                                 return(badp);
689                         }
690                         if(c == 'n') {
691                                 c = '\n';
692                         }
693                         goto defchar;
694
695                 case '\0':
696                 case '\n':
697                         cp = sp;
698                         return(badp);
699
700                 case '.':
701                         *ep++ = CDOT;
702                         continue;
703
704                 case '*':
705                         if (lastep == 0)
706                                 goto defchar;
707                         if(*lastep == CKET) {
708                                 cp = sp;
709                                 return(badp);
710                         }
711                         *lastep |= STAR;
712                         continue;
713
714                 case '$':
715                         if (*sp != seof)
716                                 goto defchar;
717                         *ep++ = CDOL;
718                         continue;
719
720                 case '[':
721                         if(&ep[33] >= reend) {
722                                 fprintf(stderr, "sed: RE too long: %s\n", linebuf);
723                                 exit(2);
724                         }
725
726                         *ep++ = CCL;
727
728                         neg = 0;
729                         if((c = *sp++) == '^') {
730                                 neg = 1;
731                                 c = *sp++;
732                         }
733
734                         cstart = sp;
735                         do {
736                                 if(c == '\0') {
737                                         fprintf(stderr, CGMES, linebuf);
738                                         exit(2);
739                                 }
740                                 if (c=='-' && sp>cstart && *sp!=']') {
741                                         for (c = sp[-2]; c<*sp; c++)
742                                                 ep[c>>3] |= bittab[c&07];
743                                 }
744                                 if(c == '\\') {
745                                         switch(c = *sp++) {
746                                                 case 'n':
747                                                         c = '\n';
748                                                         break;
749                                         }
750                                 }
751
752                                 ep[c >> 3] |= bittab[c & 07];
753                         } while((c = *sp++) != ']');
754
755                         if(neg)
756                                 for(cclcnt = 0; cclcnt < 32; cclcnt++)
757                                         ep[cclcnt] ^= -1;
758                         ep[0] &= 0376;
759
760                         ep += 32;
761
762                         continue;
763
764                 defchar:
765                 default:
766                         *ep++ = CCHR;
767                         *ep++ = c;
768                 }
769         }
770 }
771 int
772 rline(uchar *lbuf)
773 {
774         uchar   *p, *q;
775         int     t;
776         static uchar    *saveq;
777
778         p = lbuf - 1;
779
780         if(eflag) {
781                 if(eflag > 0) {
782                         eflag = -1;
783                         if(eargc-- <= 0)
784                                 exit(2);
785                         q = *++eargv;
786                         while(*++p = *q++) {
787                                 if(*p == '\\') {
788                                         if((*++p = *q++) == '\0') {
789                                                 saveq = 0;
790                                                 return(-1);
791                                         } else
792                                                 continue;
793                                 }
794                                 if(*p == '\n') {
795                                         *p = '\0';
796                                         saveq = q;
797                                         return(1);
798                                 }
799                         }
800                         saveq = 0;
801                         return(1);
802                 }
803                 if((q = saveq) == 0)    return(-1);
804
805                 while(*++p = *q++) {
806                         if(*p == '\\') {
807                                 if((*++p = *q++) == '0') {
808                                         saveq = 0;
809                                         return(-1);
810                                 } else
811                                         continue;
812                         }
813                         if(*p == '\n') {
814                                 *p = '\0';
815                                 saveq = q;
816                                 return(1);
817                         }
818                 }
819                 saveq = 0;
820                 return(1);
821         }
822
823         while((t = getc(fin)) != EOF) {
824                 *++p = t;
825                 if(*p == '\\') {
826                         t = getc(fin);
827                         *++p = t;
828                 }
829                 else if(*p == '\n') {
830                         *p = '\0';
831                         return(1);
832                 }
833         }
834         *++p = '\0';
835         return(-1);
836 }
837
838 uchar *
839 address(uchar *expbuf)
840 {
841         uchar   *rcp;
842         long    lno;
843
844         if(*cp == '$') {
845                 cp++;
846                 *expbuf++ = CEND;
847                 *expbuf++ = CEOF;
848                 return(expbuf);
849         }
850
851         if(*cp == '/') {
852                 seof = '/';
853                 cp++;
854                 return(compile(expbuf));
855         }
856
857         rcp = cp;
858         lno = 0;
859
860         while(*rcp >= '0' && *rcp <= '9')
861                 lno = lno*10 + *rcp++ - '0';
862
863         if(rcp > cp) {
864                 if(!lno){
865                         fprintf(stderr, "sed: line number 0 is illegal\n");
866                         exit(2);
867                 }
868                 *expbuf++ = CLNUM;
869                 *expbuf++ = lno;
870                 *expbuf++ = lno >> 8;
871                 *expbuf++ = lno >> 16;
872                 *expbuf++ = lno >> 24;
873                 *expbuf++ = CEOF;
874                 cp = rcp;
875                 return(expbuf);
876         }
877         return(0);
878 }
879 int
880 cmp(uchar *a, uchar *b)
881 {
882         uchar   *ra, *rb;
883
884         ra = a - 1;
885         rb = b - 1;
886
887         while(*++ra == *++rb)
888                 if(*ra == '\0') return(0);
889         return(1);
890 }
891
892 uchar *
893 text(uchar *textbuf)
894 {
895         uchar   *p, *q;
896
897         p = textbuf;
898         q = cp;
899         while(*q == '\t' || *q == ' ')  q++;
900         for(;;) {
901
902                 if((*p = *q++) == '\\')
903                         *p = *q++;
904                 if(*p == '\0') {
905                         cp = --q;
906                         return(++p);
907                 }
908                 if(*p == '\n') {
909                         while(*q == '\t' || *q == ' ')  q++;
910                 }
911                 p++;
912         }
913 }
914
915
916 struct label *
917 search(struct label *ptr)
918 {
919         struct label    *rp;
920
921         rp = labtab;
922         while(rp < ptr) {
923                 if(cmp(rp->asc, ptr->asc) == 0)
924                         return(rp);
925                 rp++;
926         }
927
928         return(0);
929 }
930
931 void
932 dechain(void)
933 {
934         struct label    *lptr;
935         union reptr     *rptr, *trptr;
936
937         for(lptr = labtab; lptr < lab; lptr++) {
938
939                 if(lptr->address == 0) {
940                         fprintf(stderr, "sed: Undefined label: %s\n", lptr->asc);
941                         exit(2);
942                 }
943
944                 if(lptr->chain) {
945                         rptr = lptr->chain;
946                         while(trptr = rptr->r2.lb1) {
947                                 rptr->r2.lb1 = lptr->address;
948                                 rptr = trptr;
949                         }
950                         rptr->r2.lb1 = lptr->address;
951                 }
952         }
953 }
954
955 uchar *
956 ycomp(uchar *expbuf)
957 {
958         uchar *ep, *tsp;
959         int c;
960         uchar   *sp;
961
962         ep = expbuf;
963         sp = cp;
964         for(tsp = cp; *tsp != seof; tsp++) {
965                 if(*tsp == '\\')
966                         tsp++;
967                 if(*tsp == '\n' || *tsp == '\0')
968                         return(badp);
969         }
970         tsp++;
971
972         while((c = *sp++) != seof) {
973                 if(c == '\\' && *sp == 'n') {
974                         sp++;
975                         c = '\n';
976                 }
977                 if((ep[c] = *tsp++) == '\\' && *tsp == 'n') {
978                         ep[c] = '\n';
979                         tsp++;
980                 }
981                 if(ep[c] == seof || ep[c] == '\0')
982                         return(badp);
983         }
984         if(*tsp != seof)
985                 return(badp);
986         cp = ++tsp;
987
988         for(c = 0; c<0400; c++)
989                 if(ep[c] == 0)
990                         ep[c] = c;
991
992         return(ep + 0400);
993 }
994