mirror of
https://github.com/apache/httpd.git
synced 2025-08-01 07:26:57 +03:00
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1748653 13f79535-47bb-0310-9956-ffa450edef68
1027 lines
28 KiB
C
1027 lines
28 KiB
C
/*
|
|
* 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;
|
|
}
|
|
|
|
|