2 * Copyright (c) 2005, 2008 Sun Microsystems, Inc. All Rights Reserved.
3 * Use is subject to license terms.
5 * Copyright (c) 1984 AT&T
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0.
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 #include "apr_strings.h"
29 static int fcomp(sed_commands_t *commands, apr_file_t *fin);
30 static char *compsub(sed_commands_t *commands,
31 sed_comp_args *compargs, char *rhsbuf);
32 static int rline(sed_commands_t *commands, apr_file_t *fin,
33 char *lbuf, char *lbend);
34 static char *address(sed_commands_t *commands, char *expbuf,
35 apr_status_t* status);
36 static char *text(sed_commands_t *commands, char *textbuf, char *endbuf);
37 static sed_label_t *search(sed_commands_t *commands);
38 static char *ycomp(sed_commands_t *commands, char *expbuf);
39 static char *comple(sed_commands_t *commands, sed_comp_args *compargs,
40 char *x1, char *ep, char *x3, char x4);
41 static sed_reptr_t *alloc_reptr(sed_commands_t *commands);
42 static int check_finalized(const sed_commands_t *commands);
44 void command_errf(sed_commands_t *commands, const char *fmt, ...)
46 if (commands->errfn && commands->pool) {
50 error = apr_pvsprintf(commands->pool, fmt, args);
51 commands->errfn(commands->data, error);
59 apr_status_t sed_init_commands(sed_commands_t *commands, sed_err_fn_t *errfn, void *data,
62 memset(commands, 0, sizeof(*commands));
64 commands->errfn = errfn;
65 commands->data = data;
67 commands->labtab = commands->ltab;
68 commands->lab = commands->labtab + 1;
71 commands->respace = apr_pcalloc(p, RESIZE);
72 if (commands->respace == NULL) {
73 command_errf(commands, SEDERR_OOMMES);
77 commands->rep = alloc_reptr(commands);
78 if (commands->rep == NULL)
81 commands->rep->ad1 = commands->respace;
82 commands->reend = &commands->respace[RESIZE - 1];
83 commands->labend = &commands->labtab[SED_LABSIZE];
84 commands->canbefinal = 1;
90 * sed_destroy_commands
92 void sed_destroy_commands(sed_commands_t *commands)
99 apr_status_t sed_compile_string(sed_commands_t *commands, const char *s)
106 rv = fcomp(commands, NULL);
107 if (rv == APR_SUCCESS)
108 commands->canbefinal = check_finalized(commands);
112 return (rv != 0 ? APR_EGENERAL : APR_SUCCESS);
118 apr_status_t sed_compile_file(sed_commands_t *commands, apr_file_t *fin)
120 apr_status_t rv = fcomp(commands, fin);
121 return (rv != 0 ? APR_EGENERAL : APR_SUCCESS);
125 * sed_get_finalize_error
127 char* sed_get_finalize_error(const sed_commands_t *commands, apr_pool_t* pool)
129 const sed_label_t *lab;
130 if (commands->depth) {
131 return SEDERR_TMOMES;
134 /* Empty branch chain is not a issue */
135 for (lab = commands->labtab + 1; lab < commands->lab; lab++) {
137 if (lab->address == 0) {
138 error = apr_psprintf(pool, SEDERR_ULMES, lab->asc);
143 return SEDERR_INTERNAL;
150 * sed_canbe_finalized
152 int sed_canbe_finalized(const sed_commands_t *commands)
154 return commands->canbefinal;
160 static int check_finalized(const sed_commands_t *commands)
162 const sed_label_t *lab;
163 if (commands->depth) {
167 /* Empty branch chain is not a issue */
168 for (lab = commands->labtab + 1; lab < commands->lab; lab++) {
169 if (lab->address == 0 || (lab->chain)) {
179 static void dechain(sed_label_t *lpt, sed_reptr_t *address)
182 if ((lpt == NULL) || (lpt->chain == NULL) || (address == NULL))
199 static int fcomp(sed_commands_t *commands, apr_file_t *fin)
202 sed_reptr_t *pt, *pt1;
205 char fnamebuf[APR_PATH_MAX];
207 sed_comp_args compargs;
209 op = commands->lastre;
210 if (!commands->linebuf) {
211 commands->linebuf = apr_pcalloc(commands->pool, LBSIZE + 1);
214 if (rline(commands, fin, commands->linebuf,
215 (commands->linebuf + LBSIZE + 1)) < 0)
217 if (*commands->linebuf == '#') {
218 if (commands->linebuf[1] == 'n')
222 commands->cp = commands->linebuf;
227 if (rline(commands, fin, commands->linebuf,
228 (commands->linebuf + LBSIZE + 1)) < 0)
231 commands->cp = commands->linebuf;
234 while (*commands->cp == ' ' || *commands->cp == '\t')
236 if (*commands->cp == '\0' || *commands->cp == '#')
238 if (*commands->cp == ';') {
243 p = address(commands, commands->rep->ad1, &status);
244 if (status != APR_SUCCESS) {
245 command_errf(commands, SEDERR_CGMES, commands->linebuf);
249 if (p == commands->rep->ad1) {
251 commands->rep->ad1 = op;
253 command_errf(commands, SEDERR_NRMES);
257 p = commands->rep->ad1;
258 commands->rep->ad1 = 0;
260 op = commands->rep->ad1;
261 if (*commands->cp == ',' || *commands->cp == ';') {
263 commands->rep->ad2 = p;
264 p = address(commands, commands->rep->ad2, &status);
265 if ((status != APR_SUCCESS) || (p == 0)) {
266 command_errf(commands, SEDERR_CGMES, commands->linebuf);
269 if (p == commands->rep->ad2)
270 commands->rep->ad2 = op;
272 op = commands->rep->ad2;
274 commands->rep->ad2 = 0;
277 if(p > &commands->respace[RESIZE-1]) {
278 command_errf(commands, SEDERR_TMMES, commands->linebuf);
282 while (*commands->cp == ' ' || *commands->cp == '\t')
286 switch(*commands->cp++) {
288 command_errf(commands, SEDERR_UCMES, commands->linebuf);
292 commands->rep->negfl = 1;
296 commands->rep->command = BCOM;
297 commands->rep->negfl = !(commands->rep->negfl);
298 commands->cmpend[commands->depth++] = &commands->rep->lb1;
299 commands->rep = alloc_reptr(commands);
300 commands->rep->ad1 = p;
301 if (*commands->cp == '\0')
306 if (commands->rep->ad1) {
307 command_errf(commands, SEDERR_AD0MES, commands->linebuf);
311 if (--commands->depth < 0) {
312 command_errf(commands, SEDERR_TMCMES);
315 *commands->cmpend[commands->depth] = commands->rep;
317 commands->rep->ad1 = p;
321 commands->rep->command = EQCOM;
322 if (commands->rep->ad2) {
323 command_errf(commands, SEDERR_AD1MES, commands->linebuf);
329 if (commands->rep->ad1) {
330 command_errf(commands, SEDERR_AD0MES, commands->linebuf);
334 while (*commands->cp++ == ' ');
337 tp = commands->lab->asc;
338 while ((*tp++ = *commands->cp++)) {
339 if (tp >= &(commands->lab->asc[8])) {
340 command_errf(commands, SEDERR_LTLMES, commands->linebuf);
346 if ((lpt = search(commands)) != NULL) {
348 command_errf(commands, SEDERR_DLMES, commands->linebuf);
351 dechain(lpt, commands->rep);
353 commands->lab->chain = 0;
355 if (++commands->lab >= commands->labend) {
356 command_errf(commands, SEDERR_TMLMES, commands->linebuf);
360 lpt->address = commands->rep;
361 commands->rep->ad1 = p;
366 commands->rep->command = ACOM;
367 if (commands->rep->ad2) {
368 command_errf(commands, SEDERR_AD1MES, commands->linebuf);
371 if (*commands->cp == '\\')
373 if (*commands->cp++ != '\n') {
374 command_errf(commands, SEDERR_CGMES, commands->linebuf);
377 commands->rep->re1 = p;
378 p = text(commands, commands->rep->re1, commands->reend);
384 commands->rep->command = CCOM;
385 if (*commands->cp == '\\') commands->cp++;
386 if (*commands->cp++ != ('\n')) {
387 command_errf(commands, SEDERR_CGMES, commands->linebuf);
390 commands->rep->re1 = p;
391 p = text(commands, commands->rep->re1, commands->reend);
397 commands->rep->command = ICOM;
398 if (commands->rep->ad2) {
399 command_errf(commands, SEDERR_AD1MES, commands->linebuf);
402 if (*commands->cp == '\\') commands->cp++;
403 if (*commands->cp++ != ('\n')) {
404 command_errf(commands, SEDERR_CGMES, commands->linebuf);
407 commands->rep->re1 = p;
408 p = text(commands, commands->rep->re1, commands->reend);
414 commands->rep->command = GCOM;
418 commands->rep->command = CGCOM;
422 commands->rep->command = HCOM;
426 commands->rep->command = CHCOM;
430 commands->rep->command = TCOM;
434 commands->rep->command = BCOM;
436 while (*commands->cp++ == ' ');
439 if (*commands->cp == '\0') {
440 if ((pt = commands->labtab->chain) != NULL) {
441 while ((pt1 = pt->lb1) != NULL)
443 pt->lb1 = commands->rep;
445 commands->labtab->chain = commands->rep;
448 tp = commands->lab->asc;
449 while ((*tp++ = *commands->cp++))
450 if (tp >= &(commands->lab->asc[8])) {
451 command_errf(commands, SEDERR_LTLMES, commands->linebuf);
457 if ((lpt = search(commands)) != NULL) {
459 commands->rep->lb1 = lpt->address;
462 while ((pt1 = pt->lb1) != NULL)
464 pt->lb1 = commands->rep;
467 commands->lab->chain = commands->rep;
468 commands->lab->address = 0;
469 if (++commands->lab >= commands->labend) {
470 command_errf(commands, SEDERR_TMLMES, commands->linebuf);
477 commands->rep->command = NCOM;
481 commands->rep->command = CNCOM;
485 commands->rep->command = PCOM;
489 commands->rep->command = CPCOM;
493 commands->rep->command = RCOM;
494 if (commands->rep->ad2) {
495 command_errf(commands, SEDERR_AD1MES, commands->linebuf);
498 if (*commands->cp++ != ' ') {
499 command_errf(commands, SEDERR_CGMES, commands->linebuf);
502 commands->rep->re1 = p;
503 p = text(commands, commands->rep->re1, commands->reend);
509 commands->rep->command = DCOM;
513 commands->rep->command = CDCOM;
514 commands->rep->lb1 = commands->ptrspace;
518 commands->rep->command = QCOM;
519 if (commands->rep->ad2) {
520 command_errf(commands, SEDERR_AD1MES, commands->linebuf);
526 commands->rep->command = LCOM;
530 commands->rep->command = SCOM;
531 commands->sseof = *commands->cp++;
532 commands->rep->re1 = p;
533 p = comple(commands, &compargs, (char *) 0, commands->rep->re1,
534 commands->reend, commands->sseof);
537 if (p == commands->rep->re1) {
539 commands->rep->re1 = op;
541 command_errf(commands, SEDERR_NRMES);
545 op = commands->rep->re1;
546 commands->rep->rhs = p;
548 p = compsub(commands, &compargs, commands->rep->rhs);
552 if (*commands->cp == 'g') {
554 commands->rep->gfl = 999;
555 } else if (commands->gflag)
556 commands->rep->gfl = 999;
558 if (*commands->cp >= '1' && *commands->cp <= '9') {
559 i = *commands->cp - '0';
563 if (ii < '0' || ii > '9')
567 command_errf(commands, SEDERR_TOOBIG, commands->linebuf);
572 commands->rep->gfl = i;
575 if (*commands->cp == 'p') {
577 commands->rep->pfl = 1;
580 if (*commands->cp == 'P') {
582 commands->rep->pfl = 2;
585 if (*commands->cp == 'w') {
587 if (*commands->cp++ != ' ') {
588 command_errf(commands, SEDERR_SMMES, commands->linebuf);
591 if (text(commands, fnamebuf, &fnamebuf[APR_PATH_MAX]) == NULL) {
592 command_errf(commands, SEDERR_FNTL, commands->linebuf);
595 for (i = commands->nfiles - 1; i >= 0; i--)
596 if (strcmp(fnamebuf,commands->fname[i]) == 0) {
597 commands->rep->findex = i;
600 if (commands->nfiles >= NWFILES) {
601 command_errf(commands, SEDERR_TMWFMES);
604 commands->fname[commands->nfiles] =
605 apr_pstrdup(commands->pool, fnamebuf);
606 if (commands->fname[commands->nfiles] == NULL) {
607 command_errf(commands, SEDERR_OOMMES);
610 commands->rep->findex = commands->nfiles++;
615 commands->rep->command = WCOM;
616 if (*commands->cp++ != ' ') {
617 command_errf(commands, SEDERR_SMMES, commands->linebuf);
620 if (text(commands, fnamebuf, &fnamebuf[APR_PATH_MAX]) == NULL) {
621 command_errf(commands, SEDERR_FNTL, commands->linebuf);
624 for (i = commands->nfiles - 1; i >= 0; i--)
625 if (strcmp(fnamebuf, commands->fname[i]) == 0) {
626 commands->rep->findex = i;
629 if (commands->nfiles >= NWFILES) {
630 command_errf(commands, SEDERR_TMWFMES);
633 if ((commands->fname[commands->nfiles] =
634 apr_pstrdup(commands->pool, fnamebuf)) == NULL) {
635 command_errf(commands, SEDERR_OOMMES);
639 commands->rep->findex = commands->nfiles++;
643 commands->rep->command = XCOM;
647 commands->rep->command = YCOM;
648 commands->sseof = *commands->cp++;
649 commands->rep->re1 = p;
650 p = ycomp(commands, commands->rep->re1);
656 commands->rep = alloc_reptr(commands);
658 commands->rep->ad1 = p;
660 if (*commands->cp++ != '\0') {
661 if (commands->cp[-1] == ';')
663 command_errf(commands, SEDERR_CGMES, commands->linebuf);
667 commands->rep->command = 0;
668 commands->lastre = op;
673 static char *compsub(sed_commands_t *commands,
674 sed_comp_args *compargs, char *rhsbuf)
681 if(p > &commands->respace[RESIZE-1]) {
682 command_errf(commands, SEDERR_TMMES, commands->linebuf);
685 if((*p = *q++) == '\\') {
687 if(p > &commands->respace[RESIZE-1]) {
688 command_errf(commands, SEDERR_TMMES, commands->linebuf);
692 if(*p > compargs->nbra + '0' && *p <= '9') {
693 command_errf(commands, SEDERR_DOORNG, commands->linebuf);
699 if(*p == commands->sseof) {
705 command_errf(commands, SEDERR_EDMOSUB, commands->linebuf);
714 static int rline(sed_commands_t *commands, apr_file_t *fin,
715 char *lbuf, char *lbend)
720 apr_size_t bytes_read;
724 if(commands->eflag) {
725 if(commands->eflag > 0) {
726 commands->eflag = -1;
728 while((t = *q++) != '\0') {
736 if((t = *q++) == '\0') {
737 commands->saveq = NULL;
744 commands->saveq = NULL;
748 command_errf(commands, SEDERR_CLTL);
754 if((q = commands->saveq) == 0) return(-1);
756 while((t = *q++) != '\0') {
764 if((t = *q++) == '\0') {
765 commands->saveq = NULL;
772 commands->saveq = NULL;
776 command_errf(commands, SEDERR_CLTL);
784 /* XXX extremely inefficient 1 byte reads */
785 while (apr_file_read(fin, &t, &bytes_read) != APR_SUCCESS) {
788 command_errf(commands, SEDERR_CLTL);
798 if (apr_file_read(fin, &t, &bytes_read) != APR_SUCCESS) {
812 static char *address(sed_commands_t *commands, char *expbuf,
813 apr_status_t* status)
817 sed_comp_args compargs;
819 *status = APR_SUCCESS;
820 if(*commands->cp == '$') {
821 if (expbuf > &commands->respace[RESIZE-2]) {
822 command_errf(commands, SEDERR_TMMES, commands->linebuf);
823 *status = APR_EGENERAL;
831 if (*commands->cp == '/' || *commands->cp == '\\' ) {
832 if ( *commands->cp == '\\' )
834 commands->sseof = *commands->cp++;
835 return(comple(commands, &compargs, (char *) 0, expbuf, commands->reend,
842 while(*rcp >= '0' && *rcp <= '9')
843 lno = lno*10 + *rcp++ - '0';
845 if(rcp > commands->cp) {
846 if (expbuf > &commands->respace[RESIZE-3]) {
847 command_errf(commands, SEDERR_TMMES, commands->linebuf);
848 *status = APR_EGENERAL;
852 *expbuf++ = commands->nlno;
853 commands->tlno[commands->nlno++] = lno;
854 if(commands->nlno >= SED_NLINES) {
855 command_errf(commands, SEDERR_TMLNMES);
856 *status = APR_EGENERAL;
869 static char *text(sed_commands_t *commands, char *textbuf, char *tbend)
877 * Strip off indentation from text to be inserted.
879 while(*q == '\t' || *q == ' ') q++;
884 return(NULL); /* overflowed the buffer */
885 if((*p = *q++) == '\\')
893 * Strip off indentation from text to be inserted.
896 while(*q == '\t' || *q == ' ') q++;
907 static sed_label_t *search(sed_commands_t *commands)
912 rp = commands->labtab;
915 if (strcmp(rp->asc, ptr->asc) == 0)
926 static char *ycomp(sed_commands_t *commands, char *expbuf)
929 int cint; /* integer value of char c */
935 if(ep + 0377 > &commands->respace[RESIZE-1]) {
936 command_errf(commands, SEDERR_TMMES, commands->linebuf);
940 for(tsp = commands->cp; (c = *tsp) != commands->sseof; tsp++) {
943 if(c == '\0' || c == '\n') {
944 command_errf(commands, SEDERR_EDMOSTR, commands->linebuf);
951 while((c = *sp++) != commands->sseof) {
953 if(c == '\\' && *sp == 'n') {
958 if((ep[cint] = *tsp++) == '\\' && *tsp == 'n') {
962 if(ep[cint] == commands->sseof || ep[cint] == '\0') {
963 command_errf(commands, SEDERR_TSNTSS, commands->linebuf);
966 if(*tsp != commands->sseof) {
968 command_errf(commands, SEDERR_EDMOSTR, commands->linebuf);
971 command_errf(commands, SEDERR_TSNTSS, commands->linebuf);
975 commands->cp = ++tsp;
977 for(i = 0; i < 0400; i++)
987 static char *comple(sed_commands_t *commands, sed_comp_args *compargs,
988 char *x1, char *ep, char *x3, char x4)
992 p = sed_compile(commands, compargs, ep + 1, x3, x4);
995 *ep = compargs->circf;
1002 static sed_reptr_t *alloc_reptr(sed_commands_t *commands)
1006 var = apr_pcalloc(commands->pool, sizeof(sed_reptr_t));
1008 command_errf(commands, SEDERR_OOMMES);
1012 var->nrep = commands->nrep;
1016 if (commands->ptrspace == NULL)
1017 commands->ptrspace = var;
1019 commands->ptrend->next = var;
1021 commands->ptrend = var;
1022 commands->labtab->address = var;