summaryrefslogtreecommitdiffstats
path: root/modules/filters/sed1.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/filters/sed1.c')
-rw-r--r--modules/filters/sed1.c1110
1 files changed, 1110 insertions, 0 deletions
diff --git a/modules/filters/sed1.c b/modules/filters/sed1.c
new file mode 100644
index 0000000..047f49b
--- /dev/null
+++ b/modules/filters/sed1.c
@@ -0,0 +1,1110 @@
+/*
+ * 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_lib.h"
+#include "libsed.h"
+#include "sed.h"
+#include "apr_strings.h"
+#include "regexp.h"
+
+static const char *const trans[040] = {
+ "\\01",
+ "\\02",
+ "\\03",
+ "\\04",
+ "\\05",
+ "\\06",
+ "\\07",
+ "\\10",
+ "\\11",
+ "\n",
+ "\\13",
+ "\\14",
+ "\\15",
+ "\\16",
+ "\\17",
+ "\\20",
+ "\\21",
+ "\\22",
+ "\\23",
+ "\\24",
+ "\\25",
+ "\\26",
+ "\\27",
+ "\\30",
+ "\\31",
+ "\\32",
+ "\\33",
+ "\\34",
+ "\\35",
+ "\\36",
+ "\\37"
+};
+static const char rub[] = {"\\177"};
+
+extern int sed_step(char *p1, char *p2, int circf, step_vars_storage *vars);
+static int substitute(sed_eval_t *eval, sed_reptr_t *ipc,
+ step_vars_storage *step_vars);
+static apr_status_t execute(sed_eval_t *eval);
+static int match(sed_eval_t *eval, char *expbuf, int gf,
+ step_vars_storage *step_vars);
+static apr_status_t dosub(sed_eval_t *eval, char *rhsbuf, int n,
+ step_vars_storage *step_vars);
+static char *place(sed_eval_t *eval, char *asp, char *al1, char *al2);
+static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc,
+ step_vars_storage *step_vars);
+static apr_status_t wline(sed_eval_t *eval, char *buf, apr_size_t sz);
+static apr_status_t arout(sed_eval_t *eval);
+
+static void eval_errf(sed_eval_t *eval, const char *fmt, ...)
+{
+ if (eval->errfn && eval->pool) {
+ va_list args;
+ const char* error;
+ va_start(args, fmt);
+ error = apr_pvsprintf(eval->pool, fmt, args);
+ eval->errfn(eval->data, error);
+ va_end(args);
+ }
+}
+
+#define INIT_BUF_SIZE 1024
+#define MAX_BUF_SIZE 1024*8192
+
+/*
+ * grow_buffer
+ */
+static apr_status_t grow_buffer(apr_pool_t *pool, char **buffer,
+ char **spend, apr_size_t *cursize,
+ apr_size_t newsize)
+{
+ char* newbuffer = NULL;
+ apr_size_t spendsize = 0;
+ if (*cursize >= newsize) {
+ return APR_SUCCESS;
+ }
+ /* Avoid number of times realloc is called. It could cause huge memory
+ * requirement if line size is huge e.g 2 MB */
+ if (newsize < *cursize * 2) {
+ newsize = *cursize * 2;
+ }
+
+ /* Align it to 4 KB boundary */
+ newsize = (newsize + ((1 << 12) - 1)) & ~((1 << 12) - 1);
+ if (newsize > MAX_BUF_SIZE) {
+ return APR_ENOMEM;
+ }
+ newbuffer = apr_pcalloc(pool, newsize);
+ if (*spend && *buffer && (*cursize > 0)) {
+ spendsize = *spend - *buffer;
+ }
+ if ((*cursize > 0) && *buffer) {
+ memcpy(newbuffer, *buffer, *cursize);
+ }
+ *buffer = newbuffer;
+ *cursize = newsize;
+ if (spend != buffer) {
+ *spend = *buffer + spendsize;
+ }
+ return APR_SUCCESS;
+}
+
+/*
+ * grow_line_buffer
+ */
+static apr_status_t grow_line_buffer(sed_eval_t *eval, apr_size_t newsize)
+{
+ return grow_buffer(eval->pool, &eval->linebuf, &eval->lspend,
+ &eval->lsize, newsize);
+}
+
+/*
+ * grow_hold_buffer
+ */
+static apr_status_t grow_hold_buffer(sed_eval_t *eval, apr_size_t newsize)
+{
+ return grow_buffer(eval->pool, &eval->holdbuf, &eval->hspend,
+ &eval->hsize, newsize);
+}
+
+/*
+ * grow_gen_buffer
+ */
+static apr_status_t grow_gen_buffer(sed_eval_t *eval, apr_size_t newsize,
+ char **gspend)
+{
+ apr_status_t rc = 0;
+ if (gspend == NULL) {
+ gspend = &eval->genbuf;
+ }
+ rc = grow_buffer(eval->pool, &eval->genbuf, gspend,
+ &eval->gsize, newsize);
+ if (rc == APR_SUCCESS) {
+ eval->lcomend = &eval->genbuf[71];
+ }
+ return rc;
+}
+
+/*
+ * appendmem_to_linebuf
+ */
+static apr_status_t appendmem_to_linebuf(sed_eval_t *eval, const char* sz, apr_size_t len)
+{
+ apr_status_t rc = 0;
+ apr_size_t reqsize = (eval->lspend - eval->linebuf) + len;
+ if (eval->lsize < reqsize) {
+ rc = grow_line_buffer(eval, reqsize);
+ if (rc != APR_SUCCESS) {
+ return rc;
+ }
+ }
+ memcpy(eval->lspend, sz, len);
+ eval->lspend += len;
+ return APR_SUCCESS;
+}
+
+/*
+ * append_to_linebuf
+ */
+static apr_status_t append_to_linebuf(sed_eval_t *eval, const char* sz,
+ step_vars_storage *step_vars)
+{
+ apr_size_t len = strlen(sz);
+ char *old_linebuf = eval->linebuf;
+ apr_status_t rc = 0;
+ /* Copy string including null character */
+ rc = appendmem_to_linebuf(eval, sz, len + 1);
+ if (rc != APR_SUCCESS) {
+ return rc;
+ }
+ --eval->lspend; /* lspend will now point to NULL character */
+ /* Sync step_vars after a possible linebuf expansion */
+ if (step_vars && old_linebuf != eval->linebuf) {
+ if (step_vars->loc1) {
+ step_vars->loc1 = step_vars->loc1 - old_linebuf + eval->linebuf;
+ }
+ if (step_vars->loc2) {
+ step_vars->loc2 = step_vars->loc2 - old_linebuf + eval->linebuf;
+ }
+ if (step_vars->locs) {
+ step_vars->locs = step_vars->locs - old_linebuf + eval->linebuf;
+ }
+ }
+ return APR_SUCCESS;
+}
+
+/*
+ * copy_to_linebuf
+ */
+static apr_status_t copy_to_linebuf(sed_eval_t *eval, const char* sz,
+ step_vars_storage *step_vars)
+{
+ eval->lspend = eval->linebuf;
+ return append_to_linebuf(eval, sz, step_vars);
+}
+
+/*
+ * append_to_holdbuf
+ */
+static apr_status_t append_to_holdbuf(sed_eval_t *eval, const char* sz)
+{
+ apr_size_t len = strlen(sz);
+ apr_size_t reqsize = (eval->hspend - eval->holdbuf) + len + 1;
+ apr_status_t rc = 0;
+ if (eval->hsize <= reqsize) {
+ rc = grow_hold_buffer(eval, reqsize);
+ if (rc != APR_SUCCESS) {
+ return rc;
+ }
+ }
+ memcpy(eval->hspend, sz, len + 1);
+ /* hspend will now point to NULL character */
+ eval->hspend += len;
+ return APR_SUCCESS;
+}
+
+/*
+ * copy_to_holdbuf
+ */
+static apr_status_t copy_to_holdbuf(sed_eval_t *eval, const char* sz)
+{
+ eval->hspend = eval->holdbuf;
+ return append_to_holdbuf(eval, sz);
+}
+
+/*
+ * append_to_genbuf
+ */
+static apr_status_t append_to_genbuf(sed_eval_t *eval, const char* sz, char **gspend)
+{
+ apr_size_t len = strlen(sz);
+ apr_size_t reqsize = (*gspend - eval->genbuf) + len + 1;
+ apr_status_t rc = 0;
+ if (eval->gsize < reqsize) {
+ rc = grow_gen_buffer(eval, reqsize, gspend);
+ if (rc != APR_SUCCESS) {
+ return rc;
+ }
+ }
+ memcpy(*gspend, sz, len + 1);
+ /* *gspend will now point to NULL character */
+ *gspend += len;
+ return APR_SUCCESS;
+}
+
+/*
+ * copy_to_genbuf
+ */
+static apr_status_t copy_to_genbuf(sed_eval_t *eval, const char* sz)
+{
+ apr_size_t len = strlen(sz);
+ apr_size_t reqsize = len + 1;
+ apr_status_t rc = APR_SUCCESS;;
+ if (eval->gsize < reqsize) {
+ rc = grow_gen_buffer(eval, reqsize, NULL);
+ if (rc != APR_SUCCESS) {
+ return rc;
+ }
+ }
+ memcpy(eval->genbuf, sz, len + 1);
+ return rc;
+}
+
+/*
+ * sed_init_eval
+ */
+apr_status_t sed_init_eval(sed_eval_t *eval, sed_commands_t *commands, sed_err_fn_t *errfn, void *data, sed_write_fn_t *writefn, apr_pool_t* p)
+{
+ memset(eval, 0, sizeof(*eval));
+ eval->pool = p;
+ eval->writefn = writefn;
+ return sed_reset_eval(eval, commands, errfn, data);
+}
+
+/*
+ * sed_reset_eval
+ */
+apr_status_t sed_reset_eval(sed_eval_t *eval, sed_commands_t *commands, sed_err_fn_t *errfn, void *data)
+{
+ int i;
+
+ eval->errfn = errfn;
+ eval->data = data;
+
+ eval->commands = commands;
+
+ eval->lnum = 0;
+ eval->fout = NULL;
+
+ if (eval->linebuf == NULL) {
+ eval->lsize = INIT_BUF_SIZE;
+ eval->linebuf = apr_pcalloc(eval->pool, eval->lsize);
+ }
+ if (eval->holdbuf == NULL) {
+ eval->hsize = INIT_BUF_SIZE;
+ eval->holdbuf = apr_pcalloc(eval->pool, eval->hsize);
+ }
+ if (eval->genbuf == NULL) {
+ eval->gsize = INIT_BUF_SIZE;
+ eval->genbuf = apr_pcalloc(eval->pool, eval->gsize);
+ }
+ eval->lspend = eval->linebuf;
+ eval->hspend = eval->holdbuf;
+ eval->lcomend = &eval->genbuf[71];
+
+ for (i = 0; i < sizeof(eval->abuf) / sizeof(eval->abuf[0]); i++)
+ eval->abuf[i] = NULL;
+ eval->aptr = eval->abuf;
+ eval->pending = NULL;
+ eval->inar = apr_pcalloc(eval->pool, commands->nrep * sizeof(unsigned char));
+ eval->nrep = commands->nrep;
+
+ eval->dolflag = 0;
+ eval->sflag = 0;
+ eval->jflag = 0;
+ eval->delflag = 0;
+ eval->lreadyflag = 0;
+ eval->quitflag = 0;
+ eval->finalflag = 1; /* assume we're evaluating only one file/stream */
+ eval->numpass = 0;
+ eval->nullmatch = 0;
+ eval->col = 0;
+
+ for (i = 0; i < commands->nfiles; i++) {
+ const char* filename = commands->fname[i];
+ if (apr_file_open(&eval->fcode[i], filename,
+ APR_WRITE | APR_CREATE, APR_OS_DEFAULT,
+ eval->pool) != APR_SUCCESS) {
+ eval_errf(eval, SEDERR_COMES, filename);
+ return APR_EGENERAL;
+ }
+ }
+
+ return APR_SUCCESS;
+}
+
+/*
+ * sed_destroy_eval
+ */
+void sed_destroy_eval(sed_eval_t *eval)
+{
+ int i;
+ /* eval->linebuf, eval->holdbuf, eval->genbuf and eval->inar are allocated
+ * on pool. It will be freed when pool will be freed */
+ for (i = 0; i < eval->commands->nfiles; i++) {
+ if (eval->fcode[i] != NULL) {
+ apr_file_close(eval->fcode[i]);
+ eval->fcode[i] = NULL;
+ }
+ }
+}
+
+/*
+ * sed_eval_file
+ */
+apr_status_t sed_eval_file(sed_eval_t *eval, apr_file_t *fin, void *fout)
+{
+ for (;;) {
+ char buf[1024];
+ apr_size_t read_bytes = 0;
+
+ read_bytes = sizeof(buf);
+ if (apr_file_read(fin, buf, &read_bytes) != APR_SUCCESS)
+ break;
+
+ if (sed_eval_buffer(eval, buf, read_bytes, fout) != APR_SUCCESS)
+ return APR_EGENERAL;
+
+ if (eval->quitflag)
+ return APR_SUCCESS;
+ }
+
+ return sed_finalize_eval(eval, fout);
+}
+
+/*
+ * sed_eval_buffer
+ */
+apr_status_t sed_eval_buffer(sed_eval_t *eval, const char *buf, apr_size_t bufsz, void *fout)
+{
+ apr_status_t rv;
+
+ if (eval->quitflag)
+ return APR_SUCCESS;
+
+ if (!sed_canbe_finalized(eval->commands)) {
+ /* Commands were not finalized properly. */
+ const char* error = sed_get_finalize_error(eval->commands, eval->pool);
+ if (error) {
+ eval_errf(eval, error);
+ return APR_EGENERAL;
+ }
+ }
+
+ eval->fout = fout;
+
+ /* Process leftovers */
+ if (bufsz && eval->lreadyflag) {
+ eval->lreadyflag = 0;
+ eval->lspend--;
+ *eval->lspend = '\0';
+ rv = execute(eval);
+ if (rv != APR_SUCCESS)
+ return rv;
+ }
+
+ while (bufsz) {
+ apr_status_t rc = 0;
+ char *n;
+ apr_size_t llen;
+
+ n = memchr(buf, '\n', bufsz);
+ if (n == NULL)
+ break;
+
+ llen = n - buf;
+ if (llen == bufsz - 1) {
+ /* This might be the last line; delay its processing */
+ eval->lreadyflag = 1;
+ break;
+ }
+
+ rc = appendmem_to_linebuf(eval, buf, llen + 1);
+ if (rc != APR_SUCCESS) {
+ return rc;
+ }
+ --eval->lspend;
+ /* replace new line character with NULL */
+ *eval->lspend = '\0';
+ buf += (llen + 1);
+ bufsz -= (llen + 1);
+ rv = execute(eval);
+ if (rv != APR_SUCCESS)
+ return rv;
+ if (eval->quitflag)
+ break;
+ }
+
+ /* Save the leftovers for later */
+ if (bufsz) {
+ apr_status_t rc = appendmem_to_linebuf(eval, buf, bufsz);
+ if (rc != APR_SUCCESS) {
+ return rc;
+ }
+ }
+
+ return APR_SUCCESS;
+}
+
+/*
+ * sed_finalize_eval
+ */
+apr_status_t sed_finalize_eval(sed_eval_t *eval, void *fout)
+{
+ if (eval->quitflag)
+ return APR_SUCCESS;
+
+ if (eval->finalflag)
+ eval->dolflag = 1;
+
+ eval->fout = fout;
+
+ /* Process leftovers */
+ if (eval->lspend > eval->linebuf) {
+ apr_status_t rv;
+ apr_status_t rc = 0;
+
+ if (eval->lreadyflag) {
+ eval->lreadyflag = 0;
+ eval->lspend--;
+ } else {
+ /* Code can probably reach here when last character in output
+ * buffer is not a newline.
+ */
+ /* Assure space for NULL */
+ rc = append_to_linebuf(eval, "", NULL);
+ if (rc != APR_SUCCESS) {
+ return rc;
+ }
+ }
+
+ *eval->lspend = '\0';
+ rv = execute(eval);
+ if (rv != APR_SUCCESS)
+ return rv;
+ }
+
+ eval->quitflag = 1;
+
+ return APR_SUCCESS;
+}
+
+/*
+ * execute
+ */
+static apr_status_t execute(sed_eval_t *eval)
+{
+ sed_reptr_t *ipc = eval->commands->ptrspace;
+ step_vars_storage step_vars;
+ apr_status_t rv = APR_SUCCESS;
+
+ eval->lnum++;
+
+ eval->sflag = 0;
+
+ if (eval->pending) {
+ ipc = eval->pending;
+ eval->pending = NULL;
+ }
+
+ memset(&step_vars, 0, sizeof(step_vars));
+
+ while (ipc->command) {
+ char *p1;
+ char *p2;
+ int c;
+
+ p1 = ipc->ad1;
+ p2 = ipc->ad2;
+
+ if (p1) {
+
+ if (eval->inar[ipc->nrep]) {
+ if (*p2 == CEND) {
+ p1 = 0;
+ } else if (*p2 == CLNUM) {
+ c = (unsigned char)p2[1];
+ if (eval->lnum > eval->commands->tlno[c]) {
+ eval->inar[ipc->nrep] = 0;
+ if (ipc->negfl)
+ goto yes;
+ ipc = ipc->next;
+ continue;
+ }
+ if (eval->lnum == eval->commands->tlno[c]) {
+ eval->inar[ipc->nrep] = 0;
+ }
+ } else if (match(eval, p2, 0, &step_vars)) {
+ eval->inar[ipc->nrep] = 0;
+ }
+ } else if (*p1 == CEND) {
+ if (!eval->dolflag) {
+ if (ipc->negfl)
+ goto yes;
+ ipc = ipc->next;
+ continue;
+ }
+ } else if (*p1 == CLNUM) {
+ c = (unsigned char)p1[1];
+ if (eval->lnum != eval->commands->tlno[c]) {
+ if (ipc->negfl)
+ goto yes;
+ ipc = ipc->next;
+ continue;
+ }
+ if (p2)
+ eval->inar[ipc->nrep] = 1;
+ } else if (match(eval, p1, 0, &step_vars)) {
+ if (p2)
+ eval->inar[ipc->nrep] = 1;
+ } else {
+ if (ipc->negfl)
+ goto yes;
+ ipc = ipc->next;
+ continue;
+ }
+ }
+
+ if (ipc->negfl) {
+ ipc = ipc->next;
+ continue;
+ }
+
+yes:
+ rv = command(eval, ipc, &step_vars);
+ if (rv != APR_SUCCESS)
+ return rv;
+
+ if (eval->quitflag)
+ return APR_SUCCESS;
+
+ if (eval->pending)
+ return APR_SUCCESS;
+
+ if (eval->delflag)
+ break;
+
+ if (eval->jflag) {
+ eval->jflag = 0;
+ if ((ipc = ipc->lb1) == 0) {
+ ipc = eval->commands->ptrspace;
+ break;
+ }
+ } else
+ ipc = ipc->next;
+ }
+
+ if (!eval->commands->nflag && !eval->delflag) {
+ rv = wline(eval, eval->linebuf, eval->lspend - eval->linebuf);
+ if (rv != APR_SUCCESS)
+ return rv;
+ }
+
+ if (eval->aptr > eval->abuf)
+ rv = arout(eval);
+
+ eval->delflag = 0;
+
+ eval->lspend = eval->linebuf;
+
+ return rv;
+}
+
+/*
+ * match
+ */
+static int match(sed_eval_t *eval, char *expbuf, int gf,
+ step_vars_storage *step_vars)
+{
+ char *p1;
+ int circf;
+
+ if (gf) {
+ if (*expbuf) return(0);
+ step_vars->locs = p1 = step_vars->loc2;
+ } else {
+ p1 = eval->linebuf;
+ step_vars->locs = 0;
+ }
+
+ circf = *expbuf++;
+ return(sed_step(p1, expbuf, circf, step_vars));
+}
+
+/*
+ * substitute
+ */
+static int substitute(sed_eval_t *eval, sed_reptr_t *ipc,
+ step_vars_storage *step_vars)
+{
+ if (match(eval, ipc->re1, 0, step_vars) == 0) return(0);
+
+ eval->numpass = 0;
+ eval->sflag = 0; /* Flags if any substitution was made */
+ if (dosub(eval, ipc->rhs, ipc->gfl, step_vars) != APR_SUCCESS)
+ return -1;
+
+ if (ipc->gfl) {
+ while (*step_vars->loc2) {
+ if (match(eval, ipc->re1, 1, step_vars) == 0) break;
+ if (dosub(eval, ipc->rhs, ipc->gfl, step_vars) != APR_SUCCESS)
+ return -1;
+ }
+ }
+ return(eval->sflag);
+}
+
+/*
+ * dosub
+ */
+static apr_status_t dosub(sed_eval_t *eval, char *rhsbuf, int n,
+ step_vars_storage *step_vars)
+{
+ char *lp, *sp, *rp;
+ int c;
+ apr_status_t rv = APR_SUCCESS;
+
+ if (n > 0 && n < 999) {
+ eval->numpass++;
+ if (n != eval->numpass) return APR_SUCCESS;
+ }
+ eval->sflag = 1;
+ lp = eval->linebuf;
+ sp = eval->genbuf;
+ rp = rhsbuf;
+ sp = place(eval, sp, lp, step_vars->loc1);
+ if (sp == NULL) {
+ return APR_EGENERAL;
+ }
+ while ((c = *rp++) != 0) {
+ if (c == '&') {
+ sp = place(eval, sp, step_vars->loc1, step_vars->loc2);
+ if (sp == NULL) {
+ return APR_EGENERAL;
+ }
+ }
+ else if (c == '\\') {
+ c = *rp++;
+ if (c >= '1' && c < NBRA+'1') {
+ sp = place(eval, sp, step_vars->braslist[c-'1'],
+ step_vars->braelist[c-'1']);
+ if (sp == NULL)
+ return APR_EGENERAL;
+ }
+ else
+ *sp++ = c;
+ } else
+ *sp++ = c;
+ if (sp >= eval->genbuf + eval->gsize) {
+ /* expand genbuf and set the sp appropriately */
+ rv = grow_gen_buffer(eval, eval->gsize + 1024, &sp);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ }
+ }
+ lp = step_vars->loc2;
+ step_vars->loc2 = sp - eval->genbuf + eval->linebuf;
+ rv = append_to_genbuf(eval, lp, &sp);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ rv = copy_to_linebuf(eval, eval->genbuf, step_vars);
+ return rv;
+}
+
+/*
+ * place
+ */
+static char *place(sed_eval_t *eval, char *asp, char *al1, char *al2)
+{
+ char *sp = asp;
+ apr_size_t n = al2 - al1;
+ apr_size_t reqsize = (sp - eval->genbuf) + n + 1;
+
+ if (eval->gsize < reqsize) {
+ apr_status_t rc = grow_gen_buffer(eval, reqsize, &sp);
+ if (rc != APR_SUCCESS) {
+ return NULL;
+ }
+ }
+ memcpy(sp, al1, n);
+ return sp + n;
+}
+
+/*
+ * command
+ */
+static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc,
+ step_vars_storage *step_vars)
+{
+ int i;
+ char *p1, *p2;
+ const char *p3;
+ int length;
+ char sz[32]; /* 32 bytes enough to store 64 bit integer in decimal */
+ apr_status_t rv = APR_SUCCESS;
+
+
+ switch(ipc->command) {
+
+ case ACOM:
+ if (eval->aptr >= &eval->abuf[SED_ABUFSIZE]) {
+ eval_errf(eval, SEDERR_TMAMES, eval->lnum);
+ } else {
+ *eval->aptr++ = ipc;
+ *eval->aptr = NULL;
+ }
+ break;
+
+ case CCOM:
+ eval->delflag = 1;
+ if (!eval->inar[ipc->nrep] || eval->dolflag) {
+ for (p1 = ipc->re1; *p1; p1++)
+ ;
+ rv = wline(eval, ipc->re1, p1 - ipc->re1);
+ }
+ break;
+
+ case DCOM:
+ eval->delflag++;
+ break;
+
+ case CDCOM:
+ p1 = eval->linebuf;
+
+ while (*p1 != '\n') {
+ if (*p1++ == 0) {
+ eval->delflag++;
+ return APR_SUCCESS;
+ }
+ }
+
+ p1++;
+ rv = copy_to_linebuf(eval, p1, step_vars);
+ if (rv != APR_SUCCESS) return rv;
+ eval->jflag++;
+ break;
+
+ case EQCOM:
+ length = apr_snprintf(sz, sizeof(sz), "%d", (int) eval->lnum);
+ rv = wline(eval, sz, length);
+ break;
+
+ case GCOM:
+ rv = copy_to_linebuf(eval, eval->holdbuf, step_vars);
+ if (rv != APR_SUCCESS) return rv;
+ break;
+
+ case CGCOM:
+ rv = append_to_linebuf(eval, "\n", step_vars);
+ if (rv != APR_SUCCESS) return rv;
+ rv = append_to_linebuf(eval, eval->holdbuf, step_vars);
+ if (rv != APR_SUCCESS) return rv;
+ break;
+
+ case HCOM:
+ rv = copy_to_holdbuf(eval, eval->linebuf);
+ if (rv != APR_SUCCESS) return rv;
+ break;
+
+ case CHCOM:
+ rv = append_to_holdbuf(eval, "\n");
+ if (rv != APR_SUCCESS) return rv;
+ rv = append_to_holdbuf(eval, eval->linebuf);
+ if (rv != APR_SUCCESS) return rv;
+ break;
+
+ case ICOM:
+ for (p1 = ipc->re1; *p1; p1++);
+ rv = wline(eval, ipc->re1, p1 - ipc->re1);
+ break;
+
+ case BCOM:
+ eval->jflag = 1;
+ break;
+
+ case LCOM:
+ p1 = eval->linebuf;
+ p2 = eval->genbuf;
+ eval->genbuf[72] = 0;
+ while (*p1) {
+ if ((unsigned char)*p1 >= 040) {
+ if (*p1 == 0177) {
+ p3 = rub;
+ while ((*p2++ = *p3++) != 0)
+ if (p2 >= eval->lcomend) {
+ *p2 = '\\';
+ rv = wline(eval, eval->genbuf,
+ strlen(eval->genbuf));
+ if (rv != APR_SUCCESS)
+ return rv;
+ p2 = eval->genbuf;
+ }
+ p2--;
+ p1++;
+ continue;
+ }
+ if (!isprint(*p1 & 0377)) {
+ *p2++ = '\\';
+ if (p2 >= eval->lcomend) {
+ *p2 = '\\';
+ rv = wline(eval, eval->genbuf,
+ strlen(eval->genbuf));
+ if (rv != APR_SUCCESS)
+ return rv;
+ p2 = eval->genbuf;
+ }
+ *p2++ = (*p1 >> 6) + '0';
+ if (p2 >= eval->lcomend) {
+ *p2 = '\\';
+ rv = wline(eval, eval->genbuf,
+ strlen(eval->genbuf));
+ if (rv != APR_SUCCESS)
+ return rv;
+ p2 = eval->genbuf;
+ }
+ *p2++ = ((*p1 >> 3) & 07) + '0';
+ if (p2 >= eval->lcomend) {
+ *p2 = '\\';
+ rv = wline(eval, eval->genbuf,
+ strlen(eval->genbuf));
+ if (rv != APR_SUCCESS)
+ return rv;
+ p2 = eval->genbuf;
+ }
+ *p2++ = (*p1++ & 07) + '0';
+ if (p2 >= eval->lcomend) {
+ *p2 = '\\';
+ rv = wline(eval, eval->genbuf,
+ strlen(eval->genbuf));
+ if (rv != APR_SUCCESS)
+ return rv;
+ p2 = eval->genbuf;
+ }
+ } else {
+ *p2++ = *p1++;
+ if (p2 >= eval->lcomend) {
+ *p2 = '\\';
+ rv = wline(eval, eval->genbuf,
+ strlen(eval->genbuf));
+ if (rv != APR_SUCCESS)
+ return rv;
+ p2 = eval->genbuf;
+ }
+ }
+ } else {
+ p3 = trans[(unsigned char)*p1-1];
+ while ((*p2++ = *p3++) != 0)
+ if (p2 >= eval->lcomend) {
+ *p2 = '\\';
+ rv = wline(eval, eval->genbuf,
+ strlen(eval->genbuf));
+ if (rv != APR_SUCCESS)
+ return rv;
+ p2 = eval->genbuf;
+ }
+ p2--;
+ p1++;
+ }
+ }
+ *p2 = 0;
+ rv = wline(eval, eval->genbuf, strlen(eval->genbuf));
+ break;
+
+ case NCOM:
+ if (!eval->commands->nflag) {
+ rv = wline(eval, eval->linebuf, eval->lspend - eval->linebuf);
+ if (rv != APR_SUCCESS)
+ return rv;
+ }
+
+ if (eval->aptr > eval->abuf) {
+ rv = arout(eval);
+ if (rv != APR_SUCCESS)
+ return rv;
+ }
+ eval->lspend = eval->linebuf;
+ eval->pending = ipc->next;
+ break;
+
+ case CNCOM:
+ if (eval->aptr > eval->abuf) {
+ rv = arout(eval);
+ if (rv != APR_SUCCESS)
+ return rv;
+ }
+ rv = append_to_linebuf(eval, "\n", step_vars);
+ if (rv != APR_SUCCESS) return rv;
+ eval->pending = ipc->next;
+ break;
+
+ case PCOM:
+ rv = wline(eval, eval->linebuf, eval->lspend - eval->linebuf);
+ break;
+
+ case CPCOM:
+ for (p1 = eval->linebuf; *p1 != '\n' && *p1 != '\0'; p1++);
+ rv = wline(eval, eval->linebuf, p1 - eval->linebuf);
+ break;
+
+ case QCOM:
+ if (!eval->commands->nflag) {
+ rv = wline(eval, eval->linebuf, eval->lspend - eval->linebuf);
+ if (rv != APR_SUCCESS)
+ break;
+ }
+
+ if (eval->aptr > eval->abuf) {
+ rv = arout(eval);
+ if (rv != APR_SUCCESS)
+ return rv;
+ }
+
+ eval->quitflag = 1;
+ break;
+
+ case RCOM:
+ if (eval->aptr >= &eval->abuf[SED_ABUFSIZE]) {
+ eval_errf(eval, SEDERR_TMRMES, eval->lnum);
+ } else {
+ *eval->aptr++ = ipc;
+ *eval->aptr = NULL;
+ }
+ break;
+
+ case SCOM:
+ i = substitute(eval, ipc, step_vars);
+ if (i == -1) {
+ return APR_EGENERAL;
+ }
+ if (ipc->pfl && eval->commands->nflag && i) {
+ if (ipc->pfl == 1) {
+ rv = wline(eval, eval->linebuf, eval->lspend -
+ eval->linebuf);
+ if (rv != APR_SUCCESS)
+ return rv;
+ } else {
+ for (p1 = eval->linebuf; *p1 != '\n' && *p1 != '\0'; p1++);
+ rv = wline(eval, eval->linebuf, p1 - eval->linebuf);
+ if (rv != APR_SUCCESS)
+ return rv;
+ }
+ }
+ if (i && (ipc->findex >= 0) && eval->fcode[ipc->findex])
+ apr_file_printf(eval->fcode[ipc->findex], "%s\n",
+ eval->linebuf);
+ break;
+
+ case TCOM:
+ if (eval->sflag == 0) break;
+ eval->sflag = 0;
+ eval->jflag = 1;
+ break;
+
+ case WCOM:
+ if (ipc->findex >= 0)
+ apr_file_printf(eval->fcode[ipc->findex], "%s\n",
+ eval->linebuf);
+ break;
+
+ case XCOM:
+ rv = copy_to_genbuf(eval, eval->linebuf);
+ if (rv != APR_SUCCESS) return rv;
+ rv = copy_to_linebuf(eval, eval->holdbuf, step_vars);
+ if (rv != APR_SUCCESS) return rv;
+ rv = copy_to_holdbuf(eval, eval->genbuf);
+ if (rv != APR_SUCCESS) return rv;
+ break;
+
+ case YCOM:
+ p1 = eval->linebuf;
+ p2 = ipc->re1;
+ while ((*p1 = p2[(unsigned char)*p1]) != 0) p1++;
+ break;
+ }
+ return rv;
+}
+
+/*
+ * arout
+ */
+static apr_status_t arout(sed_eval_t *eval)
+{
+ apr_status_t rv = APR_SUCCESS;
+ eval->aptr = eval->abuf - 1;
+ while (*++eval->aptr) {
+ if ((*eval->aptr)->command == ACOM) {
+ char *p1;
+
+ for (p1 = (*eval->aptr)->re1; *p1; p1++);
+ rv = wline(eval, (*eval->aptr)->re1, p1 - (*eval->aptr)->re1);
+ if (rv != APR_SUCCESS)
+ return rv;
+ } else {
+ apr_file_t *fi = NULL;
+ char buf[512];
+ apr_size_t n = sizeof(buf);
+
+ if (apr_file_open(&fi, (*eval->aptr)->re1, APR_READ, 0, eval->pool)
+ != APR_SUCCESS)
+ continue;
+ while ((apr_file_read(fi, buf, &n)) == APR_SUCCESS) {
+ if (n == 0)
+ break;
+ rv = eval->writefn(eval->fout, buf, n);
+ if (rv != APR_SUCCESS) {
+ apr_file_close(fi);
+ return rv;
+ }
+ n = sizeof(buf);
+ }
+ apr_file_close(fi);
+ }
+ }
+ eval->aptr = eval->abuf;
+ *eval->aptr = NULL;
+ return rv;
+}
+
+/*
+ * wline
+ */
+static apr_status_t wline(sed_eval_t *eval, char *buf, apr_size_t sz)
+{
+ apr_status_t rv = APR_SUCCESS;
+ rv = eval->writefn(eval->fout, buf, sz);
+ if (rv != APR_SUCCESS)
+ return rv;
+ rv = eval->writefn(eval->fout, "\n", 1);
+ return rv;
+}
+