This commit is contained in:
Oliver Lehmann 1990-01-25 05:41:31 +00:00
parent eefa54f77f
commit 541d815424
3 changed files with 709 additions and 0 deletions

View File

@ -0,0 +1,306 @@
# include <stdio.h>
# include "gen.h"
# include "../h/bs.h"
# include "constants.h"
# include "globals.h"
static struct display Symsp; /* storage for symbols read by */
/* yylex() */
static struct display Displays[1]; /* Cv_display is set to point at */
/* this, so that Cv_display may be */
/* passed a parameter instead of */
/* &Cv_display */
struct display *Cv_display = &Displays[0];
/*
** 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()
**
**
**
** this avoids having to specify &Cv_display in the semantic
** routines, by making Cv_display a pointer to the pertinent
** display structure.
*/
/*
** 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 eql()[main.c])
*/
struct disp_node *enter_display(disp, string)
register struct display *disp;
register char *string;
{
register struct disp_node *node;
extern char *nalloc();
node = (struct disp_node *) nalloc(sizeof *node);
if (!node)
{
yysemerr("symbol space overflow", string);
reset();
}
if (!disp->disp_first)
disp->disp_first = disp->disp_last = node;
else
{
disp->disp_last->d_next = node;
disp->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
*/
struct disp_node *addsym(s)
register 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
*/
free_display(disp)
register struct display *disp;
{
register struct disp_node *f;
register struct disp_node *n;
for (f = disp->disp_first; f; f = n)
{
n = f->d_next;
xfree(f->d_elm);
xfree(f);
}
disp->disp_first = disp->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()
*/
symspfree()
{
register struct display *d;
register struct disp_node *f;
register struct disp_node *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_raw() and w_key() so as
** to have the minimum number of spaces in the text.
*/
w_display(disp)
register struct display *disp;
{
register struct disp_node *n;
register int i;
for (n = disp->disp_first; n; n = n->d_next)
{
i = AAlength(n->d_elm);
i = n->d_elm[i - 1];
switch (CMAP(i))
{
case OPATR :
case PUNCT :
w_raw(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_raw()'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.
**
** 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;
{
register char *cp;
register int level;
register int i;
register int pk;
char r_c[2];
char buf[MAXSTRING + 1];
extern char *salloc();
cp = buf;
level = i = 1;
*cp = left_ch;
do
{
i++;
if (i >= sizeof buf)
{
yysemerr("display too long", (char *) 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 EQL 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)
Newline = 0;
*++cp = '\0';
if (disp)
enter_display(disp, salloc(buf));
else
w_raw(buf);
}

View File

@ -0,0 +1,252 @@
# include <stdio.h>
# include "gen.h"
# include "constants.h"
# include "globals.h"
struct inc_file *Inc_file; /* file stack pushed by #includes */
/*
** INLUDE.C -- Routine to process "#include" lines
**
** Defines:
** tst_include()
** include()
** restoref()
**
**
**
** TST_INCLUDE -- Test and process a "#include" line
**
** Checks that a line is of the form '# include "<filename.q.h>"',
** and calls include to change i/o files if so.
**
** Returns:
** 1 -- if change of file was done
** 0 -- otherwise
*/
tst_include()
{
register char *lp;
register char *tp;
register char *chp;
char temp[MAXSTRING + 1];
/* copy line read into temp ( because temp is same
* size as Linebuf, no overflow check is needed
*/
for (tp = temp, lp = Line_buf; (*tp++ = *lp++) != '\n'; )
continue;
/* skip white space between "#" and "include" */
for (tp = &temp[1]; *tp == ' ' || *tp == '\t'; tp++)
continue;
if (AAscompare("include", 7, tp, 7))
return (0);
/* skip "include", the white space till '"' */
for (tp = &tp[7]; *tp == ' ' || *tp == '\t'; tp++)
continue;
if (*tp++ != '"')
return (0);
/* {tp points to X in a line "#<white>include<white>"X..." }
* make "lp" point at right end '"' (filename must not have
* escaped '"' in it
*/
for (lp = tp; *lp != '"' && *lp != '\n'; lp++)
continue;
if (*lp != '"')
return (0);
/* make sure filename is long enough to have the EQL "include"
* suffix ".q.h"
*/
if (lp - tp < 4)
return (0);
if (AAscompare(".q.h", 4, &lp[-4], 4))
return (0); /* other include (non-EQL) */
/* "chp" points at 'q' in '.q.h' which will be changed to 'c' */
chp = &lp[-3];
/* check that rest of the line is white space */
for (lp++; *lp == ' ' || *lp == '\t'; lp++)
continue;
if (*lp != '\n')
{
*lp = '\0';
yysemerr("garbage after valid \"#include\"", temp);
return (0);
}
*++lp = '\0';
return (include(temp, tp, chp, &chp[3]));
}
/*
** INCLUDE -- Change i/o files for a file inclusion
** Saves status of current i/o files, puts out
** '#include"___.c.h"', and opens appropriate files.
** Makes both files legal C files, closing quotes,
** and reopeneing them in the new file, if necessary.
** Reuses Out_buf.
**
** Parameters:
** buf -- "#include..." line
** start -- start of filename
** chp -- *chp is 'q' in ".q.h" of filename
** end -- ptr to last '"' after filename
**
** Returns:
** 1 -- if i/o files changed
** 0 -- otherwise
*/
include(buf, start, chp, end)
char *buf;
char *start;
char *chp;
char *end;
{
register struct inc_file *i_f;
register int in_q_flag;
# ifdef SETBUF
register char *ibuf;
# endif
extern char *nalloc();
extern char *salloc();
in_q_flag = In_quote;
if (in_q_flag)
{
end_quote();
equate_lines();
}
if (!(i_f = (struct inc_file *) nalloc(sizeof *i_f)))
{
err1 :
*++end = '\0'; /* overwrite before new-line at end */
yysemerr("alloc error in #include processing", buf);
if (in_q_flag)
begin_quote();
*end = '\n';
return (0);
}
# ifdef SETBUF
if (!(ibuf = nalloc(BUFSIZ)))
goto err2;
# endif
i_f->inc_yyline = yyline + 1; /* next line that will be read is
* yyline + 1 because getch does not
* see the '\n' at the end of the
* "#include" line
*/
i_f->inc_lineout = Lineout + 1; /* because the write of the "#include
* "... .c.h" file is done after the
* fixation of the value of Lineout.
*/
i_f->inc_fid = Input_file_name;
i_f->inc_outfile = Out_file;
i_f->inc_infile = In_file;
# ifdef SETBUF
i_f->inc_ibuf = Ibuf;
# endif
i_f->inc_next = 0;
*end = '\0';
if (!(Input_file_name = salloc(start)))
{
# ifdef SETBUF
xfree(ibuf);
# endif
err2 :
xfree(i_f);
goto err1;
}
if (!(In_file = fopen(Input_file_name, "r")))
{
printf("can't read included file \"%s\"\n", Input_file_name);
err3 :
xfree(Input_file_name);
Input_file_name = i_f->inc_fid;
In_file = i_f->inc_infile;
# ifdef SETBUF
xfree(ibuf);
# endif
xfree(i_f);
return (0);
}
# ifdef SETBUF
setbuf(In_file, ibuf);
# endif
*end = '"';
*chp = 'c';
/* write out "#include..c.h" line (make sure it's at beginning
* of line.
*/
equate_lines();
if (Charcnt)
w_raw("\n");
w_raw(buf);
fflush(Out_file);
*end = '\0';
if (!(Out_file = fopen(start, "w")))
{
printf("can't write file \"%s\"\n", start);
fclose(In_file);
Out_file = i_f->inc_outfile;
goto err3;
}
# ifdef SETBUF
setbuf(Out_file, Out_buf);
Ibuf = ibuf;
# endif
/* go to it !!! */
Lineout = yyline = Newline = 1;
Pre_proc_flag = 0;
Line_pos = (char *) 0;
if (in_q_flag)
begin_quote();
Inc_file = i_f;
return (1);
}
/*
** RESTOREF -- Restore previous file environment
** Closes current files, and restores global variable
** values for old files.
**
** Returns:
** 0 -- if no old files (top level, no "#include"s)
** 1 -- otherwise
*/
restoref()
{
register struct inc_file *i_f;
if (Inc_file)
{
fclose(Out_file);
fclose(In_file);
# ifdef SETBUF
xfree(Ibuf);
# endif
xfree(Input_file_name);
/* restore previous environment */
i_f = Inc_file;
yyline = i_f->inc_yyline;
Lineout = i_f->inc_lineout;
# ifdef SETBUF
Ibuf = i_f->inc_ibuf;
# endif
Input_file_name = i_f->inc_fid;
Out_file = i_f->inc_outfile;
In_file = i_f->inc_infile;
Line_pos = (char *) 0;
Inc_file = i_f->inc_next;
xfree(i_f);
return (1);
}
return (0);
}

View File

@ -0,0 +1,151 @@
# include <stdio.h>
# include "gen.h"
# include "constants.h"
# include "globals.h"
static struct ret_list Ret_list; /* list of variables in a "ctlelm" */
/*
** RETRIEVE.C -- ret_list struct handlers
**
** The Ret_list is a structure where references to C variables,
** and their types, used in a target list of a "tupret" are kept
** for outputting in the while loop generated.
**
** Defines:
** enter_ret()
** add_ret()
** w_ret()
** free_ret()
**
**
**
** ENTER_RET -- enter a variable in a ret_list
** Concatenatest the strings in disp the calls add_ret
** to add the new string to Ret_list.
**
** Parameters:
** disp -- display containing the reference to the variable
** type -- type of the variable
*/
enter_ret(disp, type)
struct display *disp;
int type;
{
register char *srce;
register char *dest;
register struct disp_node *d;
register int i;
char buf[MAXSTRING + 2];
extern char *salloc();
i = 0;
dest = buf;
for (d = disp->disp_first; d; d = d->d_next)
{
for (srce = d->d_elm; *srce; )
{
if (i < MAXSTRING)
{
i += 1;
*++dest = *srce++;
}
else
break;
}
if (i >= MAXSTRING)
{
yysemerr("reference to a variable too long, ']' probably missing from array subscription", (char *) 0);
break;
}
}
*++dest = '\0';
add_ret(salloc(&buf[1]), type);
}
/*
** ADD_RET -- add a string (reference to a variable) to the Ret_list
**
** Parameters:
** s -- string to add
** type -- type of variable being added
*/
add_ret(s, type)
char *s;
int type;
{
register struct ret_list *list;
register struct ret_var *node;
extern char *nalloc();
if (!s)
{
s = "ERROR_TOKEN";
yysemerr("alloc error", s);
}
list = &Ret_list;
node = (struct ret_var *) nalloc(sizeof *node);
if (!node)
{
yysemerr("alloc error", s);
xfree(s);
return;
}
node->r_elm = s;
node->r_next = 0;
node->r_type = type;
if (!list->ret_first)
list->ret_first = list->ret_last = node;
else
{
list->ret_last->r_next = node;
list->ret_last = node;
}
}
/*
** W_RET -- Generates the IIn_get() calls for the Ret_list
**
** Any variable whose type is not string gets an '&'
** (adress of) operand prepended.
*/
w_ret()
{
register struct ret_var *node;
char type[3];
for (node = Ret_list.ret_first; node; node = node->r_next)
{
w_raw("IIn_ret(");
if (node->r_type != opSTRING)
w_raw("&");
w_raw(node->r_elm);
w_raw(", ");
AA_itoa(node->r_type, type);
w_raw(type);
w_raw(");");
}
}
/*
** FRE_RET -- Free up the storage used by the Ret_list
*/
free_ret()
{
register struct ret_list *list;
register struct ret_var *n;
register struct ret_var *f;
list = &Ret_list;
for (f = list->ret_first; f; f = n)
{
n = f->r_next;
xfree(f->r_elm);
xfree(f);
}
list->ret_first = list->ret_last = 0;
}