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