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