$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 <stdio.h>
 #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
