2.11BSD/ingres/source/equel/display.c
#
# include "../unix.h"
extern jmp_buf Env;
/*
** DISPLAY.C -- display manipulation routines
**
** a display is a list of strings, the symbol
** space Symsp is impemented by means of displays.
**
** Defines:
** enter_display()
** addsym()
** free_display()
** symspfree()
** w_display()
** eat_display()
**
** Required By:
** Lexical analysis routines to add to the symbol space
** semantic productions to manipulate input
**
** Files:
** constants.h
** globals.h
**
** History:
** 6/1/78 -- (marc) written
**
*/
# include <stdio.h>
# include "constants.h"
# include "globals.h"
/* this avoids having to specify &Cv_display in the semantic
* routines, by making Cv_display a pointer to the pertinent
* display structure.
*/
extern struct display *Cv_display = &Displays [0];
/*
** ENTER_DISPLAY -- enter a new string into a display
**
** Parameters:
** disp -- display to be added to
** string -- string to add
**
** Returns:
** pointer to new disp_node structure.
**
** Side Effects:
** allocates a new disp_node structure.
** Expects a dynamic "string", i.e. one that it can
** dispose of as it wishes, so it is the users responsability
** to allocate space for this string.
** If the string passed is 0, the string
** "ERROR_TOKEN" is substituted, and a message is printed,
** so a caller may call enter_display with the return of an
** salloc() directly.
** If no space is available for the allocation of the
** new node, an error message is given, and a longjump(3)
** is performed (this should goto equel()[main.c])
**
** Called By:
** add_sym() -- to add a token to the Symsp
** the semantic productions -- for manipulating usages
** of C variables.
**
** Diagnostics:
** "symbol space overflow" -- total reset to after
** current top level file (not #included)
** "alloc error in display" -- someone called enter_display
** with a string == 0
**
** History:
** 6/1/78 -- (marc) written
**
*/
struct disp_node *enter_display(disp, string)
struct display *disp;
char *string;
{
register struct display *d;
register struct disp_node *node;
extern char *nalloc();
node = (struct disp_node *) nalloc(sizeof *node);
if (node == 0)
{
yysemerr("symbol space overflow", string);
reset(Env, 1);
}
d = disp;
if (!d->disp_first)
d->disp_first = d->disp_last = node;
else
{
d->disp_last->d_next = node;
d->disp_last = node;
}
node->d_next = 0;
if (!(node->d_elm = string))
{
printf("alloc error in display\n");
node->d_elm = "ERROR_TOKEN";
}
return (node);
}
/*
** ADDSYM -- add a token to the symbol space
**
** The node's .d_line field is set to the value of yyline,
** which, if this routine is called from a lexical routine
** taking lexemes that can't include newlines (and back them up),
** is the line the lexeme was read from. This fact is used
** be yyserror() [yyerror.c] to report accurate line numbers
** for errors.
**
** Parameters:
** s -- string to add
**
** Returns:
** pointer to node added
**
** Requires:
** enter_display() -- to enter the string
** Symsp -- display in which to enter it
**
** Called By:
** All lexical routines
**
** History:
** 6/1/78 -- (marc) written
**
*/
struct disp_node *addsym(s)
char *s;
{
register struct disp_node *d;
d = enter_display(&Symsp, s);
d->d_line = yyline;
return (d);
}
/*
** FREE_DISPLAY -- frees all elements of a display
**
** Parameters:
** disp -- the display to free
**
** Called By:
** The semantic produtions dealing with
** usage of C variables.
**
** History:
** 6/1/78 -- (marc) written
**
*/
free_display(disp)
struct display *disp;
{
register struct display *d;
register struct disp_node *f, *n;
d = disp;
for (f = d->disp_first; f; f = n)
{
n = f->d_next;
xfree(f->d_elm);
xfree(f);
}
d->disp_first = d->disp_last = 0;
}
/*
** SYSMSPFREE -- Frees symbol space
** Symspfree frees all the symbol table, EXCEPT
** for the last element in it, as this is the lookahead
** element. That is to say, the element which forced reduction
** to the non-terminal program, which called on symspfree()
**
** Requires:
** Symsp -- to free it
**
** Called By:
** argproc()
** semantic routines (nonterminal "program")
**
** History:
** 6/1/78 -- (marc) written
**
*/
symspfree()
{
register struct display *d;
register struct disp_node *f, *n;
d = &Symsp;
for (f = d->disp_first; f && f->d_next; f = n)
{
n = f->d_next;
xfree(f->d_elm);
xfree(f);
}
d->disp_first = d->disp_last;
}
/*
** W_DISPLAY -- write out the contents of a display
**
** Parameters:
** disp -- display to take write out
**
** Side Effects:
** Writes onto Out_file
** the contents of the display,
** each string is comsidered a separate
** word to be written out(so w_raw may
** break a line between words).
** Calls are made to w_op() and w_key() so as
** to have the minimum number of spaces in the text.
**
** Requires:
** w_op() -- to write out operator terminated
** strings
** w_key() -- to write out KEYCHAR terminated
** strings
**
** Called By:
** semantic productions dealing with usage of
** C variables.
**
** History:
** 6/1/78 -- (marc) written
**
*/
w_display(disp)
struct display *disp;
{
register struct disp_node *n;
for (n = disp->disp_first; n; n = n->d_next)
{
switch (Cmap [n->d_elm [length(n->d_elm) - 1]])
{
case OPATR :
case PUNCT :
w_op(n->d_elm);
break;
default :
w_key(n->d_elm);
break;
}
}
}
/*
** EAT_DISPLAY -- enter text from In_file into a display
** Enters all text gotten through getch() [getch.c]
** lying between one character delimiters, which may
** be nested, into a display or w_op()'s it.
** eat_display() assumes that when it is called a
** "left_ch" has just been seen. It will "eat" up to
** MAXSTRING characters.
** Newline is played with because :
** a) a newline may have been read by eat_display
** instead of yylex(), therefore if eat_display
** stops there, yylex() must know that a newline
** has just been seen and it must test for C_CODE.
** b) Newline may have to be set to 0 if an include()
** was done which sets it to 1, and no yylex() was
** done afterwards to reset it.
**
** NOTE : This playing with Newline is needed because
** yylex() and not getch() maintains Newline. If getch()
** maintained Newline then it would be automatically right.
**
** Parameters:
** disp -- display to add elements to if != 0 else
** characters are written out.
** left_ch -- left delimiter character
** right_ch -- right delimiter character
**
** Side Effects:
** advances input to after the close of the
** left_ch, right_ch pair.
** may back up 2 characters.
**
** Called By:
** semantic routines dealing with array subscription
**
** Diagnostics:
** "missing closing character" -- if end-of-file
** encountered in the stream.
** "display too long" -- if more than MAXSTRING
** chars between delimiters.
**
** History:
** 6/1/78 -- (marc) written
**
** Bugs:
** #include's encountered, are treated wrongly
** because the "#include ...c.h" is put out immediately,
** while the display is put out only later.
**
**
*/
eat_display(disp, left_ch, right_ch)
struct display *disp;
char left_ch;
char right_ch;
{
char buf [MAXSTRING + 1];
register char *cp;
register level;
register i;
char pk;
char r_c [2];
cp = buf;
level = i = 1;
*cp = left_ch;
do
{
i++;
if (i >= sizeof buf)
{
yysemerr("display too long", 0);
break;
}
if ((*++cp = getch()) == left_ch)
level++;
else if (*cp == right_ch)
level -= 1;
else if (*cp == EOF_TOK)
{
backup(*cp);
missing :
r_c [1] = '\0';
r_c [0] = right_ch;
yysemerr("missing closing character", r_c);
*cp = right_ch;
/* make next line be read as possible
* C_CODE by yylex() [yylex.c]
*/
Newline = 1;
break;
}
else if (*cp == '\n')
{
/* test that next line is valid equel line,
* and strip "##"
*/
if ((pk = getch()) != '#')
{
backup(pk);
goto missing;
}
if ((pk = getch()) != '#')
{
backup(pk);
backup('#');
goto missing;
}
}
} while (*cp != right_ch || level > 0);
if (level == 0)
Newline = 0;
*++cp = '\0';
if (disp)
enter_display(disp, salloc(buf));
else
w_op(buf);
}