components/apache2/mod_sed/sed0.c
changeset 278 77b380ba9d84
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/apache2/mod_sed/sed0.c	Thu Jun 02 00:54:08 2011 -0700
@@ -0,0 +1,1026 @@
+/*
+ * 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);
+            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]) == 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]) == 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, commands->linebuf);
+                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, commands->linebuf);
+            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, commands->linebuf);
+                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, commands->linebuf);
+            *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;
+}
+
+