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_lib.h"
     23  0      jyri #include "libsed.h"
     24  0      jyri #include "sed.h"
     25  0      jyri #include "apr_strings.h"
     26  0      jyri #include "regexp.h"
     27  0      jyri 
     28  0      jyri char    *trans[040]  = {
     29  0      jyri     "\\01",
     30  0      jyri     "\\02",
     31  0      jyri     "\\03",
     32  0      jyri     "\\04",
     33  0      jyri     "\\05",
     34  0      jyri     "\\06",
     35  0      jyri     "\\07",
     36  0      jyri     "-<",
     37  0      jyri     "->",
     38  0      jyri     "\n",
     39  0      jyri     "\\13",
     40  0      jyri     "\\14",
     41  0      jyri     "\\15",
     42  0      jyri     "\\16",
     43  0      jyri     "\\17",
     44  0      jyri     "\\20",
     45  0      jyri     "\\21",
     46  0      jyri     "\\22",
     47  0      jyri     "\\23",
     48  0      jyri     "\\24",
     49  0      jyri     "\\25",
     50  0      jyri     "\\26",
     51  0      jyri     "\\27",
     52  0      jyri     "\\30",
     53  0      jyri     "\\31",
     54  0      jyri     "\\32",
     55  0      jyri     "\\33",
     56  0      jyri     "\\34",
     57  0      jyri     "\\35",
     58  0      jyri     "\\36",
     59  0      jyri     "\\37"
     60  0      jyri };
     61  0      jyri char rub[] = {"\\177"};
     62  0      jyri 
     63  0      jyri extern int sed_step(char *p1, char *p2, int circf, step_vars_storage *vars);
     64  0      jyri static int substitute(sed_eval_t *eval, sed_reptr_t *ipc,
     65  0      jyri                       step_vars_storage *step_vars);
     66  0      jyri static apr_status_t execute(sed_eval_t *eval);
     67  0      jyri static int match(sed_eval_t *eval, char *expbuf, int gf,
     68  0      jyri                  step_vars_storage *step_vars);
     69  0      jyri static apr_status_t dosub(sed_eval_t *eval, char *rhsbuf, int n,
     70  0      jyri                           step_vars_storage *step_vars);
     71  0      jyri static char *place(sed_eval_t *eval, char *asp, char *al1, char *al2);
     72  0      jyri static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc,
     73  0      jyri                             step_vars_storage *step_vars);
     74  0      jyri static void wline(sed_eval_t *eval, char *buf, int sz);
     75  0      jyri static void arout(sed_eval_t *eval);
     76  0      jyri 
     77  0      jyri static void eval_errf(sed_eval_t *eval, const char *fmt, ...)
     78  0      jyri {
     79  0      jyri     if (eval->errfn && eval->pool) {
     80  0      jyri         va_list args;
     81  0      jyri         const char* error;
     82  0      jyri         va_start(args, fmt);
     83  0      jyri         error = apr_pvsprintf(eval->pool, fmt, args);
     84  0      jyri         eval->errfn(eval->data, error);
     85  0      jyri         va_end(args);
     86  0      jyri     }
     87  0      jyri }
     88  0      jyri 
     89  6  bk139067 #define INIT_BUF_SIZE 1024
     90  6  bk139067 
     91  6  bk139067 /*
     92  6  bk139067  * grow_buffer
     93  6  bk139067  */
     94  6  bk139067 static void grow_buffer(apr_pool_t *pool, char **buffer,
     95  6  bk139067                         char **spend, unsigned int *cursize,
     96  6  bk139067                         unsigned int newsize)
     97  6  bk139067 {
     98  6  bk139067     char* newbuffer = NULL;
     99  6  bk139067     int spendsize = 0;
    100  6  bk139067     if (*cursize >= newsize)
    101  6  bk139067         return;
    102  6  bk139067     /* Align it to 4 KB boundary */
    103  6  bk139067     newsize = (newsize  + ((1 << 12) - 1)) & ~((1 << 12) -1);
    104  6  bk139067     newbuffer = apr_pcalloc(pool, newsize);
    105  6  bk139067     if (*spend && *buffer && (*cursize > 0)) {
    106  6  bk139067         spendsize = *spend - *buffer;
    107  6  bk139067     }
    108  6  bk139067     if ((*cursize > 0) && *buffer) {
    109  6  bk139067         memcpy(newbuffer, *buffer, *cursize);
    110  6  bk139067     }
    111  6  bk139067     *buffer = newbuffer;
    112  6  bk139067     *cursize = newsize;
    113  6  bk139067     if (spend != buffer) {
    114  6  bk139067         *spend = *buffer + spendsize;
    115  6  bk139067     }
    116  6  bk139067 }
    117  6  bk139067 
    118  6  bk139067 /*
    119  6  bk139067  * grow_line_buffer
    120  6  bk139067  */
    121  6  bk139067 static void grow_line_buffer(sed_eval_t *eval, int newsize)
    122  6  bk139067 {
    123  6  bk139067     grow_buffer(eval->pool, &eval->linebuf, &eval->lspend,
    124  6  bk139067                 &eval->lsize, newsize);
    125  6  bk139067 }
    126  6  bk139067 
    127  6  bk139067 /*
    128  6  bk139067  * grow_hold_buffer
    129  6  bk139067  */
    130  6  bk139067 static void grow_hold_buffer(sed_eval_t *eval, int newsize)
    131  6  bk139067 {
    132  6  bk139067     grow_buffer(eval->pool, &eval->holdbuf, &eval->hspend,
    133  6  bk139067                 &eval->hsize, newsize);
    134  6  bk139067 }
    135  6  bk139067 
    136  6  bk139067 /*
    137  6  bk139067  * grow_gen_buffer
    138  6  bk139067  */
    139  6  bk139067 static void grow_gen_buffer(sed_eval_t *eval, int newsize,
    140  6  bk139067                             char **gspend)
    141  6  bk139067 {
    142  6  bk139067     if (gspend == NULL) {
    143  6  bk139067         gspend = &eval->genbuf;
    144  6  bk139067     }
    145  6  bk139067     grow_buffer(eval->pool, &eval->genbuf, gspend,
    146  6  bk139067                 &eval->gsize, newsize);
    147  6  bk139067     eval->lcomend = &eval->genbuf[71];
    148  6  bk139067 }
    149  6  bk139067 
    150  6  bk139067 /*
    151  6  bk139067  * appendmem_to_linebuf
    152  6  bk139067  */
    153  6  bk139067 static void appendmem_to_linebuf(sed_eval_t *eval, const char* sz, int len)
    154  6  bk139067 {
    155  8   basantk     unsigned int reqsize = (eval->lspend - eval->linebuf) + len;
    156  6  bk139067     if (eval->lsize < reqsize) {
    157  6  bk139067         grow_line_buffer(eval, reqsize);
    158  6  bk139067     }
    159  6  bk139067     memcpy(eval->lspend, sz, len);
    160  6  bk139067     eval->lspend += len;
    161  6  bk139067 }
    162  6  bk139067 
    163  6  bk139067 /*
    164  6  bk139067  * append_to_linebuf
    165  6  bk139067  */
    166  6  bk139067 static void append_to_linebuf(sed_eval_t *eval, const char* sz)
    167  6  bk139067 {
    168  6  bk139067     int len = strlen(sz);
    169  6  bk139067     /* Copy string including null character */
    170  6  bk139067     appendmem_to_linebuf(eval, sz, len + 1);
    171  6  bk139067     --eval->lspend; /* lspend will now point to NULL character */
    172  6  bk139067 }
    173  6  bk139067 
    174  6  bk139067 /*
    175  6  bk139067  * copy_to_linebuf
    176  6  bk139067  */
    177  6  bk139067 static void copy_to_linebuf(sed_eval_t *eval, const char* sz)
    178  6  bk139067 {
    179  6  bk139067     eval->lspend = eval->linebuf;
    180  6  bk139067     append_to_linebuf(eval, sz);
    181  6  bk139067 }
    182  6  bk139067 
    183  6  bk139067 /*
    184  6  bk139067  * append_to_holdbuf
    185  6  bk139067  */
    186  6  bk139067 static void append_to_holdbuf(sed_eval_t *eval, const char* sz)
    187  6  bk139067 {
    188  6  bk139067     int len = strlen(sz);
    189  8   basantk     unsigned int reqsize = (eval->hspend - eval->holdbuf) + len + 1;
    190  6  bk139067     if (eval->hsize <= reqsize) {
    191  6  bk139067         grow_hold_buffer(eval, reqsize);
    192  6  bk139067     }
    193  6  bk139067     strcpy(eval->hspend, sz);
    194  6  bk139067     /* hspend will now point to NULL character */
    195  6  bk139067     eval->hspend += len;
    196  6  bk139067 }
    197  6  bk139067 
    198  6  bk139067 /*
    199  6  bk139067  * copy_to_holdbuf
    200  6  bk139067  */
    201  6  bk139067 static void copy_to_holdbuf(sed_eval_t *eval, const char* sz)
    202  6  bk139067 {
    203  6  bk139067     eval->hspend = eval->holdbuf;
    204  6  bk139067     append_to_holdbuf(eval, sz);
    205  6  bk139067 }
    206  6  bk139067 
    207  6  bk139067 /*
    208  6  bk139067  * append_to_genbuf
    209  6  bk139067  */
    210  6  bk139067 static void append_to_genbuf(sed_eval_t *eval, const char* sz, char **gspend)
    211  6  bk139067 {
    212  6  bk139067     int len = strlen(sz);
    213  8   basantk     unsigned int reqsize = (*gspend - eval->genbuf) + len + 1;
    214  6  bk139067     if (eval->gsize < reqsize) {
    215  6  bk139067         grow_gen_buffer(eval, reqsize, gspend);
    216  6  bk139067     }
    217  6  bk139067     strcpy(*gspend, sz);
    218  6  bk139067     /* *gspend will now point to NULL character */
    219  6  bk139067     *gspend += len;
    220  6  bk139067 }
    221  6  bk139067 
    222  6  bk139067 /*
    223  6  bk139067  * copy_to_genbuf
    224  6  bk139067  */
    225  6  bk139067 static void copy_to_genbuf(sed_eval_t *eval, const char* sz)
    226  6  bk139067 {
    227  6  bk139067     int len = strlen(sz);
    228  8   basantk     unsigned int reqsize = len + 1;
    229  6  bk139067     if (eval->gsize < reqsize) {
    230  6  bk139067         grow_gen_buffer(eval, reqsize, NULL);
    231  6  bk139067     }
    232  6  bk139067 }
    233  6  bk139067 
    234  0      jyri /*
    235  0      jyri  * sed_init_eval
    236  0      jyri  */
    237  0      jyri apr_status_t sed_init_eval(sed_eval_t *eval, sed_commands_t *commands, sed_err_fn_t *errfn, void *data, sed_write_fn_t *writefn, apr_pool_t* p)
    238  0      jyri {
    239  0      jyri     memset(eval, 0, sizeof(*eval));
    240  0      jyri     eval->pool = p;
    241  0      jyri     eval->writefn = writefn;
    242  0      jyri     return sed_reset_eval(eval, commands, errfn, data);
    243  0      jyri }
    244  0      jyri 
    245  0      jyri /*
    246  0      jyri  * sed_reset_eval
    247  0      jyri  */
    248  0      jyri apr_status_t sed_reset_eval(sed_eval_t *eval, sed_commands_t *commands, sed_err_fn_t *errfn, void *data)
    249  0      jyri {
    250  0      jyri     int i;
    251  0      jyri 
    252  0      jyri     eval->errfn = errfn;
    253  0      jyri     eval->data = data;
    254  0      jyri 
    255  0      jyri     eval->commands = commands;
    256  0      jyri 
    257  0      jyri     eval->lnum = 0;
    258  0      jyri     eval->fout = NULL;
    259  0      jyri 
    260  0      jyri     if (eval->linebuf == NULL) {
    261  6  bk139067         eval->lsize = INIT_BUF_SIZE;
    262  6  bk139067         eval->linebuf = apr_pcalloc(eval->pool, eval->lsize);
    263  0      jyri     }
    264  0      jyri     if (eval->holdbuf == NULL) {
    265  6  bk139067         eval->hsize = INIT_BUF_SIZE;
    266  6  bk139067         eval->holdbuf = apr_pcalloc(eval->pool, eval->hsize);
    267  0      jyri     }
    268  0      jyri     if (eval->genbuf == NULL) {
    269  6  bk139067         eval->gsize = INIT_BUF_SIZE;
    270  6  bk139067         eval->genbuf = apr_pcalloc(eval->pool, eval->gsize);
    271  0      jyri     }
    272  0      jyri     eval->lspend = eval->linebuf;
    273  0      jyri     eval->hspend = eval->holdbuf;
    274  0      jyri     eval->lcomend = &eval->genbuf[71];
    275  0      jyri 
    276  0      jyri     for (i = 0; i < sizeof(eval->abuf) / sizeof(eval->abuf[0]); i++)
    277  0      jyri         eval->abuf[i] = NULL;
    278  0      jyri     eval->aptr = eval->abuf;
    279  0      jyri     eval->pending = NULL;
    280  0      jyri     eval->inar = apr_pcalloc(eval->pool, commands->nrep * sizeof(unsigned char));
    281  0      jyri     eval->nrep = commands->nrep;
    282  0      jyri 
    283  0      jyri     eval->dolflag = 0;
    284  0      jyri     eval->sflag = 0;
    285  0      jyri     eval->jflag = 0;
    286  0      jyri     eval->delflag = 0;
    287  0      jyri     eval->lreadyflag = 0;
    288  0      jyri     eval->quitflag = 0;
    289  0      jyri     eval->finalflag = 1; /* assume we're evaluating only one file/stream */
    290  0      jyri     eval->numpass = 0;
    291  0      jyri     eval->nullmatch = 0;
    292  0      jyri     eval->col = 0;
    293  0      jyri 
    294  0      jyri     for (i = 0; i < commands->nfiles; i++) {
    295  0      jyri         const char* filename = commands->fname[i];
    296  0      jyri         if (apr_file_open(&eval->fcode[i], filename,
    297  0      jyri                           APR_WRITE | APR_CREATE, APR_OS_DEFAULT,
    298  0      jyri                           eval->pool) != APR_SUCCESS) {
    299  0      jyri             eval_errf(eval, SEDERR_COMES, filename);
    300  0      jyri             return APR_EGENERAL;
    301  0      jyri         }
    302  0      jyri     }
    303  0      jyri 
    304  0      jyri     return APR_SUCCESS;
    305  0      jyri }
    306  0      jyri 
    307  0      jyri /*
    308  0      jyri  * sed_destroy_eval
    309  0      jyri  */
    310  0      jyri void sed_destroy_eval(sed_eval_t *eval)
    311  0      jyri {
    312  0      jyri     int i;
    313  0      jyri     /* eval->linebuf, eval->holdbuf, eval->genbuf and eval->inar are allocated
    314  0      jyri      * on pool. It will be freed when pool will be freed */
    315  0      jyri     for (i = 0; i < eval->commands->nfiles; i++) {
    316  0      jyri         if (eval->fcode[i] != NULL) {
    317  0      jyri             apr_file_close(eval->fcode[i]);
    318  0      jyri             eval->fcode[i] = NULL;
    319  0      jyri         }
    320  0      jyri     }
    321  0      jyri }
    322  0      jyri 
    323  0      jyri /*
    324  0      jyri  * sed_eval_file
    325  0      jyri  */
    326  0      jyri apr_status_t sed_eval_file(sed_eval_t *eval, apr_file_t *fin, void *fout)
    327  0      jyri {
    328  0      jyri     for (;;) {
    329  0      jyri         char buf[1024];
    330  0      jyri         apr_size_t read_bytes = 0;
    331  0      jyri 
    332  0      jyri         read_bytes = sizeof(buf);
    333  0      jyri         if (apr_file_read(fin, buf, &read_bytes) != APR_SUCCESS)
    334  0      jyri             break;
    335  0      jyri 
    336  0      jyri         if (sed_eval_buffer(eval, buf, read_bytes, fout) != APR_SUCCESS)
    337  0      jyri             return APR_EGENERAL;
    338  0      jyri 
    339  0      jyri         if (eval->quitflag)
    340  0      jyri             return APR_SUCCESS;
    341  0      jyri     }
    342  0      jyri 
    343  0      jyri     return sed_finalize_eval(eval, fout);
    344  0      jyri }
    345  0      jyri 
    346  0      jyri /*
    347  0      jyri  * sed_eval_buffer
    348  0      jyri  */
    349  0      jyri apr_status_t sed_eval_buffer(sed_eval_t *eval, const char *buf, int bufsz, void *fout)
    350  0      jyri {
    351  0      jyri     apr_status_t rv;
    352  0      jyri 
    353  0      jyri     if (eval->quitflag)
    354  0      jyri         return APR_SUCCESS;
    355  4   basantk 
    356  4   basantk     if (!sed_canbe_finalized(eval->commands)) {
    357  4   basantk         /* Commands were not finalized properly. */
    358  4   basantk         const char* error = sed_get_finalize_error(eval->commands, eval->pool);
    359  4   basantk         if (error) {
    360  4   basantk             eval_errf(eval, error);
    361  4   basantk             return APR_EGENERAL;
    362  4   basantk         }
    363  4   basantk     }
    364  0      jyri 
    365  0      jyri     eval->fout = fout;
    366  0      jyri 
    367  0      jyri     /* Process leftovers */
    368  0      jyri     if (bufsz && eval->lreadyflag) {
    369  0      jyri         eval->lreadyflag = 0;
    370  0      jyri         eval->lspend--;
    371  0      jyri         *eval->lspend = '\0';
    372  0      jyri         rv = execute(eval);
    373  0      jyri         if (rv != 0)
    374  0      jyri             return APR_EGENERAL;
    375  0      jyri     }
    376  0      jyri 
    377  0      jyri     while (bufsz) {
    378  0      jyri         char *n;
    379  0      jyri         int llen;
    380  0      jyri 
    381  0      jyri         n = memchr(buf, '\n', bufsz);
    382  0      jyri         if (n == NULL)
    383  0      jyri             break;
    384  0      jyri 
    385  0      jyri         llen = n - buf;
    386  0      jyri         if (llen == bufsz - 1) {
    387  0      jyri             /* This might be the last line; delay its processing */
    388  0      jyri             eval->lreadyflag = 1;
    389  0      jyri             break;
    390  0      jyri         }
    391  6  bk139067 
    392  6  bk139067         appendmem_to_linebuf(eval, buf, llen + 1);
    393  6  bk139067         --eval->lspend;
    394  6  bk139067         /* replace new line character with NULL */
    395  6  bk139067         *eval->lspend = '\0';
    396  0      jyri         buf += (llen + 1);
    397  0      jyri         bufsz -= (llen + 1);
    398  0      jyri         rv = execute(eval);
    399  0      jyri         if (rv != 0)
    400  0      jyri             return APR_EGENERAL;
    401  0      jyri         if (eval->quitflag)
    402  0      jyri             break;
    403  0      jyri     }
    404  0      jyri 
    405  0      jyri     /* Save the leftovers for later */
    406  0      jyri     if (bufsz) {
    407  6  bk139067         appendmem_to_linebuf(eval, buf, bufsz);
    408  0      jyri     }
    409  0      jyri 
    410  0      jyri     return APR_SUCCESS;
    411  0      jyri }
    412  0      jyri 
    413  0      jyri /*
    414  0      jyri  * sed_finalize_eval
    415  0      jyri  */
    416  0      jyri apr_status_t sed_finalize_eval(sed_eval_t *eval, void *fout)
    417  0      jyri {
    418  0      jyri     if (eval->quitflag)
    419  0      jyri         return APR_SUCCESS;
    420  0      jyri 
    421  0      jyri     if (eval->finalflag)
    422  0      jyri         eval->dolflag = 1;
    423  0      jyri 
    424  0      jyri     eval->fout = fout;
    425  0      jyri 
    426  0      jyri     /* Process leftovers */
    427  0      jyri     if (eval->lspend > eval->linebuf) {
    428  0      jyri         apr_status_t rv;
    429  0      jyri 
    430  0      jyri         if (eval->lreadyflag) {
    431  0      jyri             eval->lreadyflag = 0;
    432  0      jyri             eval->lspend--;
    433  0      jyri         } else {
    434  6  bk139067             /* Code can probably reach here when last character in output
    435  7   basantk              * buffer is not a newline.
    436  6  bk139067              */
    437  6  bk139067             /* Assure space for NULL */
    438  6  bk139067             append_to_linebuf(eval, "");
    439  0      jyri         }
    440  0      jyri 
    441  0      jyri         *eval->lspend = '\0';
    442  0      jyri         rv = execute(eval);
    443  0      jyri         if (rv != 0)
    444  0      jyri             return APR_EGENERAL;
    445  0      jyri     }
    446  0      jyri 
    447  0      jyri     eval->quitflag = 1;
    448  0      jyri 
    449  0      jyri     return APR_SUCCESS;
    450  0      jyri }
    451  0      jyri 
    452  0      jyri /*
    453  0      jyri  * execute
    454  0      jyri  */
    455  0      jyri static apr_status_t execute(sed_eval_t *eval)
    456  0      jyri {
    457  0      jyri     sed_reptr_t *ipc = eval->commands->ptrspace;
    458  0      jyri     step_vars_storage step_vars;
    459  0      jyri 
    460  0      jyri     eval->lnum++;
    461  0      jyri 
    462  0      jyri     eval->sflag = 0;
    463  0      jyri 
    464  0      jyri     if (eval->pending) {
    465  0      jyri         ipc = eval->pending;
    466  0      jyri         eval->pending = NULL;
    467  0      jyri     }
    468  0      jyri 
    469  0      jyri     memset(&step_vars, 0, sizeof(step_vars));
    470  0      jyri 
    471  0      jyri     while (ipc->command) {
    472  0      jyri         char *p1;
    473  0      jyri         char *p2;
    474  0      jyri         apr_status_t rv;
    475  0      jyri         int c;
    476  0      jyri 
    477  0      jyri         p1 = ipc->ad1;
    478  0      jyri         p2 = ipc->ad2;
    479  0      jyri 
    480  0      jyri         if (p1) {
    481  0      jyri 
    482  0      jyri             if (eval->inar[ipc->nrep]) {
    483  0      jyri                 if (*p2 == CEND) {
    484  0      jyri                     p1 = 0;
    485  0      jyri                 } else if (*p2 == CLNUM) {
    486  0      jyri                     c = (unsigned char)p2[1];
    487  0      jyri                     if (eval->lnum > eval->commands->tlno[c]) {
    488  0      jyri                         eval->inar[ipc->nrep] = 0;
    489  0      jyri                         if (ipc->negfl)
    490  0      jyri                             goto yes;
    491  0      jyri                         ipc = ipc->next;
    492  0      jyri                         continue;
    493  0      jyri                     }
    494  0      jyri                     if (eval->lnum == eval->commands->tlno[c]) {
    495  0      jyri                         eval->inar[ipc->nrep] = 0;
    496  0      jyri                     }
    497  0      jyri                 } else if (match(eval, p2, 0, &step_vars)) {
    498  0      jyri                     eval->inar[ipc->nrep] = 0;
    499  0      jyri                 }
    500  0      jyri             } else if (*p1 == CEND) {
    501  0      jyri                 if (!eval->dolflag) {
    502  0      jyri                     if (ipc->negfl)
    503  0      jyri                         goto yes;
    504  0      jyri                     ipc = ipc->next;
    505  0      jyri                     continue;
    506  0      jyri                 }
    507  0      jyri             } else if (*p1 == CLNUM) {
    508  0      jyri                 c = (unsigned char)p1[1];
    509  0      jyri                 if (eval->lnum != eval->commands->tlno[c]) {
    510  0      jyri                     if (ipc->negfl)
    511  0      jyri                         goto yes;
    512  0      jyri                     ipc = ipc->next;
    513  0      jyri                     continue;
    514  0      jyri                 }
    515  0      jyri                 if (p2)
    516  0      jyri                     eval->inar[ipc->nrep] = 1;
    517  0      jyri             } else if (match(eval, p1, 0, &step_vars)) {
    518  0      jyri                 if (p2)
    519  0      jyri                     eval->inar[ipc->nrep] = 1;
    520  0      jyri             } else {
    521  0      jyri                 if (ipc->negfl)
    522  0      jyri                     goto yes;
    523  0      jyri                 ipc = ipc->next;
    524  0      jyri                 continue;
    525  0      jyri             }
    526  0      jyri         }
    527  0      jyri 
    528  0      jyri         if (ipc->negfl) {
    529  0      jyri             ipc = ipc->next;
    530  0      jyri             continue;
    531  0      jyri         }
    532  0      jyri 
    533  0      jyri yes:
    534  0      jyri         rv = command(eval, ipc, &step_vars);
    535  0      jyri         if (rv != APR_SUCCESS)
    536  0      jyri             return rv;
    537  0      jyri 
    538  0      jyri         if (eval->quitflag)
    539  0      jyri             return APR_SUCCESS;
    540  0      jyri 
    541  0      jyri         if (eval->pending)
    542  0      jyri             return APR_SUCCESS;
    543  0      jyri 
    544  0      jyri         if (eval->delflag)
    545  0      jyri             break;
    546  0      jyri 
    547  0      jyri         if (eval->jflag) {
    548  0      jyri             eval->jflag = 0;
    549  0      jyri             if ((ipc = ipc->lb1) == 0) {
    550  0      jyri                 ipc = eval->commands->ptrspace;
    551  0      jyri                 break;
    552  0      jyri             }
    553  0      jyri         } else
    554  0      jyri             ipc = ipc->next;
    555  0      jyri     }
    556  0      jyri 
    557  0      jyri     if (!eval->commands->nflag && !eval->delflag)
    558  0      jyri         wline(eval, eval->linebuf, eval->lspend - eval->linebuf);
    559  0      jyri 
    560  0      jyri     if (eval->aptr > eval->abuf)
    561  0      jyri         arout(eval);
    562  0      jyri 
    563  0      jyri     eval->delflag = 0;
    564  0      jyri 
    565  0      jyri     eval->lspend = eval->linebuf;
    566  0      jyri 
    567  0      jyri     return APR_SUCCESS;
    568  0      jyri }
    569  0      jyri 
    570  0      jyri /*
    571  0      jyri  * match
    572  0      jyri  */
    573  0      jyri static int match(sed_eval_t *eval, char *expbuf, int gf,
    574  0      jyri                  step_vars_storage *step_vars)
    575  0      jyri {
    576  0      jyri     char   *p1;
    577  0      jyri     int circf;
    578  0      jyri 
    579  0      jyri     if(gf) {
    580  0      jyri         if(*expbuf)    return(0);
    581  0      jyri         step_vars->locs = p1 = step_vars->loc2;
    582  0      jyri     } else {
    583  0      jyri         p1 = eval->linebuf;
    584  0      jyri         step_vars->locs = 0;
    585  0      jyri     }
    586  0      jyri 
    587  0      jyri     circf = *expbuf++;
    588  0      jyri     return(sed_step(p1, expbuf, circf, step_vars));
    589  0      jyri }
    590  0      jyri 
    591  0      jyri /*
    592  0      jyri  * substitute
    593  0      jyri  */
    594  0      jyri static int substitute(sed_eval_t *eval, sed_reptr_t *ipc,
    595  0      jyri                       step_vars_storage *step_vars)
    596  0      jyri {
    597  0      jyri     if(match(eval, ipc->re1, 0, step_vars) == 0)    return(0);
    598  0      jyri 
    599  0      jyri     eval->numpass = 0;
    600  0      jyri     eval->sflag = 0;        /* Flags if any substitution was made */
    601  0      jyri     if (dosub(eval, ipc->rhs, ipc->gfl, step_vars) != APR_SUCCESS)
    602  0      jyri         return -1;
    603  0      jyri 
    604  0      jyri     if(ipc->gfl) {
    605  0      jyri         while(*step_vars->loc2) {
    606  0      jyri             if(match(eval, ipc->re1, 1, step_vars) == 0) break;
    607  0      jyri             if (dosub(eval, ipc->rhs, ipc->gfl, step_vars) != APR_SUCCESS)
    608  0      jyri                 return -1;
    609  0      jyri         }
    610  0      jyri     }
    611  0      jyri     return(eval->sflag);
    612  0      jyri }
    613  0      jyri 
    614  0      jyri /*
    615  0      jyri  * dosub
    616  0      jyri  */
    617  0      jyri static apr_status_t dosub(sed_eval_t *eval, char *rhsbuf, int n,
    618  0      jyri                           step_vars_storage *step_vars)
    619  0      jyri {
    620  0      jyri     char *lp, *sp, *rp;
    621  0      jyri     int c;
    622  0      jyri     apr_status_t rv = APR_SUCCESS;
    623  0      jyri 
    624  0      jyri     if(n > 0 && n < 999) {
    625  0      jyri         eval->numpass++;
    626  0      jyri         if(n != eval->numpass) return APR_SUCCESS;
    627  0      jyri     }
    628  0      jyri     eval->sflag = 1;
    629  0      jyri     lp = eval->linebuf;
    630  0      jyri     sp = eval->genbuf;
    631  0      jyri     rp = rhsbuf;
    632  6  bk139067     sp = place(eval, sp, lp, step_vars->loc1);
    633  8   basantk     while ((c = *rp++) != 0) {
    634  0      jyri         if (c == '&') {
    635  0      jyri             sp = place(eval, sp, step_vars->loc1, step_vars->loc2);
    636  0      jyri             if (sp == NULL)
    637  0      jyri                 return APR_EGENERAL;
    638  0      jyri         }
    639  0      jyri         else if (c == '\\') {
    640  0      jyri             c = *rp++;
    641  0      jyri             if (c >= '1' && c < NBRA+'1') {
    642  0      jyri                 sp = place(eval, sp, step_vars->braslist[c-'1'],
    643  0      jyri                            step_vars->braelist[c-'1']);
    644  0      jyri                 if (sp == NULL)
    645  0      jyri                     return APR_EGENERAL;
    646  0      jyri             }
    647  0      jyri             else
    648  0      jyri                 *sp++ = c;
    649  0      jyri           } else
    650  0      jyri             *sp++ = c;
    651  6  bk139067         if (sp >= eval->genbuf + eval->gsize) {
    652  6  bk139067             /* expand genbuf and set the sp appropriately */
    653  6  bk139067             grow_gen_buffer(eval, eval->gsize + 1024, &sp);
    654  0      jyri         }
    655  0      jyri     }
    656  0      jyri     lp = step_vars->loc2;
    657  0      jyri     step_vars->loc2 = sp - eval->genbuf + eval->linebuf;
    658  6  bk139067     append_to_genbuf(eval, lp, &sp);
    659  6  bk139067     copy_to_linebuf(eval, eval->genbuf);
    660  0      jyri     return rv;
    661  0      jyri }
    662  0      jyri 
    663  0      jyri /*
    664  0      jyri  * place
    665  0      jyri  */
    666  0      jyri static char *place(sed_eval_t *eval, char *asp, char *al1, char *al2)
    667  0      jyri {
    668  6  bk139067     char *sp = asp;
    669  6  bk139067     int n = al2 - al1;
    670  8   basantk     unsigned int reqsize = (sp - eval->genbuf) + n + 1;
    671  0      jyri 
    672  6  bk139067     if (eval->gsize < reqsize) {
    673  6  bk139067         grow_gen_buffer(eval, reqsize, &sp);
    674  0      jyri     }
    675  6  bk139067     memcpy(sp, al1, n);
    676  6  bk139067     return sp + n;
    677  0      jyri }
    678  0      jyri 
    679  0      jyri /*
    680  0      jyri  * command
    681  0      jyri  */
    682  0      jyri static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc,
    683  0      jyri                             step_vars_storage *step_vars)
    684  0      jyri {
    685  0      jyri     int    i;
    686  0      jyri     char   *p1, *p2, *p3;
    687  0      jyri     int length;
    688  0      jyri     char sz[32]; /* 32 bytes enough to store 64 bit integer in decimal */
    689  0      jyri 
    690  0      jyri 
    691  0      jyri     switch(ipc->command) {
    692  0      jyri 
    693  0      jyri         case ACOM:
    694  0      jyri             if(eval->aptr >= &eval->abuf[SED_ABUFSIZE]) {
    695  0      jyri                 eval_errf(eval, SEDERR_TMAMES, eval->lnum);
    696  0      jyri             } else {
    697  0      jyri                 *eval->aptr++ = ipc;
    698  0      jyri                 *eval->aptr = NULL;
    699  0      jyri             }
    700  0      jyri             break;
    701  0      jyri 
    702  0      jyri         case CCOM:
    703  0      jyri             eval->delflag = 1;
    704  0      jyri             if(!eval->inar[ipc->nrep] || eval->dolflag) {
    705  0      jyri                 for (p1 = ipc->re1; *p1; p1++)
    706  0      jyri                     ;
    707  0      jyri                 wline(eval, ipc->re1, p1 - ipc->re1);
    708  0      jyri             }
    709  0      jyri             break;
    710  0      jyri         case DCOM:
    711  0      jyri             eval->delflag++;
    712  0      jyri             break;
    713  0      jyri         case CDCOM:
    714  0      jyri             p1 = eval->linebuf;
    715  0      jyri 
    716  0      jyri             while(*p1 != '\n') {
    717  0      jyri                 if(*p1++ == 0) {
    718  0      jyri                     eval->delflag++;
    719  0      jyri                     return APR_SUCCESS;
    720  0      jyri                 }
    721  0      jyri             }
    722  0      jyri 
    723  0      jyri             p1++;
    724  6  bk139067             copy_to_linebuf(eval, p1);
    725  0      jyri             eval->jflag++;
    726  0      jyri             break;
    727  0      jyri 
    728  0      jyri         case EQCOM:
    729  8   basantk             length = apr_snprintf(sz, sizeof(sz), "%d", (int) eval->lnum);
    730  0      jyri             wline(eval, sz, length);
    731  0      jyri             break;
    732  0      jyri 
    733  0      jyri         case GCOM:
    734  6  bk139067             copy_to_linebuf(eval, eval->holdbuf);
    735  0      jyri             break;
    736  0      jyri 
    737  0      jyri         case CGCOM:
    738  6  bk139067             append_to_linebuf(eval, "\n");
    739  6  bk139067             append_to_linebuf(eval, eval->holdbuf);
    740  0      jyri             break;
    741  0      jyri 
    742  0      jyri         case HCOM:
    743  6  bk139067             copy_to_holdbuf(eval, eval->linebuf);
    744  0      jyri             break;
    745  0      jyri 
    746  0      jyri         case CHCOM:
    747  6  bk139067             append_to_holdbuf(eval, "\n");
    748  6  bk139067             append_to_holdbuf(eval, eval->linebuf);
    749  0      jyri             break;
    750  0      jyri 
    751  0      jyri         case ICOM:
    752  0      jyri             for (p1 = ipc->re1; *p1; p1++);
    753  0      jyri             wline(eval, ipc->re1, p1 - ipc->re1);
    754  0      jyri             break;
    755  0      jyri 
    756  0      jyri         case BCOM:
    757  0      jyri             eval->jflag = 1;
    758  0      jyri             break;
    759  0      jyri 
    760  0      jyri 
    761  0      jyri         case LCOM:
    762  0      jyri             p1 = eval->linebuf;
    763  0      jyri             p2 = eval->genbuf;
    764  0      jyri             eval->genbuf[72] = 0;
    765  0      jyri             while(*p1)
    766  0      jyri                 if((unsigned char)*p1 >= 040) {
    767  0      jyri                     if(*p1 == 0177) {
    768  0      jyri                         p3 = rub;
    769  8   basantk                         while ((*p2++ = *p3++) != 0)
    770  0      jyri                             if(p2 >= eval->lcomend) {
    771  0      jyri                                 *p2 = '\\';
    772  0      jyri                                 wline(eval, eval->genbuf,
    773  0      jyri                                       strlen(eval->genbuf));
    774  0      jyri                                 p2 = eval->genbuf;
    775  0      jyri                             }
    776  0      jyri                         p2--;
    777  0      jyri                         p1++;
    778  0      jyri                         continue;
    779  0      jyri                     }
    780  0      jyri                     if(!isprint(*p1 & 0377)) {
    781  0      jyri                         *p2++ = '\\';
    782  0      jyri                         if(p2 >= eval->lcomend) {
    783  0      jyri                             *p2 = '\\';
    784  0      jyri                             wline(eval, eval->genbuf, strlen(eval->genbuf));
    785  0      jyri                             p2 = eval->genbuf;
    786  0      jyri                         }
    787  0      jyri                         *p2++ = (*p1 >> 6) + '0';
    788  0      jyri                         if(p2 >= eval->lcomend) {
    789  0      jyri                             *p2 = '\\';
    790  0      jyri                             wline(eval, eval->genbuf, strlen(eval->genbuf));
    791  0      jyri                             p2 = eval->genbuf;
    792  0      jyri                         }
    793  0      jyri                         *p2++ = ((*p1 >> 3) & 07) + '0';
    794  0      jyri                         if(p2 >= eval->lcomend) {
    795  0      jyri                             *p2 = '\\';
    796  0      jyri                             wline(eval, eval->genbuf, strlen(eval->genbuf));
    797  0      jyri                             p2 = eval->genbuf;
    798  0      jyri                         }
    799  0      jyri                         *p2++ = (*p1++ & 07) + '0';
    800  0      jyri                         if(p2 >= eval->lcomend) {
    801  0      jyri                             *p2 = '\\';
    802  0      jyri                             wline(eval, eval->genbuf, strlen(eval->genbuf));
    803  0      jyri                             p2 = eval->genbuf;
    804  0      jyri                         }
    805  0      jyri                     } else {
    806  0      jyri                         *p2++ = *p1++;
    807  0      jyri                         if(p2 >= eval->lcomend) {
    808  0      jyri                             *p2 = '\\';
    809  0      jyri                             wline(eval, eval->genbuf, strlen(eval->genbuf));
    810  0      jyri                             p2 = eval->genbuf;
    811  0      jyri                         }
    812  0      jyri                     }
    813  0      jyri                 } else {
    814  0      jyri                     p3 = trans[(unsigned char)*p1-1];
    815  8   basantk                     while ((*p2++ = *p3++) != 0)
    816  0      jyri                         if(p2 >= eval->lcomend) {
    817  0      jyri                             *p2 = '\\';
    818  0      jyri                             wline(eval, eval->genbuf, strlen(eval->genbuf));
    819  0      jyri                             p2 = eval->genbuf;
    820  0      jyri                         }
    821  0      jyri                     p2--;
    822  0      jyri                     p1++;
    823  0      jyri                 }
    824  0      jyri             *p2 = 0;
    825  0      jyri             wline(eval, eval->genbuf, strlen(eval->genbuf));
    826  0      jyri             break;
    827  0      jyri 
    828  0      jyri         case NCOM:
    829  0      jyri             if(!eval->commands->nflag) {
    830  0      jyri                 wline(eval, eval->linebuf, eval->lspend - eval->linebuf);
    831  0      jyri             }
    832  0      jyri 
    833  0      jyri             if(eval->aptr > eval->abuf)
    834  0      jyri                 arout(eval);
    835  0      jyri             eval->lspend = eval->linebuf;
    836  0      jyri             eval->pending = ipc->next;
    837  0      jyri 
    838  0      jyri             break;
    839  0      jyri         case CNCOM:
    840  0      jyri             if(eval->aptr > eval->abuf)
    841  0      jyri                 arout(eval);
    842  6  bk139067             append_to_linebuf(eval, "\n");
    843  0      jyri             eval->pending = ipc->next;
    844  0      jyri             break;
    845  0      jyri 
    846  0      jyri         case PCOM:
    847  0      jyri             wline(eval, eval->linebuf, eval->lspend - eval->linebuf);
    848  0      jyri             break;
    849  0      jyri         case CPCOM:
    850  0      jyri             for (p1 = eval->linebuf; *p1 != '\n' && *p1 != '\0'; p1++);
    851  0      jyri             wline(eval, eval->linebuf, p1 - eval->linebuf);
    852  0      jyri             break;
    853  0      jyri 
    854  0      jyri         case QCOM:
    855  0      jyri             if (!eval->commands->nflag)
    856  0      jyri                 wline(eval, eval->linebuf, eval->lspend - eval->linebuf);
    857  0      jyri 
    858  0      jyri             if(eval->aptr > eval->abuf)
    859  0      jyri                 arout(eval);
    860  0      jyri 
    861  0      jyri             eval->quitflag = 1;
    862  0      jyri             break;
    863  0      jyri         case RCOM:
    864  0      jyri             if(eval->aptr >= &eval->abuf[SED_ABUFSIZE]) {
    865  0      jyri                 eval_errf(eval, SEDERR_TMRMES, eval->lnum);
    866  0      jyri             } else {
    867  0      jyri                 *eval->aptr++ = ipc;
    868  0      jyri                 *eval->aptr = NULL;
    869  0      jyri             }
    870  0      jyri             break;
    871  0      jyri 
    872  0      jyri         case SCOM:
    873  0      jyri             i = substitute(eval, ipc, step_vars);
    874  0      jyri             if (i == -1) {
    875  0      jyri                 return APR_EGENERAL;
    876  0      jyri             }
    877  0      jyri             if(ipc->pfl && eval->commands->nflag && i) {
    878  0      jyri                 if(ipc->pfl == 1) {
    879  0      jyri                     wline(eval, eval->linebuf, eval->lspend - eval->linebuf);
    880  0      jyri                 } else {
    881  0      jyri                     for (p1 = eval->linebuf; *p1 != '\n' && *p1 != '\0'; p1++);
    882  0      jyri                     wline(eval, eval->linebuf, p1 - eval->linebuf);
    883  0      jyri                 }
    884  0      jyri             }
    885  0      jyri             if (i && (ipc->findex >= 0) && eval->fcode[ipc->findex])
    886  0      jyri                 apr_file_printf(eval->fcode[ipc->findex], "%s\n",
    887  0      jyri                                 eval->linebuf);
    888  0      jyri             break;
    889  0      jyri 
    890  0      jyri         case TCOM:
    891  0      jyri             if(eval->sflag == 0)  break;
    892  0      jyri             eval->sflag = 0;
    893  0      jyri             eval->jflag = 1;
    894  0      jyri             break;
    895  0      jyri 
    896  0      jyri         case WCOM:
    897  0      jyri             if (ipc->findex >= 0)
    898  0      jyri                 apr_file_printf(eval->fcode[ipc->findex], "%s\n",
    899  0      jyri                                 eval->linebuf);
    900  0      jyri             break;
    901  0      jyri         case XCOM:
    902  6  bk139067             copy_to_genbuf(eval, eval->linebuf);
    903  6  bk139067             copy_to_linebuf(eval, eval->holdbuf);
    904  6  bk139067             copy_to_holdbuf(eval, eval->genbuf);
    905  0      jyri             break;
    906  0      jyri 
    907  0      jyri         case YCOM:
    908  0      jyri             p1 = eval->linebuf;
    909  0      jyri             p2 = ipc->re1;
    910  8   basantk             while((*p1 = p2[(unsigned char)*p1]) != 0)    p1++;
    911  0      jyri             break;
    912  0      jyri     }
    913  0      jyri     return APR_SUCCESS;
    914  0      jyri }
    915  0      jyri 
    916  0      jyri /*
    917  0      jyri  * arout
    918  0      jyri  */
    919  0      jyri static void arout(sed_eval_t *eval)
    920  0      jyri {
    921  0      jyri     eval->aptr = eval->abuf - 1;
    922  0      jyri     while (*++eval->aptr) {
    923  0      jyri         if ((*eval->aptr)->command == ACOM) {
    924  0      jyri             char *p1;
    925  0      jyri 
    926  0      jyri             for (p1 = (*eval->aptr)->re1; *p1; p1++);
    927  0      jyri             wline(eval, (*eval->aptr)->re1, p1 - (*eval->aptr)->re1);
    928  0      jyri         } else {
    929  0      jyri             apr_file_t *fi = NULL;
    930  0      jyri             char buf[512];
    931  0      jyri             apr_size_t n = sizeof(buf);
    932  0      jyri 
    933  0      jyri             if (apr_file_open(&fi, (*eval->aptr)->re1, APR_READ, 0, eval->pool)
    934  0      jyri                               != APR_SUCCESS)
    935  0      jyri                 continue;
    936  0      jyri             while ((apr_file_read(fi, buf, &n)) == APR_SUCCESS) {
    937  0      jyri                 if (n == 0)
    938  0      jyri                     break;
    939  3   basantk                 eval->writefn(eval->fout, buf, n);
    940  0      jyri                 n = sizeof(buf);
    941  0      jyri             }
    942  0      jyri             apr_file_close(fi);
    943  0      jyri         }
    944  0      jyri     }
    945  0      jyri     eval->aptr = eval->abuf;
    946  0      jyri     *eval->aptr = NULL;
    947  0      jyri }
    948  0      jyri 
    949  0      jyri /*
    950  0      jyri  * wline
    951  0      jyri  */
    952  0      jyri static void wline(sed_eval_t *eval, char *buf, int sz)
    953  0      jyri {
    954  3   basantk     eval->writefn(eval->fout, buf, sz);
    955  3   basantk     eval->writefn(eval->fout, "\n", 1);
    956  0      jyri }
    957  0      jyri 
    958