$NetBSD: patch-af,v 1.1.1.1 2001/05/30 11:45:41 agc Exp $ --- translate.c.orig Mon May 28 11:39:14 2001 +++ translate.c Mon May 28 12:18:03 2001 @@ -11,6 +11,10 @@ #include #include "texi2roff.h" +#ifndef TDEBUG +#define TDEBUG 0 +#endif + extern int transparent; /* -t flag: dont discard things */ int displaylevel = 0; /* nesting level of 'display' text */ int inmacroarg = NO; /* protect roff macro args flag */ @@ -78,6 +82,9 @@ while (fgets(input, MAXLINELEN, in) != NULL) { ++linecount; + if (linecount == 1 && strncmp(input, "\\input texinfo", 14) == 0) { + continue; + } inp = input; *output = 0; if (*inp == '.') /* protect leading '.' in input */ @@ -118,13 +125,99 @@ } /* + * handle variables + */ + +static struct vartag { + char var_name[MAXLINELEN]; + char var_value[MAXLINELEN + 20]; /* room for no value for ... */ + int var_is_set; + struct vartag *var_next; +} *first_var = NULL; + +/* + * lookup a variable and return a pointer to it. + * creates the variable if needed. + */ + +static struct vartag * +lookup_var(name) +char *name; +{ + struct vartag *v; + + for (v = first_var; v; v = v->var_next) { + if (strcmp(v->var_name, name) == 0) { + return(v); + } + } + + v = (struct vartag *) malloc(sizeof(struct vartag)); + if (!v) { + errormsg("unable to save variable: ", name); + } else { + strncpy(v->var_name, name, MAXLINELEN); + v->var_name[MAXLINELEN-1] = '\0'; + v->var_value[0] = '\0'; + v->var_is_set = NO; + v->var_next = first_var; + first_var = v; + } + return(v); +} + +static void +set_var(name, is_set, value) +char *name, *value; +int is_set; +{ + struct vartag *v; + + v = lookup_var(name); + if (v) { + v->var_is_set = is_set; + if (is_set) { + strncpy(v->var_value, value, MAXLINELEN-1); + v->var_value[MAXLINELEN-1] = '\0'; + } else { + v->var_value[0] = '\0'; + } + } +} + +static int +var_is_set(name) +char *name; +{ + struct vartag *v; + v = lookup_var(name); + return(v != (struct vartag *)NULL && v->var_is_set); +} + +static char * +get_var(name) +char *name; +{ + struct vartag *v; + v = lookup_var(name); + if (!v) + return(""); + if (!v->var_is_set) + sprintf(v->var_value, "{No value for \"%s\"}", v->var_name); + return(v->var_value); +} + +/* * PUSH - macro to push pointer to table entry onto command stack * and current font onto font stack */ -#define MAXDEPTH 20 +#define MAXDEPTH 100 #define PUSH(tptr) \ + if (tptr->texend[0] == '\0') { \ + errormsg("error - table has empty end for cmd ", tptr->texstart);\ + } \ if (++stackptr == MAXDEPTH) { \ errormsg("stack overflow - commands nested too deeply", ""); \ return NULL; \ @@ -160,6 +253,13 @@ FILE *fp; /* for @include files */ extern int process(); /* for @include files */ +#if TDEBUG + fprintf(stderr, + "interp, ln %d token '%s', stackptr %d fontptr %d discard %d level %d inmacarg %d\n", + linecount, token, stackptr, fontptr, + discarding, discardlevel, inmacroarg); +#endif + if (init == NO) { (void) strcpy(fontstack[0], defaultfont); (void) strcpy(curfont, defaultfont); @@ -169,12 +269,17 @@ s = inp; if (stackptr > 0 && STREQ(token, stack[stackptr]->texend)) { /* have fetched closing token of current Texinfo command */ +#if TDEBUG + fprintf(stderr, "interp, found end, stackptr %d\n", stackptr); +#endif if (STREQ(token, "@end")) {/* WARNING! only works from translate() */ s = gettoken(eatwhitespace(s),tempstr); - if (! STREQ(&(stack[stackptr]->texstart[1]), tempstr) - && !discarding) { + if (! STREQ(&(stack[stackptr]->texstart[1]), tempstr) ) { errormsg("unexpected @end found for Texinfo cmd @", tempstr); - return s; + errormsg("expected @end for Texinfo cmd ", stack[stackptr]->texstart); + if (!discarding) { + return s; + } } } if (!discarding) @@ -209,6 +314,9 @@ return ""; /* flush rest of line if any */ } } else if (*token != '@') { /* ordinary piece of text */ +#if TDEBUG + fprintf(stderr, "interp, normal text\n"); +#endif if (!discarding) (void) strcat(outstring, token); if (*token == '\n') { @@ -220,10 +328,23 @@ if (!discarding) errormsg("unrecognized Texinfo command ", token); } else { +#if TDEBUG + fprintf(stderr, "interp, command, type %d\n", tptr->type); +#endif switch (tptr->type) { case ESCAPED: - if (!discarding) - (void) strcat(outstring, tptr->trfstart); + if (tptr->texend[0] != '\0') { + errormsg("error - table has non-empty end for cmd ", + tptr->texstart); + } + if (!discarding) { + if (tptr->trfstart[0] != '\0') { + (void) strcat(outstring, tptr->trfstart); + } + if (tptr->trfend[0] != '\0') { + (void) strcat(outstring, tptr->trfend); + } + } break; case DISPLAY: ++displaylevel; @@ -249,6 +370,16 @@ if (!discarding && !transparent) { discarding = YES; discardlevel = stackptr; + if (tptr->texend[0] == '\n') { + while (*s != '\0' && *s != '\n') + s++; + } + } + break; + case DISCARDLINE: + if (!transparent) { + while (*s != '\0' && *s != '\n') + s++; } break; case ITEMIZING: @@ -277,8 +408,7 @@ break; case END: s = gettoken(eatwhitespace(s),tempstr); - if (!discarding) - errormsg("unexpected @end found for Texinfo cmd @", tempstr); + errormsg("unexpected @end found for Texinfo cmd @", tempstr); break; case FOOTNOTE: PUSH(tptr); @@ -297,11 +427,56 @@ for (cp = tempstr; strchr(" \t\n",*s) == NULL; *cp++ = *s++) ; *cp = '\0'; - if (!discarding && ( fp = fopen(tempstr, "r")) == NULL) - errormsg("can't open included file ", tempstr); - else { - (void) process(fp, tempstr); - (void) fclose(fp); + if (!discarding) { + if ( (fp = fopen(tempstr, "r")) == NULL) + errormsg("can't open included file ", tempstr); + else { + (void) process(fp, tempstr); + (void) fclose(fp); + } + } + break; + case IFSET: + case IFCLEAR: + PUSH(tptr); + s = eatwhitespace(s); + for (cp = tempstr; strchr(" \t\n",*s) == NULL; *cp++ = *s++) + ; + *cp = '\0'; + if (!discarding) { + discarding = var_is_set(tempstr); + if (tptr->type == IFSET) discarding = !discarding; + if (discarding) discardlevel = stackptr; + } + break; + case SET: + case CLEAR: + s = eatwhitespace(s); + for (cp = itemtag; strchr(" \t\n",*s) == NULL; *cp++ = *s++) + ; + *cp = '\0'; + if (tptr->type == CLEAR) { + if (!discarding) { + set_var(itemtag, NO, ""); + } + } else { + s = eatwhitespace(s); + for (cp = s; *s != '\0' && *s != '\n'; s++) + ; + *s = '\0'; + if (!discarding) { + set_var(itemtag, YES, cp); + } + } + break; + case VALUE: + cp = tempstr; + while (*s != '}' && *s != '\n' && *s != '\0') + *cp++ = *s++; + *cp = 0; + if (*s == '}') s++; + if (!discarding) { + (void) strcat(outstring, get_var(tempstr)); } break; default: @@ -406,6 +581,13 @@ ++s; break; case '@': + /* handle 3 char @ tokens @ + "'`=^~ + letter */ + if (s[1] != '\0' && + ((s[2] >= 'a' && s[2] <= 'z') || (s[2] >= 'A' && s[2] <= 'Z')) && + strchr("\"'`=^~", s[1]) != NULL) { + s += 2; + break; + } s = strpbrk_like(q + 1, endchars ); /* handles 2 char @ tokens: @{ @} @@ @: @. @* */ if ( strchr("{}@:.*", *s) == NULL