|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T m
Length: 2942 (0xb7e) Types: TextFile Names: »maketext.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/General/Insult/maketext.c«
/* RCS Info: $Revision: $ on $Date: $ * $Source: $ * Copyright (c) 1985 Wayne A. Christopher * Permission is granted to do anything with this code except sell it * or remove this message. */ #include <stdio.h> #include "kafgraf.h" #include "defs.h" struct kkelt kkstack[STACKSIZE]; /* The stack. */ struct kkelt *kksp; /* The stack pointer. */ extern struct kknode *start; extern struct kknode *nodelist; /* This routine is the one that generates a string in the grammer, * beginning with the non-terminal s. Returns -1 if s is not the * name of a non-terminal. */ maketext(s) char *s; { struct kknode *stnode, *kknn; int kkcv; /* First find the start node. */ /* dumpnlist(); Diagnostic. */ for (stnode = nodelist; stnode != NULL; stnode = stnode->kk_link) if (!strcmp(stnode->kk_nodename, s)) break; if (stnode == NULL) { /* Error condition. */ return (-1); } /* Now to generate the text. The generator works like this: first * select one of the rules for the given non-terminal to follow. * If the non-terminal is actually a computed terminal, compute * the value and output it. Otherwise, then push a pointer to the * it onto the stack along with a pointer to the arc that we are * currently following and follow it. If it is a terminal arc, * output the terminal and return, otherwise repeat for the * new nt. When returning, pop the stack and go on to the next * arc, or return if there is none. */ kksp = &kkstack[0]; kksp->ke_node = stnode; kksp->ke_arc = stnode->kk_arc; nextarc: if (kksp->ke_arc == NULL) { /* We have reached the end of the * current rule. */ kksp--; if (kksp < &kkstack[0]) { /* Done? */ return (0); } /* There are more rules to go. */ kksp->ke_arc = kksp->ke_arc->kc_narc; goto nextarc; } /* There are yet arcs to be followed in the current rule. */ if (kksp->ke_arc->kc_to) { /* The arc is to a non-term. Follow it. */ kknn = kksp->ke_arc->kc_to; if (kknn->kk_type == KTCOMP) { /* Compute the value of the terminal. Note that we * don't bother declaring these functions to be * char *. */ kkcv = (int) (*kknn->kk_func) (); if (kkcv == NULL) { /* Doesn't like this rule. */ kksp->ke_arc = kksp->ke_arc->kc_narc; goto nextarc; } else { /* Cool. */ kkoutput((char *) kkcv); kksp->ke_arc = kksp->ke_arc->kc_narc; goto nextarc; } } /* It must be a real non-terminal then. Now decide * which rule to use. */ while (kknn) { if ((kknn->kk_func == NULL) || (*kknn->kk_func) () ) break; kknn = kknn->kk_next; } if (kknn == NULL) { fprintf(stderr, "Error: no rules accepted for %s\n", kksp->ke_node->kk_nodename); exit(1); } kksp++; kksp->ke_node = kknn; kksp->ke_arc = kknn->kk_arc; goto nextarc; } /* It is a terminal. */ kkoutput(kksp->ke_arc->kc_toname); kksp->ke_arc = kksp->ke_arc->kc_narc; goto nextarc; }