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