Home | History | Annotate | Download | only in mod_sed
      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);
    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, commands->linebuf);
    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, commands->linebuf);
    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, commands->linebuf);
    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, commands->linebuf);
    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 
   1027