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
29static int fcomp(sed_commands_t *commands, apr_file_t *fin);
30static char *compsub(sed_commands_t *commands,
31                     sed_comp_args *compargs, char *rhsbuf);
32static int rline(sed_commands_t *commands, apr_file_t *fin,
33                 char *lbuf, char *lbend);
34static char *address(sed_commands_t *commands, char *expbuf,
35                     apr_status_t* status);
36static char *text(sed_commands_t *commands, char *textbuf, char *endbuf);
37static sed_label_t *search(sed_commands_t *commands);
38static char *ycomp(sed_commands_t *commands, char *expbuf);
39static char *comple(sed_commands_t *commands, sed_comp_args *compargs,
40                    char *x1, char *ep, char *x3, char x4);
41static sed_reptr_t *alloc_reptr(sed_commands_t *commands);
42static int check_finalized(const sed_commands_t *commands);
43
44void 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 */
59apr_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 */
92void sed_destroy_commands(sed_commands_t *commands)
93{
94}
95
96/*
97 * sed_compile_string
98 */
99apr_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 */
118apr_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 */
127char* 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 */
152int sed_canbe_finalized(const sed_commands_t *commands)
153{
154    return commands->canbefinal;
155}
156
157/*
158 * check_finalized
159 */
160static 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 */
179static 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 */
199static 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
233comploop:
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
285swit:
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;
435jtcommon:
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        }
655done:
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
673static 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 */
714static 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 */
812static 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 */
869static 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 */
907static 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 */
926static 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 */
987static 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 */
1002static 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
1027