ING_DB
This commit is contained in:
parent
eefa54f77f
commit
541d815424
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
Loading…
Reference in New Issue