| /* |
| * Copyright (c) 2005, 2008 Sun Microsystems, Inc. All Rights Reserved. |
| * Use is subject to license terms. |
| * |
| * Copyright (c) 1984 AT&T |
| * All Rights Reserved |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * http://www.apache.org/licenses/LICENSE-2.0. |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
| * or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "apr.h" |
| #include "apr_strings.h" |
| #include "libsed.h" |
| #include "sed.h" |
| #include "regexp.h" |
| |
| #define CCEOF 22 |
| |
| static int fcomp(sed_commands_t *commands, apr_file_t *fin); |
| static char *compsub(sed_commands_t *commands, |
| sed_comp_args *compargs, char *rhsbuf); |
| static int rline(sed_commands_t *commands, apr_file_t *fin, |
| char *lbuf, char *lbend); |
| static char *address(sed_commands_t *commands, char *expbuf, |
| apr_status_t* status); |
| static char *text(sed_commands_t *commands, char *textbuf, char *endbuf); |
| static sed_label_t *search(sed_commands_t *commands); |
| static char *ycomp(sed_commands_t *commands, char *expbuf); |
| static char *comple(sed_commands_t *commands, sed_comp_args *compargs, |
| char *x1, char *ep, char *x3, char x4); |
| static sed_reptr_t *alloc_reptr(sed_commands_t *commands); |
| static int check_finalized(const sed_commands_t *commands); |
| |
| void command_errf(sed_commands_t *commands, const char *fmt, ...) |
| { |
| if (commands->errfn && commands->pool) { |
| va_list args; |
| const char* error; |
| va_start(args, fmt); |
| error = apr_pvsprintf(commands->pool, fmt, args); |
| commands->errfn(commands->data, error); |
| va_end(args); |
| } |
| } |
| |
| /* |
| * sed_init_commands |
| */ |
| apr_status_t sed_init_commands(sed_commands_t *commands, sed_err_fn_t *errfn, void *data, |
| apr_pool_t *p) |
| { |
| memset(commands, 0, sizeof(*commands)); |
| |
| commands->errfn = errfn; |
| commands->data = data; |
| |
| commands->labtab = commands->ltab; |
| commands->lab = commands->labtab + 1; |
| commands->pool = p; |
| |
| commands->respace = apr_pcalloc(p, RESIZE); |
| if (commands->respace == NULL) { |
| command_errf(commands, SEDERR_OOMMES); |
| return APR_EGENERAL; |
| } |
| |
| commands->rep = alloc_reptr(commands); |
| if (commands->rep == NULL) |
| return APR_EGENERAL; |
| |
| commands->rep->ad1 = commands->respace; |
| commands->reend = &commands->respace[RESIZE - 1]; |
| commands->labend = &commands->labtab[SED_LABSIZE]; |
| commands->canbefinal = 1; |
| |
| return APR_SUCCESS; |
| } |
| |
| /* |
| * sed_destroy_commands |
| */ |
| void sed_destroy_commands(sed_commands_t *commands) |
| { |
| } |
| |
| /* |
| * sed_compile_string |
| */ |
| apr_status_t sed_compile_string(sed_commands_t *commands, const char *s) |
| { |
| apr_status_t rv; |
| |
| commands->earg = s; |
| commands->eflag = 1; |
| |
| rv = fcomp(commands, NULL); |
| if (rv == APR_SUCCESS) |
| commands->canbefinal = check_finalized(commands); |
| |
| commands->eflag = 0; |
| |
| return (rv != 0 ? APR_EGENERAL : APR_SUCCESS); |
| } |
| |
| /* |
| * sed_compile_file |
| */ |
| apr_status_t sed_compile_file(sed_commands_t *commands, apr_file_t *fin) |
| { |
| apr_status_t rv = fcomp(commands, fin); |
| return (rv != 0 ? APR_EGENERAL : APR_SUCCESS); |
| } |
| |
| /* |
| * sed_get_finalize_error |
| */ |
| char* sed_get_finalize_error(const sed_commands_t *commands, apr_pool_t* pool) |
| { |
| const sed_label_t *lab; |
| if (commands->depth) { |
| return SEDERR_TMOMES; |
| } |
| |
| /* Empty branch chain is not a issue */ |
| for (lab = commands->labtab + 1; lab < commands->lab; lab++) { |
| char *error; |
| if (lab->address == 0) { |
| error = apr_psprintf(pool, SEDERR_ULMES, lab->asc); |
| return error; |
| } |
| |
| if (lab->chain) { |
| return SEDERR_INTERNAL; |
| } |
| } |
| return NULL; |
| } |
| |
| /* |
| * sed_canbe_finalized |
| */ |
| int sed_canbe_finalized(const sed_commands_t *commands) |
| { |
| return commands->canbefinal; |
| } |
| |
| /* |
| * check_finalized |
| */ |
| static int check_finalized(const sed_commands_t *commands) |
| { |
| const sed_label_t *lab; |
| if (commands->depth) { |
| return 0; |
| } |
| |
| /* Empty branch chain is not a issue */ |
| for (lab = commands->labtab + 1; lab < commands->lab; lab++) { |
| if (lab->address == 0 || (lab->chain)) { |
| return 0; |
| } |
| } |
| return 1; |
| } |
| |
| /* |
| * dechain |
| */ |
| static void dechain(sed_label_t *lpt, sed_reptr_t *address) |
| { |
| sed_reptr_t *rep; |
| if ((lpt == NULL) || (lpt->chain == NULL) || (address == NULL)) |
| return; |
| rep = lpt->chain; |
| while (rep->lb1) { |
| sed_reptr_t *next; |
| |
| next = rep->lb1; |
| rep->lb1 = address; |
| rep = next; |
| } |
| rep->lb1 = address; |
| lpt->chain = NULL; |
| } |
| |
| /* |
| * fcomp |
| */ |
| static int fcomp(sed_commands_t *commands, apr_file_t *fin) |
| { |
| char *p, *op, *tp; |
| sed_reptr_t *pt, *pt1; |
| int i, ii; |
| sed_label_t *lpt; |
| char fnamebuf[APR_PATH_MAX]; |
| apr_status_t status; |
| sed_comp_args compargs; |
| |
| op = commands->lastre; |
| if (!commands->linebuf) { |
| commands->linebuf = apr_pcalloc(commands->pool, LBSIZE + 1); |
| } |
| |
| if (rline(commands, fin, commands->linebuf, |
| (commands->linebuf + LBSIZE + 1)) < 0) |
| return 0; |
| if (*commands->linebuf == '#') { |
| if (commands->linebuf[1] == 'n') |
| commands->nflag = 1; |
| } |
| else { |
| commands->cp = commands->linebuf; |
| goto comploop; |
| } |
| |
| for (;;) { |
| if (rline(commands, fin, commands->linebuf, |
| (commands->linebuf + LBSIZE + 1)) < 0) |
| break; |
| |
| commands->cp = commands->linebuf; |
| |
| comploop: |
| while (*commands->cp == ' ' || *commands->cp == '\t') |
| commands->cp++; |
| if (*commands->cp == '\0' || *commands->cp == '#') |
| continue; |
| if (*commands->cp == ';') { |
| commands->cp++; |
| goto comploop; |
| } |
| |
| p = address(commands, commands->rep->ad1, &status); |
| if (status != APR_SUCCESS) { |
| command_errf(commands, SEDERR_CGMES, commands->linebuf); |
| return -1; |
| } |
| |
| if (p == commands->rep->ad1) { |
| if (op) |
| commands->rep->ad1 = op; |
| else { |
| command_errf(commands, SEDERR_NRMES); |
| return -1; |
| } |
| } else if (p == 0) { |
| p = commands->rep->ad1; |
| commands->rep->ad1 = 0; |
| } else { |
| op = commands->rep->ad1; |
| if (*commands->cp == ',' || *commands->cp == ';') { |
| commands->cp++; |
| commands->rep->ad2 = p; |
| p = address(commands, commands->rep->ad2, &status); |
| if ((status != APR_SUCCESS) || (p == 0)) { |
| command_errf(commands, SEDERR_CGMES, commands->linebuf); |
| return -1; |
| } |
| if (p == commands->rep->ad2) |
| commands->rep->ad2 = op; |
| else |
| op = commands->rep->ad2; |
| } else |
| commands->rep->ad2 = 0; |
| } |
| |
| if(p > &commands->respace[RESIZE-1]) { |
| command_errf(commands, SEDERR_TMMES, commands->linebuf); |
| return -1; |
| } |
| |
| while (*commands->cp == ' ' || *commands->cp == '\t') |
| commands->cp++; |
| |
| swit: |
| switch(*commands->cp++) { |
| default: |
| command_errf(commands, SEDERR_UCMES, commands->linebuf); |
| return -1; |
| |
| case '!': |
| commands->rep->negfl = 1; |
| goto swit; |
| |
| case '{': |
| commands->rep->command = BCOM; |
| commands->rep->negfl = !(commands->rep->negfl); |
| commands->cmpend[commands->depth++] = &commands->rep->lb1; |
| commands->rep = alloc_reptr(commands); |
| commands->rep->ad1 = p; |
| if (*commands->cp == '\0') |
| continue; |
| goto comploop; |
| |
| case '}': |
| if (commands->rep->ad1) { |
| command_errf(commands, SEDERR_AD0MES, commands->linebuf); |
| return -1; |
| } |
| |
| if (--commands->depth < 0) { |
| command_errf(commands, SEDERR_TMCMES); |
| return -1; |
| } |
| *commands->cmpend[commands->depth] = commands->rep; |
| |
| commands->rep->ad1 = p; |
| continue; |
| |
| case '=': |
| commands->rep->command = EQCOM; |
| if (commands->rep->ad2) { |
| command_errf(commands, SEDERR_AD1MES, commands->linebuf); |
| return -1; |
| } |
| break; |
| |
| case ':': |
| if (commands->rep->ad1) { |
| command_errf(commands, SEDERR_AD0MES, commands->linebuf); |
| return -1; |
| } |
| |
| while (*commands->cp++ == ' '); |
| commands->cp--; |
| |
| tp = commands->lab->asc; |
| while ((*tp++ = *commands->cp++)) { |
| if (tp >= &(commands->lab->asc[8])) { |
| command_errf(commands, SEDERR_LTLMES, commands->linebuf); |
| return -1; |
| } |
| } |
| *--tp = '\0'; |
| |
| if ((lpt = search(commands)) != NULL) { |
| if (lpt->address) { |
| command_errf(commands, SEDERR_DLMES, commands->linebuf); |
| return -1; |
| } |
| dechain(lpt, commands->rep); |
| } else { |
| commands->lab->chain = 0; |
| lpt = commands->lab; |
| if (++commands->lab >= commands->labend) { |
| command_errf(commands, SEDERR_TMLMES, commands->linebuf); |
| return -1; |
| } |
| } |
| lpt->address = commands->rep; |
| commands->rep->ad1 = p; |
| |
| continue; |
| |
| case 'a': |
| commands->rep->command = ACOM; |
| if (commands->rep->ad2) { |
| command_errf(commands, SEDERR_AD1MES, commands->linebuf); |
| return -1; |
| } |
| if (*commands->cp == '\\') |
| commands->cp++; |
| if (*commands->cp++ != '\n') { |
| command_errf(commands, SEDERR_CGMES, commands->linebuf); |
| return -1; |
| } |
| commands->rep->re1 = p; |
| p = text(commands, commands->rep->re1, commands->reend); |
| if (p == NULL) |
| return -1; |
| break; |
| |
| case 'c': |
| commands->rep->command = CCOM; |
| if (*commands->cp == '\\') commands->cp++; |
| if (*commands->cp++ != ('\n')) { |
| command_errf(commands, SEDERR_CGMES, commands->linebuf); |
| return -1; |
| } |
| commands->rep->re1 = p; |
| p = text(commands, commands->rep->re1, commands->reend); |
| if (p == NULL) |
| return -1; |
| break; |
| |
| case 'i': |
| commands->rep->command = ICOM; |
| if (commands->rep->ad2) { |
| command_errf(commands, SEDERR_AD1MES, commands->linebuf); |
| return -1; |
| } |
| if (*commands->cp == '\\') commands->cp++; |
| if (*commands->cp++ != ('\n')) { |
| command_errf(commands, SEDERR_CGMES, commands->linebuf); |
| return -1; |
| } |
| commands->rep->re1 = p; |
| p = text(commands, commands->rep->re1, commands->reend); |
| if (p == NULL) |
| return -1; |
| break; |
| |
| case 'g': |
| commands->rep->command = GCOM; |
| break; |
| |
| case 'G': |
| commands->rep->command = CGCOM; |
| break; |
| |
| case 'h': |
| commands->rep->command = HCOM; |
| break; |
| |
| case 'H': |
| commands->rep->command = CHCOM; |
| break; |
| |
| case 't': |
| commands->rep->command = TCOM; |
| goto jtcommon; |
| |
| case 'b': |
| commands->rep->command = BCOM; |
| jtcommon: |
| while (*commands->cp++ == ' '); |
| commands->cp--; |
| |
| if (*commands->cp == '\0') { |
| if ((pt = commands->labtab->chain) != NULL) { |
| while ((pt1 = pt->lb1) != NULL) |
| pt = pt1; |
| pt->lb1 = commands->rep; |
| } else |
| commands->labtab->chain = commands->rep; |
| break; |
| } |
| tp = commands->lab->asc; |
| while ((*tp++ = *commands->cp++)) |
| if (tp >= &(commands->lab->asc[8])) { |
| command_errf(commands, SEDERR_LTLMES, commands->linebuf); |
| return -1; |
| } |
| commands->cp--; |
| *--tp = '\0'; |
| |
| if ((lpt = search(commands)) != NULL) { |
| if (lpt->address) { |
| commands->rep->lb1 = lpt->address; |
| } else { |
| pt = lpt->chain; |
| while ((pt1 = pt->lb1) != NULL) |
| pt = pt1; |
| pt->lb1 = commands->rep; |
| } |
| } else { |
| commands->lab->chain = commands->rep; |
| commands->lab->address = 0; |
| if (++commands->lab >= commands->labend) { |
| command_errf(commands, SEDERR_TMLMES, commands->linebuf); |
| return -1; |
| } |
| } |
| break; |
| |
| case 'n': |
| commands->rep->command = NCOM; |
| break; |
| |
| case 'N': |
| commands->rep->command = CNCOM; |
| break; |
| |
| case 'p': |
| commands->rep->command = PCOM; |
| break; |
| |
| case 'P': |
| commands->rep->command = CPCOM; |
| break; |
| |
| case 'r': |
| commands->rep->command = RCOM; |
| if (commands->rep->ad2) { |
| command_errf(commands, SEDERR_AD1MES, commands->linebuf); |
| return -1; |
| } |
| if (*commands->cp++ != ' ') { |
| command_errf(commands, SEDERR_CGMES, commands->linebuf); |
| return -1; |
| } |
| commands->rep->re1 = p; |
| p = text(commands, commands->rep->re1, commands->reend); |
| if (p == NULL) |
| return -1; |
| break; |
| |
| case 'd': |
| commands->rep->command = DCOM; |
| break; |
| |
| case 'D': |
| commands->rep->command = CDCOM; |
| commands->rep->lb1 = commands->ptrspace; |
| break; |
| |
| case 'q': |
| commands->rep->command = QCOM; |
| if (commands->rep->ad2) { |
| command_errf(commands, SEDERR_AD1MES, commands->linebuf); |
| return -1; |
| } |
| break; |
| |
| case 'l': |
| commands->rep->command = LCOM; |
| break; |
| |
| case 's': |
| commands->rep->command = SCOM; |
| commands->sseof = *commands->cp++; |
| commands->rep->re1 = p; |
| p = comple(commands, &compargs, (char *) 0, commands->rep->re1, |
| commands->reend, commands->sseof); |
| if (p == NULL) |
| return -1; |
| if (p == commands->rep->re1) { |
| if (op) |
| commands->rep->re1 = op; |
| else { |
| command_errf(commands, SEDERR_NRMES); |
| return -1; |
| } |
| } else |
| op = commands->rep->re1; |
| commands->rep->rhs = p; |
| |
| p = compsub(commands, &compargs, commands->rep->rhs); |
| if ((p) == NULL) |
| return -1; |
| |
| if (*commands->cp == 'g') { |
| commands->cp++; |
| commands->rep->gfl = 999; |
| } else if (commands->gflag) |
| commands->rep->gfl = 999; |
| |
| if (*commands->cp >= '1' && *commands->cp <= '9') { |
| i = *commands->cp - '0'; |
| commands->cp++; |
| while (1) { |
| ii = *commands->cp; |
| if (ii < '0' || ii > '9') |
| break; |
| i = i*10 + ii - '0'; |
| if (i > 512) { |
| command_errf(commands, SEDERR_TOOBIG, commands->linebuf); |
| return -1; |
| } |
| commands->cp++; |
| } |
| commands->rep->gfl = i; |
| } |
| |
| if (*commands->cp == 'p') { |
| commands->cp++; |
| commands->rep->pfl = 1; |
| } |
| |
| if (*commands->cp == 'P') { |
| commands->cp++; |
| commands->rep->pfl = 2; |
| } |
| |
| if (*commands->cp == 'w') { |
| commands->cp++; |
| if (*commands->cp++ != ' ') { |
| command_errf(commands, SEDERR_SMMES, commands->linebuf); |
| return -1; |
| } |
| if (text(commands, fnamebuf, &fnamebuf[APR_PATH_MAX-1]) == NULL) { |
| command_errf(commands, SEDERR_FNTL, commands->linebuf); |
| return -1; |
| } |
| for (i = commands->nfiles - 1; i >= 0; i--) |
| if (strcmp(fnamebuf,commands->fname[i]) == 0) { |
| commands->rep->findex = i; |
| goto done; |
| } |
| if (commands->nfiles >= NWFILES) { |
| command_errf(commands, SEDERR_TMWFMES); |
| return -1; |
| } |
| commands->fname[commands->nfiles] = |
| apr_pstrdup(commands->pool, fnamebuf); |
| if (commands->fname[commands->nfiles] == NULL) { |
| command_errf(commands, SEDERR_OOMMES); |
| return -1; |
| } |
| commands->rep->findex = commands->nfiles++; |
| } |
| break; |
| |
| case 'w': |
| commands->rep->command = WCOM; |
| if (*commands->cp++ != ' ') { |
| command_errf(commands, SEDERR_SMMES, commands->linebuf); |
| return -1; |
| } |
| if (text(commands, fnamebuf, &fnamebuf[APR_PATH_MAX-1]) == NULL) { |
| command_errf(commands, SEDERR_FNTL, commands->linebuf); |
| return -1; |
| } |
| for (i = commands->nfiles - 1; i >= 0; i--) |
| if (strcmp(fnamebuf, commands->fname[i]) == 0) { |
| commands->rep->findex = i; |
| goto done; |
| } |
| if (commands->nfiles >= NWFILES) { |
| command_errf(commands, SEDERR_TMWFMES); |
| return -1; |
| } |
| if ((commands->fname[commands->nfiles] = |
| apr_pstrdup(commands->pool, fnamebuf)) == NULL) { |
| command_errf(commands, SEDERR_OOMMES); |
| return -1; |
| } |
| |
| commands->rep->findex = commands->nfiles++; |
| break; |
| |
| case 'x': |
| commands->rep->command = XCOM; |
| break; |
| |
| case 'y': |
| commands->rep->command = YCOM; |
| commands->sseof = *commands->cp++; |
| commands->rep->re1 = p; |
| p = ycomp(commands, commands->rep->re1); |
| if (p == NULL) |
| return -1; |
| break; |
| } |
| done: |
| commands->rep = alloc_reptr(commands); |
| |
| commands->rep->ad1 = p; |
| |
| if (*commands->cp++ != '\0') { |
| if (commands->cp[-1] == ';') |
| goto comploop; |
| command_errf(commands, SEDERR_CGMES, commands->linebuf); |
| return -1; |
| } |
| } |
| commands->rep->command = 0; |
| commands->lastre = op; |
| |
| return 0; |
| } |
| |
| static char *compsub(sed_commands_t *commands, |
| sed_comp_args *compargs, char *rhsbuf) |
| { |
| char *p, *q; |
| |
| p = rhsbuf; |
| q = commands->cp; |
| for(;;) { |
| if(p > &commands->respace[RESIZE-1]) { |
| command_errf(commands, SEDERR_TMMES, commands->linebuf); |
| return NULL; |
| } |
| if((*p = *q++) == '\\') { |
| p++; |
| if(p > &commands->respace[RESIZE-1]) { |
| command_errf(commands, SEDERR_TMMES, commands->linebuf); |
| return NULL; |
| } |
| *p = *q++; |
| if(*p > compargs->nbra + '0' && *p <= '9') { |
| command_errf(commands, SEDERR_DOORNG, commands->linebuf); |
| return NULL; |
| } |
| p++; |
| continue; |
| } |
| if(*p == commands->sseof) { |
| *p++ = '\0'; |
| commands->cp = q; |
| return(p); |
| } |
| if(*p++ == '\0') { |
| command_errf(commands, SEDERR_EDMOSUB, commands->linebuf); |
| return NULL; |
| } |
| } |
| } |
| |
| /* |
| * rline |
| */ |
| static int rline(sed_commands_t *commands, apr_file_t *fin, |
| char *lbuf, char *lbend) |
| { |
| char *p; |
| const char *q; |
| int t; |
| apr_size_t bytes_read; |
| |
| p = lbuf; |
| |
| if(commands->eflag) { |
| if(commands->eflag > 0) { |
| commands->eflag = -1; |
| q = commands->earg; |
| while((t = *q++) != '\0') { |
| if(t == '\n') { |
| commands->saveq = q; |
| goto out1; |
| } |
| if (p < lbend) |
| *p++ = t; |
| if(t == '\\') { |
| if((t = *q++) == '\0') { |
| commands->saveq = NULL; |
| return(-1); |
| } |
| if (p < lbend) |
| *p++ = t; |
| } |
| } |
| commands->saveq = NULL; |
| |
| out1: |
| if (p == lbend) { |
| command_errf(commands, SEDERR_CLTL); |
| return -1; |
| } |
| *p = '\0'; |
| return(1); |
| } |
| if((q = commands->saveq) == 0) return(-1); |
| |
| while((t = *q++) != '\0') { |
| if(t == '\n') { |
| commands->saveq = q; |
| goto out2; |
| } |
| if(p < lbend) |
| *p++ = t; |
| if(t == '\\') { |
| if((t = *q++) == '\0') { |
| commands->saveq = NULL; |
| return(-1); |
| } |
| if (p < lbend) |
| *p++ = t; |
| } |
| } |
| commands->saveq = NULL; |
| |
| out2: |
| if (p == lbend) { |
| command_errf(commands, SEDERR_CLTL); |
| return -1; |
| } |
| *p = '\0'; |
| return(1); |
| } |
| |
| bytes_read = 1; |
| /* XXX extremely inefficient 1 byte reads */ |
| while (apr_file_read(fin, &t, &bytes_read) != APR_SUCCESS) { |
| if(t == '\n') { |
| if (p == lbend) { |
| command_errf(commands, SEDERR_CLTL); |
| return -1; |
| } |
| *p = '\0'; |
| return(1); |
| } |
| if (p < lbend) |
| *p++ = t; |
| if(t == '\\') { |
| bytes_read = 1; |
| if (apr_file_read(fin, &t, &bytes_read) != APR_SUCCESS) { |
| return -1; |
| } |
| if(p < lbend) |
| *p++ = t; |
| } |
| bytes_read = 1; |
| } |
| return(-1); |
| } |
| |
| /* |
| * address |
| */ |
| static char *address(sed_commands_t *commands, char *expbuf, |
| apr_status_t* status) |
| { |
| char *rcp; |
| apr_int64_t lno; |
| sed_comp_args compargs; |
| |
| *status = APR_SUCCESS; |
| if(*commands->cp == '$') { |
| if (expbuf > &commands->respace[RESIZE-2]) { |
| command_errf(commands, SEDERR_TMMES, commands->linebuf); |
| *status = APR_EGENERAL; |
| return NULL; |
| } |
| commands->cp++; |
| *expbuf++ = CEND; |
| *expbuf++ = CCEOF; |
| return(expbuf); |
| } |
| if (*commands->cp == '/' || *commands->cp == '\\' ) { |
| if ( *commands->cp == '\\' ) |
| commands->cp++; |
| commands->sseof = *commands->cp++; |
| return(comple(commands, &compargs, (char *) 0, expbuf, commands->reend, |
| commands->sseof)); |
| } |
| |
| rcp = commands->cp; |
| lno = 0; |
| |
| while(*rcp >= '0' && *rcp <= '9') |
| lno = lno*10 + *rcp++ - '0'; |
| |
| if(rcp > commands->cp) { |
| if (expbuf > &commands->respace[RESIZE-3]) { |
| command_errf(commands, SEDERR_TMMES, commands->linebuf); |
| *status = APR_EGENERAL; |
| return NULL; |
| } |
| *expbuf++ = CLNUM; |
| *expbuf++ = commands->nlno; |
| commands->tlno[commands->nlno++] = lno; |
| if(commands->nlno >= SED_NLINES) { |
| command_errf(commands, SEDERR_TMLNMES); |
| *status = APR_EGENERAL; |
| return NULL; |
| } |
| *expbuf++ = CCEOF; |
| commands->cp = rcp; |
| return(expbuf); |
| } |
| return(NULL); |
| } |
| |
| /* |
| * text |
| */ |
| static char *text(sed_commands_t *commands, char *textbuf, char *tbend) |
| { |
| char *p, *q; |
| |
| p = textbuf; |
| q = commands->cp; |
| #ifndef S5EMUL |
| /* |
| * Strip off indentation from text to be inserted. |
| */ |
| while(*q == '\t' || *q == ' ') q++; |
| #endif |
| for(;;) { |
| |
| if(p > tbend) |
| return(NULL); /* overflowed the buffer */ |
| if((*p = *q++) == '\\') |
| *p = *q++; |
| if(*p == '\0') { |
| commands->cp = --q; |
| return(++p); |
| } |
| #ifndef S5EMUL |
| /* |
| * Strip off indentation from text to be inserted. |
| */ |
| if(*p == '\n') { |
| while(*q == '\t' || *q == ' ') q++; |
| } |
| #endif |
| p++; |
| } |
| } |
| |
| |
| /* |
| * search |
| */ |
| static sed_label_t *search(sed_commands_t *commands) |
| { |
| sed_label_t *rp; |
| sed_label_t *ptr; |
| |
| rp = commands->labtab; |
| ptr = commands->lab; |
| while (rp < ptr) { |
| if (strcmp(rp->asc, ptr->asc) == 0) |
| return rp; |
| rp++; |
| } |
| |
| return 0; |
| } |
| |
| /* |
| * ycomp |
| */ |
| static char *ycomp(sed_commands_t *commands, char *expbuf) |
| { |
| char c; |
| int cint; /* integer value of char c */ |
| char *ep, *tsp; |
| int i; |
| char *sp; |
| |
| ep = expbuf; |
| if(ep + 0377 > &commands->respace[RESIZE-1]) { |
| command_errf(commands, SEDERR_TMMES, commands->linebuf); |
| return NULL; |
| } |
| sp = commands->cp; |
| for(tsp = commands->cp; (c = *tsp) != commands->sseof; tsp++) { |
| if(c == '\\') |
| tsp++; |
| if(c == '\0' || c == '\n') { |
| command_errf(commands, SEDERR_EDMOSTR, commands->linebuf); |
| return NULL; |
| } |
| } |
| tsp++; |
| memset(ep, 0, 0400); |
| |
| while((c = *sp++) != commands->sseof) { |
| c &= 0377; |
| if(c == '\\' && *sp == 'n') { |
| sp++; |
| c = '\n'; |
| } |
| cint = (int) c; |
| if((ep[cint] = *tsp++) == '\\' && *tsp == 'n') { |
| ep[cint] = '\n'; |
| tsp++; |
| } |
| if(ep[cint] == commands->sseof || ep[cint] == '\0') { |
| command_errf(commands, SEDERR_TSNTSS, commands->linebuf); |
| } |
| } |
| if(*tsp != commands->sseof) { |
| if(*tsp == '\0') { |
| command_errf(commands, SEDERR_EDMOSTR, commands->linebuf); |
| } |
| else { |
| command_errf(commands, SEDERR_TSNTSS, commands->linebuf); |
| } |
| return NULL; |
| } |
| commands->cp = ++tsp; |
| |
| for(i = 0; i < 0400; i++) |
| if(ep[i] == 0) |
| ep[i] = i; |
| |
| return(ep + 0400); |
| } |
| |
| /* |
| * comple |
| */ |
| static char *comple(sed_commands_t *commands, sed_comp_args *compargs, |
| char *x1, char *ep, char *x3, char x4) |
| { |
| char *p; |
| |
| p = sed_compile(commands, compargs, ep + 1, x3, x4); |
| if(p == ep + 1) |
| return(ep); |
| *ep = compargs->circf; |
| return(p); |
| } |
| |
| /* |
| * alloc_reptr |
| */ |
| static sed_reptr_t *alloc_reptr(sed_commands_t *commands) |
| { |
| sed_reptr_t *var; |
| |
| var = apr_pcalloc(commands->pool, sizeof(sed_reptr_t)); |
| if (var == NULL) { |
| command_errf(commands, SEDERR_OOMMES); |
| return 0; |
| } |
| |
| var->nrep = commands->nrep; |
| var->findex = -1; |
| commands->nrep++; |
| |
| if (commands->ptrspace == NULL) |
| commands->ptrspace = var; |
| else |
| commands->ptrend->next = var; |
| |
| commands->ptrend = var; |
| commands->labtab->address = var; |
| return var; |
| } |
| |
| |