]> granicus.if.org Git - apache/blob - modules/filters/sed0.c
mod_cache: Don't add cached/revalidated entity headers to a 304 response.
[apache] / modules / filters / sed0.c
1 /*
2  * Copyright (c) 2005, 2008 Sun Microsystems, Inc. All Rights Reserved.
3  * Use is subject to license terms.
4  *
5  *      Copyright (c) 1984 AT&T
6  *        All Rights Reserved
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *  http://www.apache.org/licenses/LICENSE-2.0.
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
16  * or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21 #include "apr.h"
22 #include "apr_strings.h"
23 #include "libsed.h"
24 #include "sed.h"
25 #include "regexp.h"
26
27 #define CCEOF 22
28
29 static int fcomp(sed_commands_t *commands, apr_file_t *fin);
30 static char *compsub(sed_commands_t *commands,
31                      sed_comp_args *compargs, char *rhsbuf);
32 static int rline(sed_commands_t *commands, apr_file_t *fin,
33                  char *lbuf, char *lbend);
34 static char *address(sed_commands_t *commands, char *expbuf,
35                      apr_status_t* status);
36 static char *text(sed_commands_t *commands, char *textbuf, char *endbuf);
37 static sed_label_t *search(sed_commands_t *commands);
38 static char *ycomp(sed_commands_t *commands, char *expbuf);
39 static char *comple(sed_commands_t *commands, sed_comp_args *compargs,
40                     char *x1, char *ep, char *x3, char x4);
41 static sed_reptr_t *alloc_reptr(sed_commands_t *commands);
42 static int check_finalized(const sed_commands_t *commands);
43
44 void command_errf(sed_commands_t *commands, const char *fmt, ...)
45 {
46     if (commands->errfn && commands->pool) {
47         va_list args;
48         const char* error;
49         va_start(args, fmt);
50         error = apr_pvsprintf(commands->pool, fmt, args);
51         commands->errfn(commands->data, error);
52         va_end(args);
53     }
54 }
55
56 /*
57  * sed_init_commands
58  */
59 apr_status_t sed_init_commands(sed_commands_t *commands, sed_err_fn_t *errfn, void *data,
60                                apr_pool_t *p)
61 {
62     memset(commands, 0, sizeof(*commands));
63
64     commands->errfn = errfn;
65     commands->data = data;
66
67     commands->labtab = commands->ltab;
68     commands->lab = commands->labtab + 1;
69     commands->pool = p;
70
71     commands->respace = apr_pcalloc(p, RESIZE);
72     if (commands->respace == NULL) {
73         command_errf(commands, SEDERR_OOMMES);
74         return APR_EGENERAL;
75     }
76
77     commands->rep = alloc_reptr(commands);
78     if (commands->rep == NULL)
79         return APR_EGENERAL;
80
81     commands->rep->ad1 = commands->respace;
82     commands->reend = &commands->respace[RESIZE - 1];
83     commands->labend = &commands->labtab[SED_LABSIZE];
84     commands->canbefinal = 1;
85
86     return APR_SUCCESS;
87 }
88
89 /*
90  * sed_destroy_commands
91  */
92 void sed_destroy_commands(sed_commands_t *commands)
93 {
94 }
95
96 /*
97  * sed_compile_string
98  */
99 apr_status_t sed_compile_string(sed_commands_t *commands, const char *s)
100 {
101     apr_status_t rv;
102
103     commands->earg = s;
104     commands->eflag = 1;
105
106     rv = fcomp(commands, NULL);
107     if (rv == APR_SUCCESS)
108         commands->canbefinal = check_finalized(commands);
109
110     commands->eflag = 0;
111
112     return (rv != 0 ? APR_EGENERAL : APR_SUCCESS);
113 }
114
115 /*
116  * sed_compile_file
117  */
118 apr_status_t sed_compile_file(sed_commands_t *commands, apr_file_t *fin)
119 {
120     apr_status_t rv = fcomp(commands, fin);
121     return (rv != 0 ? APR_EGENERAL : APR_SUCCESS);
122 }
123
124 /*
125  * sed_get_finalize_error
126  */
127 char* sed_get_finalize_error(const sed_commands_t *commands, apr_pool_t* pool)
128 {
129     const sed_label_t *lab;
130     if (commands->depth) {
131         return SEDERR_TMOMES;
132     }
133
134     /* Empty branch chain is not a issue */
135     for (lab = commands->labtab + 1; lab < commands->lab; lab++) {
136         char *error;
137         if (lab->address == 0) {
138             error = apr_psprintf(pool, SEDERR_ULMES, lab->asc);
139             return error;
140         }
141
142         if (lab->chain) {
143             return SEDERR_INTERNAL;
144         }
145     }
146     return NULL;
147 }
148
149 /*
150  * sed_canbe_finalized
151  */
152 int sed_canbe_finalized(const sed_commands_t *commands)
153 {
154     return commands->canbefinal;
155 }
156
157 /*
158  * check_finalized
159  */
160 static int check_finalized(const sed_commands_t *commands)
161 {
162     const sed_label_t *lab;
163     if (commands->depth) {
164         return 0;
165     }
166
167     /* Empty branch chain is not a issue */
168     for (lab = commands->labtab + 1; lab < commands->lab; lab++) {
169         if (lab->address == 0 || (lab->chain)) {
170             return 0;
171         }
172     }
173     return 1;
174 }
175
176 /*
177  * dechain
178  */
179 static void dechain(sed_label_t *lpt, sed_reptr_t *address)
180 {
181     sed_reptr_t *rep;
182     if ((lpt == NULL) || (lpt->chain == NULL) || (address == NULL))
183         return;
184     rep = lpt->chain;
185     while (rep->lb1) {
186         sed_reptr_t *next;
187
188         next = rep->lb1;
189         rep->lb1 = address;
190         rep = next;
191     }
192     rep->lb1 = address;
193     lpt->chain = NULL;
194 }
195
196 /*
197  * fcomp
198  */
199 static int fcomp(sed_commands_t *commands, apr_file_t *fin)
200 {
201     char *p, *op, *tp;
202     sed_reptr_t *pt, *pt1;
203     int i, ii;
204     sed_label_t *lpt;
205     char fnamebuf[APR_PATH_MAX];
206     apr_status_t status;
207     sed_comp_args compargs;
208
209     op = commands->lastre;
210     if (!commands->linebuf) {
211         commands->linebuf = apr_pcalloc(commands->pool, LBSIZE + 1);
212     }
213
214     if (rline(commands, fin, commands->linebuf,
215               (commands->linebuf + LBSIZE + 1)) < 0)
216         return 0;
217     if (*commands->linebuf == '#') {
218         if (commands->linebuf[1] == 'n')
219             commands->nflag = 1;
220     }
221     else {
222         commands->cp = commands->linebuf;
223         goto comploop;
224     }
225
226     for (;;) {
227         if (rline(commands, fin, commands->linebuf,
228                   (commands->linebuf + LBSIZE + 1)) < 0)
229             break;
230
231         commands->cp = commands->linebuf;
232
233 comploop:
234         while (*commands->cp == ' ' || *commands->cp == '\t')
235             commands->cp++;
236         if (*commands->cp == '\0' || *commands->cp == '#')
237             continue;
238         if (*commands->cp == ';') {
239             commands->cp++;
240             goto comploop;
241         }
242
243         p = address(commands, commands->rep->ad1, &status);
244         if (status != APR_SUCCESS) {
245             command_errf(commands, SEDERR_CGMES, commands->linebuf);
246             return -1;
247         }
248
249         if (p == commands->rep->ad1) {
250             if (op)
251                 commands->rep->ad1 = op;
252             else {
253                 command_errf(commands, SEDERR_NRMES);
254                 return -1;
255             }
256         } else if (p == 0) {
257             p = commands->rep->ad1;
258             commands->rep->ad1 = 0;
259         } else {
260             op = commands->rep->ad1;
261             if (*commands->cp == ',' || *commands->cp == ';') {
262                 commands->cp++;
263                 commands->rep->ad2 = p;
264                 p = address(commands, commands->rep->ad2, &status);
265                 if ((status != APR_SUCCESS) || (p == 0)) {
266                     command_errf(commands, SEDERR_CGMES, commands->linebuf);
267                     return -1;
268                 }
269                 if (p == commands->rep->ad2)
270                     commands->rep->ad2 = op;
271                 else
272                     op = commands->rep->ad2;
273             } else
274                 commands->rep->ad2 = 0;
275         }
276
277         if(p > &commands->respace[RESIZE-1]) {
278             command_errf(commands, SEDERR_TMMES, commands->linebuf);
279             return -1;
280         }
281
282         while (*commands->cp == ' ' || *commands->cp == '\t')
283             commands->cp++;
284
285 swit:
286         switch(*commands->cp++) {
287         default:
288             command_errf(commands, SEDERR_UCMES, commands->linebuf);
289             return -1;
290
291         case '!':
292             commands->rep->negfl = 1;
293             goto swit;
294
295         case '{':
296             commands->rep->command = BCOM;
297             commands->rep->negfl = !(commands->rep->negfl);
298             commands->cmpend[commands->depth++] = &commands->rep->lb1;
299             commands->rep = alloc_reptr(commands);
300             commands->rep->ad1 = p;
301             if (*commands->cp == '\0')
302                 continue;
303             goto comploop;
304
305         case '}':
306             if (commands->rep->ad1) {
307                 command_errf(commands, SEDERR_AD0MES, commands->linebuf);
308                 return -1;
309             }
310
311             if (--commands->depth < 0) {
312                 command_errf(commands, SEDERR_TMCMES);
313                 return -1;
314             }
315             *commands->cmpend[commands->depth] = commands->rep;
316
317             commands->rep->ad1 = p;
318             continue;
319
320         case '=':
321             commands->rep->command = EQCOM;
322             if (commands->rep->ad2) {
323                 command_errf(commands, SEDERR_AD1MES, commands->linebuf);
324                 return -1;
325             }
326             break;
327
328         case ':':
329             if (commands->rep->ad1) {
330                 command_errf(commands, SEDERR_AD0MES, commands->linebuf);
331                 return -1;
332             }
333
334             while (*commands->cp++ == ' ');
335             commands->cp--;
336
337             tp = commands->lab->asc;
338             while ((*tp++ = *commands->cp++)) {
339                 if (tp >= &(commands->lab->asc[8])) {
340                     command_errf(commands, SEDERR_LTLMES, commands->linebuf);
341                     return -1;
342                 }
343             }
344             *--tp = '\0';
345
346             if ((lpt = search(commands)) != NULL) {
347                 if (lpt->address) {
348                     command_errf(commands, SEDERR_DLMES, commands->linebuf);
349                     return -1;
350                 }
351                 dechain(lpt, commands->rep);
352             } else {
353                 commands->lab->chain = 0;
354                 lpt = commands->lab;
355                 if (++commands->lab >= commands->labend) {
356                     command_errf(commands, SEDERR_TMLMES, commands->linebuf);
357                     return -1;
358                 }
359             }
360             lpt->address = commands->rep;
361             commands->rep->ad1 = p;
362
363             continue;
364
365         case 'a':
366             commands->rep->command = ACOM;
367             if (commands->rep->ad2) {
368                 command_errf(commands, SEDERR_AD1MES, commands->linebuf);
369                 return -1;
370             }
371             if (*commands->cp == '\\')
372                 commands->cp++;
373             if (*commands->cp++ != '\n') {
374                 command_errf(commands, SEDERR_CGMES, commands->linebuf);
375                 return -1;
376             }
377             commands->rep->re1 = p;
378             p = text(commands, commands->rep->re1, commands->reend);
379             if (p == NULL)
380                 return -1;
381             break;
382
383         case 'c':
384             commands->rep->command = CCOM;
385             if (*commands->cp == '\\') commands->cp++;
386             if (*commands->cp++ != ('\n')) {
387                 command_errf(commands, SEDERR_CGMES, commands->linebuf);
388                 return -1;
389             }
390             commands->rep->re1 = p;
391             p = text(commands, commands->rep->re1, commands->reend);
392             if (p == NULL)
393                 return -1;
394             break;
395
396         case 'i':
397             commands->rep->command = ICOM;
398             if (commands->rep->ad2) {
399                 command_errf(commands, SEDERR_AD1MES, commands->linebuf);
400                 return -1;
401             }
402             if (*commands->cp == '\\') commands->cp++;
403             if (*commands->cp++ != ('\n')) {
404                 command_errf(commands, SEDERR_CGMES, commands->linebuf);
405                 return -1;
406             }
407             commands->rep->re1 = p;
408             p = text(commands, commands->rep->re1, commands->reend);
409             if (p == NULL)
410                 return -1;
411             break;
412
413         case 'g':
414             commands->rep->command = GCOM;
415             break;
416
417         case 'G':
418             commands->rep->command = CGCOM;
419             break;
420
421         case 'h':
422             commands->rep->command = HCOM;
423             break;
424
425         case 'H':
426             commands->rep->command = CHCOM;
427             break;
428
429         case 't':
430             commands->rep->command = TCOM;
431             goto jtcommon;
432
433         case 'b':
434             commands->rep->command = BCOM;
435 jtcommon:
436             while (*commands->cp++ == ' ');
437             commands->cp--;
438
439             if (*commands->cp == '\0') {
440                 if ((pt = commands->labtab->chain) != NULL) {
441                     while ((pt1 = pt->lb1) != NULL)
442                         pt = pt1;
443                     pt->lb1 = commands->rep;
444                 } else
445                     commands->labtab->chain = commands->rep;
446                 break;
447             }
448             tp = commands->lab->asc;
449             while ((*tp++ = *commands->cp++))
450                 if (tp >= &(commands->lab->asc[8])) {
451                     command_errf(commands, SEDERR_LTLMES, commands->linebuf);
452                     return -1;
453                 }
454             commands->cp--;
455             *--tp = '\0';
456
457             if ((lpt = search(commands)) != NULL) {
458                 if (lpt->address) {
459                     commands->rep->lb1 = lpt->address;
460                 } else {
461                     pt = lpt->chain;
462                     while ((pt1 = pt->lb1) != NULL)
463                         pt = pt1;
464                     pt->lb1 = commands->rep;
465                 }
466             } else {
467                 commands->lab->chain = commands->rep;
468                 commands->lab->address = 0;
469                 if (++commands->lab >= commands->labend) {
470                     command_errf(commands, SEDERR_TMLMES, commands->linebuf);
471                     return -1;
472                 }
473             }
474             break;
475
476         case 'n':
477             commands->rep->command = NCOM;
478             break;
479
480         case 'N':
481             commands->rep->command = CNCOM;
482             break;
483
484         case 'p':
485             commands->rep->command = PCOM;
486             break;
487
488         case 'P':
489             commands->rep->command = CPCOM;
490             break;
491
492         case 'r':
493             commands->rep->command = RCOM;
494             if (commands->rep->ad2) {
495                 command_errf(commands, SEDERR_AD1MES, commands->linebuf);
496                 return -1;
497             }
498             if (*commands->cp++ != ' ') {
499                 command_errf(commands, SEDERR_CGMES, commands->linebuf);
500                 return -1;
501             }
502             commands->rep->re1 = p;
503             p = text(commands, commands->rep->re1, commands->reend);
504             if (p == NULL)
505                 return -1;
506             break;
507
508         case 'd':
509             commands->rep->command = DCOM;
510             break;
511
512         case 'D':
513             commands->rep->command = CDCOM;
514             commands->rep->lb1 = commands->ptrspace;
515             break;
516
517         case 'q':
518             commands->rep->command = QCOM;
519             if (commands->rep->ad2) {
520                 command_errf(commands, SEDERR_AD1MES, commands->linebuf);
521                 return -1;
522             }
523             break;
524
525         case 'l':
526             commands->rep->command = LCOM;
527             break;
528
529         case 's':
530             commands->rep->command = SCOM;
531             commands->sseof = *commands->cp++;
532             commands->rep->re1 = p;
533             p = comple(commands, &compargs, (char *) 0, commands->rep->re1,
534                        commands->reend, commands->sseof);
535             if (p == NULL)
536                 return -1;
537             if (p == commands->rep->re1) {
538                 if (op)
539                     commands->rep->re1 = op;
540                 else {
541                     command_errf(commands, SEDERR_NRMES);
542                     return -1;
543                 }
544             } else
545                 op = commands->rep->re1;
546             commands->rep->rhs = p;
547
548             p = compsub(commands, &compargs, commands->rep->rhs);
549             if ((p) == NULL)
550                 return -1;
551
552             if (*commands->cp == 'g') {
553                 commands->cp++;
554                 commands->rep->gfl = 999;
555             } else if (commands->gflag)
556                 commands->rep->gfl = 999;
557
558             if (*commands->cp >= '1' && *commands->cp <= '9') {
559                 i = *commands->cp - '0';
560                 commands->cp++;
561                 while (1) {
562                     ii = *commands->cp;
563                     if (ii < '0' || ii > '9')
564                         break;
565                     i = i*10 + ii - '0';
566                     if (i > 512) {
567                         command_errf(commands, SEDERR_TOOBIG, commands->linebuf);
568                         return -1;
569                     }
570                     commands->cp++;
571                 }
572                 commands->rep->gfl = i;
573             }
574
575             if (*commands->cp == 'p') {
576                 commands->cp++;
577                 commands->rep->pfl = 1;
578             }
579
580             if (*commands->cp == 'P') {
581                 commands->cp++;
582                 commands->rep->pfl = 2;
583             }
584
585             if (*commands->cp == 'w') {
586                 commands->cp++;
587                 if (*commands->cp++ !=  ' ') {
588                     command_errf(commands, SEDERR_SMMES, commands->linebuf);
589                     return -1;
590                 }
591                 if (text(commands, fnamebuf, &fnamebuf[APR_PATH_MAX]) == NULL) {
592                     command_errf(commands, SEDERR_FNTL, commands->linebuf);
593                     return -1;
594                 }
595                 for (i = commands->nfiles - 1; i >= 0; i--)
596                     if (strcmp(fnamebuf,commands->fname[i]) == 0) {
597                         commands->rep->findex = i;
598                         goto done;
599                     }
600                 if (commands->nfiles >= NWFILES) {
601                     command_errf(commands, SEDERR_TMWFMES);
602                     return -1;
603                 }
604                 commands->fname[commands->nfiles] =
605                             apr_pstrdup(commands->pool, fnamebuf);
606                 if (commands->fname[commands->nfiles] == NULL) {
607                     command_errf(commands, SEDERR_OOMMES);
608                     return -1;
609                 }
610                 commands->rep->findex = commands->nfiles++;
611             }
612             break;
613
614         case 'w':
615             commands->rep->command = WCOM;
616             if (*commands->cp++ != ' ') {
617                 command_errf(commands, SEDERR_SMMES, commands->linebuf);
618                 return -1;
619             }
620             if (text(commands, fnamebuf, &fnamebuf[APR_PATH_MAX]) == NULL) {
621                 command_errf(commands, SEDERR_FNTL, commands->linebuf);
622                 return -1;
623             }
624             for (i = commands->nfiles - 1; i >= 0; i--)
625                 if (strcmp(fnamebuf, commands->fname[i]) == 0) {
626                     commands->rep->findex = i;
627                     goto done;
628                 }
629             if (commands->nfiles >= NWFILES) {
630                 command_errf(commands, SEDERR_TMWFMES);
631                 return -1;
632             }
633             if ((commands->fname[commands->nfiles] =
634                         apr_pstrdup(commands->pool, fnamebuf)) == NULL) {
635                 command_errf(commands, SEDERR_OOMMES);
636                 return -1;
637             }
638
639             commands->rep->findex = commands->nfiles++;
640             break;
641
642         case 'x':
643             commands->rep->command = XCOM;
644             break;
645
646         case 'y':
647             commands->rep->command = YCOM;
648             commands->sseof = *commands->cp++;
649             commands->rep->re1 = p;
650             p = ycomp(commands, commands->rep->re1);
651             if (p == NULL)
652                 return -1;
653             break;
654         }
655 done:
656         commands->rep = alloc_reptr(commands);
657
658         commands->rep->ad1 = p;
659
660         if (*commands->cp++ != '\0') {
661             if (commands->cp[-1] == ';')
662                 goto comploop;
663             command_errf(commands, SEDERR_CGMES, commands->linebuf);
664             return -1;
665         }
666     }
667     commands->rep->command = 0;
668     commands->lastre = op;
669
670     return 0;
671 }
672
673 static char *compsub(sed_commands_t *commands,
674                      sed_comp_args *compargs, char *rhsbuf)
675 {
676     char   *p, *q;
677
678     p = rhsbuf;
679     q = commands->cp;
680     for(;;) {
681         if(p > &commands->respace[RESIZE-1]) {
682             command_errf(commands, SEDERR_TMMES, commands->linebuf);
683             return NULL;
684         }
685         if((*p = *q++) == '\\') {
686             p++;
687             if(p > &commands->respace[RESIZE-1]) {
688                 command_errf(commands, SEDERR_TMMES, commands->linebuf);
689                 return NULL;
690             }
691             *p = *q++;
692             if(*p > compargs->nbra + '0' && *p <= '9') {
693                 command_errf(commands, SEDERR_DOORNG, commands->linebuf);
694                 return NULL;
695             }
696             p++;
697             continue;
698         }
699         if(*p == commands->sseof) {
700             *p++ = '\0';
701             commands->cp = q;
702             return(p);
703         }
704           if(*p++ == '\0') {
705             command_errf(commands, SEDERR_EDMOSUB, commands->linebuf);
706             return NULL;
707         }
708     }
709 }
710
711 /*
712  * rline
713  */
714 static int rline(sed_commands_t *commands, apr_file_t *fin,
715                  char *lbuf, char *lbend)
716 {
717     char   *p;
718     const char *q;
719     int    t;
720     apr_size_t bytes_read;
721
722     p = lbuf;
723
724     if(commands->eflag) {
725         if(commands->eflag > 0) {
726             commands->eflag = -1;
727             q = commands->earg;
728             while((t = *q++) != '\0') {
729                 if(t == '\n') {
730                     commands->saveq = q;
731                     goto out1;
732                 }
733                 if (p < lbend)
734                     *p++ = t;
735                 if(t == '\\') {
736                     if((t = *q++) == '\0') {
737                         commands->saveq = NULL;
738                         return(-1);
739                     }
740                     if (p < lbend)
741                         *p++ = t;
742                 }
743             }
744             commands->saveq = NULL;
745
746         out1:
747             if (p == lbend) {
748                 command_errf(commands, SEDERR_CLTL);
749                 return -1;
750             }
751             *p = '\0';
752             return(1);
753         }
754         if((q = commands->saveq) == 0)    return(-1);
755
756         while((t = *q++) != '\0') {
757             if(t == '\n') {
758                 commands->saveq = q;
759                 goto out2;
760             }
761             if(p < lbend)
762                 *p++ = t;
763             if(t == '\\') {
764                 if((t = *q++) == '\0') {
765                     commands->saveq = NULL;
766                     return(-1);
767                 }
768                 if (p < lbend)
769                     *p++ = t;
770             }
771         }
772         commands->saveq = NULL;
773
774     out2:
775         if (p == lbend) {
776             command_errf(commands, SEDERR_CLTL);
777             return -1;
778         }
779         *p = '\0';
780         return(1);
781     }
782
783     bytes_read = 1;
784     /* XXX extremely inefficient 1 byte reads */
785     while (apr_file_read(fin, &t, &bytes_read) != APR_SUCCESS) {
786         if(t == '\n') {
787             if (p == lbend) {
788                 command_errf(commands, SEDERR_CLTL);
789                 return -1;
790             }
791             *p = '\0';
792             return(1);
793         }
794         if (p < lbend)
795             *p++ = t;
796         if(t == '\\') {
797             bytes_read = 1;
798             if (apr_file_read(fin, &t, &bytes_read) != APR_SUCCESS) {
799                 return -1;
800             }
801             if(p < lbend)
802                 *p++ = t;
803         }
804         bytes_read = 1;
805     }
806     return(-1);
807 }
808
809 /*
810  * address
811  */
812 static char *address(sed_commands_t *commands, char *expbuf,
813                      apr_status_t* status)
814 {
815     char   *rcp;
816     apr_int64_t lno;
817     sed_comp_args compargs;
818
819     *status = APR_SUCCESS;
820     if(*commands->cp == '$') {
821         if (expbuf > &commands->respace[RESIZE-2]) {
822             command_errf(commands, SEDERR_TMMES, commands->linebuf);
823             *status = APR_EGENERAL;
824             return NULL;
825         }
826         commands->cp++;
827         *expbuf++ = CEND;
828         *expbuf++ = CCEOF;
829         return(expbuf);
830     }
831     if (*commands->cp == '/' || *commands->cp == '\\' ) {
832         if ( *commands->cp == '\\' )
833             commands->cp++;
834         commands->sseof = *commands->cp++;
835         return(comple(commands, &compargs, (char *) 0, expbuf, commands->reend,
836                       commands->sseof));
837     }
838
839     rcp = commands->cp;
840     lno = 0;
841
842     while(*rcp >= '0' && *rcp <= '9')
843         lno = lno*10 + *rcp++ - '0';
844
845     if(rcp > commands->cp) {
846         if (expbuf > &commands->respace[RESIZE-3]) {
847             command_errf(commands, SEDERR_TMMES, commands->linebuf);
848             *status = APR_EGENERAL;
849             return NULL;
850         }
851         *expbuf++ = CLNUM;
852         *expbuf++ = commands->nlno;
853         commands->tlno[commands->nlno++] = lno;
854         if(commands->nlno >= SED_NLINES) {
855             command_errf(commands, SEDERR_TMLNMES);
856             *status = APR_EGENERAL;
857             return NULL;
858         }
859         *expbuf++ = CCEOF;
860         commands->cp = rcp;
861         return(expbuf);
862     }
863     return(NULL);
864 }
865
866 /*
867  * text
868  */
869 static char *text(sed_commands_t *commands, char *textbuf, char *tbend)
870 {
871     char   *p, *q;
872
873     p = textbuf;
874     q = commands->cp;
875 #ifndef S5EMUL
876     /*
877      * Strip off indentation from text to be inserted.
878      */
879     while(*q == '\t' || *q == ' ')    q++;
880 #endif
881     for(;;) {
882
883         if(p > tbend)
884             return(NULL);    /* overflowed the buffer */
885         if((*p = *q++) == '\\')
886             *p = *q++;
887         if(*p == '\0') {
888             commands->cp = --q;
889             return(++p);
890         }
891 #ifndef S5EMUL
892         /*
893          * Strip off indentation from text to be inserted.
894          */
895         if(*p == '\n') {
896             while(*q == '\t' || *q == ' ')    q++;
897         }
898 #endif
899         p++;
900     }
901 }
902
903
904 /*
905  * search
906  */
907 static sed_label_t *search(sed_commands_t *commands)
908 {
909     sed_label_t *rp;
910     sed_label_t *ptr;
911
912     rp = commands->labtab;
913     ptr = commands->lab;
914     while (rp < ptr) {
915         if (strcmp(rp->asc, ptr->asc) == 0)
916             return rp;
917         rp++;
918     }
919
920     return 0;
921 }
922
923 /*
924  * ycomp
925  */
926 static char *ycomp(sed_commands_t *commands, char *expbuf)
927 {
928     char    c;
929     int cint; /* integer value of char c */
930     char *ep, *tsp;
931     int i;
932     char    *sp;
933
934     ep = expbuf;
935     if(ep + 0377 > &commands->respace[RESIZE-1]) {
936         command_errf(commands, SEDERR_TMMES, commands->linebuf);
937         return NULL;
938     }
939     sp = commands->cp;
940     for(tsp = commands->cp; (c = *tsp) != commands->sseof; tsp++) {
941         if(c == '\\')
942             tsp++;
943         if(c == '\0' || c == '\n') {
944             command_errf(commands, SEDERR_EDMOSTR, commands->linebuf);
945             return NULL;
946         }
947     }
948     tsp++;
949     memset(ep, 0, 0400);
950
951     while((c = *sp++) != commands->sseof) {
952         c &= 0377;
953         if(c == '\\' && *sp == 'n') {
954             sp++;
955             c = '\n';
956         }
957         cint = (int) c;
958         if((ep[cint] = *tsp++) == '\\' && *tsp == 'n') {
959             ep[cint] = '\n';
960             tsp++;
961         }
962         if(ep[cint] == commands->sseof || ep[cint] == '\0') {
963             command_errf(commands, SEDERR_TSNTSS, commands->linebuf);
964         }
965     }
966     if(*tsp != commands->sseof) {
967         if(*tsp == '\0') {
968             command_errf(commands, SEDERR_EDMOSTR, commands->linebuf);
969         }
970         else {
971             command_errf(commands, SEDERR_TSNTSS, commands->linebuf);
972         }
973         return NULL;
974     }
975     commands->cp = ++tsp;
976
977     for(i = 0; i < 0400; i++)
978         if(ep[i] == 0)
979             ep[i] = i;
980
981     return(ep + 0400);
982 }
983
984 /*
985  * comple
986  */
987 static char *comple(sed_commands_t *commands, sed_comp_args *compargs,
988                     char *x1, char *ep, char *x3, char x4)
989 {
990     char *p;
991
992     p = sed_compile(commands, compargs, ep + 1, x3, x4);
993     if(p == ep + 1)
994         return(ep);
995     *ep = compargs->circf;
996     return(p);
997 }
998
999 /*
1000  * alloc_reptr
1001  */
1002 static sed_reptr_t *alloc_reptr(sed_commands_t *commands)
1003 {
1004     sed_reptr_t *var;
1005
1006     var = apr_pcalloc(commands->pool, sizeof(sed_reptr_t));
1007     if (var == NULL) {
1008         command_errf(commands, SEDERR_OOMMES);
1009         return 0;
1010     }
1011
1012     var->nrep = commands->nrep;
1013     var->findex = -1;
1014     commands->nrep++;
1015
1016     if (commands->ptrspace == NULL)
1017         commands->ptrspace = var;
1018     else
1019         commands->ptrend->next = var;
1020
1021     commands->ptrend = var;
1022     commands->labtab->address = var;
1023     return var;
1024 }
1025
1026