Merge pull request #172 from ccodere/carl-ansi-part1

Carl ansi part1
This commit is contained in:
David Given 2019-02-20 19:36:49 +01:00 committed by GitHub
commit d41ba12679
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
221 changed files with 9439 additions and 8897 deletions

View file

@ -4,6 +4,7 @@
*/ */
#include "bem.h" #include "bem.h"
#include "system.h"
#ifndef NORSCID #ifndef NORSCID
static char rcs_id[] = "$Id$" ; static char rcs_id[] = "$Id$" ;
@ -59,7 +60,7 @@ List *datalist=0;
datastmt() datastmt()
{ {
List *l,*l1; List *l,*l1;
extern long sys_filesize();
/* NOSTRICT */ l= (List *) salloc(sizeof(List)); /* NOSTRICT */ l= (List *) salloc(sizeof(List));
l->linenr= currline->linenr; l->linenr= currline->linenr;

View file

@ -1,138 +1,138 @@
!File: lint.h !File: lint.h
/*#define LINT 1 /* if defined, 'lint' is produced */ /*#define LINT 1 *//* if defined, 'lint' is produced */
!File: pathlength.h !File: pathlength.h
#define PATHLENGTH 1024 /* max. length of path to file */ #define PATHLENGTH 1024 /* max. length of path to file */
!File: errout.h !File: errout.h
#define ERROUT STDERR /* file pointer for writing messages */ #define ERROUT STDERR /* file pointer for writing messages */
#define ERR_SHADOW 5 /* a syntax error overshadows error messages #define ERR_SHADOW 5 /* a syntax error overshadows error messages
until ERR_SHADOW symbols have been until ERR_SHADOW symbols have been
accepted without syntax error */ accepted without syntax error */
!File: idfsize.h !File: idfsize.h
#define IDFSIZE 64 /* maximum significant length of an identifier */ #define IDFSIZE 64 /* maximum significant length of an identifier */
!File: numsize.h !File: numsize.h
#define NUMSIZE 256 /* maximum length of a numeric constant */ #define NUMSIZE 256 /* maximum length of a numeric constant */
!File: nparams.h !File: nparams.h
#define NPARAMS 32 /* maximum number of parameters */ #define NPARAMS 32 /* maximum number of parameters */
#define STDC_NPARAMS 31 /* ANSI limit on number of parameters */ #define STDC_NPARAMS 31 /* ANSI limit on number of parameters */
!File: ifdepth.h !File: ifdepth.h
#define IFDEPTH 256 /* maximum number of nested if-constructions */ #define IFDEPTH 256 /* maximum number of nested if-constructions */
!File: density.h !File: density.h
#define DENSITY 3 /* see switch.[ch] for an explanation */ #define DENSITY 3 /* see switch.[ch] for an explanation */
!File: macbuf.h !File: macbuf.h
#define LAPBUF 128 /* initial size of macro replacement buffer */ #define LAPBUF 128 /* initial size of macro replacement buffer */
#define ARGBUF 128 /* initial size of macro parameter buffer(s) */ #define ARGBUF 128 /* initial size of macro parameter buffer(s) */
!File: strsize.h !File: strsize.h
#define ISTRSIZE 32 /* minimum number of bytes allocated for #define ISTRSIZE 32 /* minimum number of bytes allocated for
storing a string */ storing a string */
#define RSTRSIZE 16 /* step size in enlarging the memory for #define RSTRSIZE 16 /* step size in enlarging the memory for
the storage of a string */ the storage of a string */
!File: trgt_sizes.h !File: trgt_sizes.h
#define MAXSIZE 8 /* the maximum of the SZ_* constants */ #define MAXSIZE 8 /* the maximum of the SZ_* constants */
/* target machine sizes */ /* target machine sizes */
#define SZ_CHAR 1 #define SZ_CHAR 1
#define SZ_SHORT 2 #define SZ_SHORT 2
#define SZ_WORD 4 #define SZ_WORD 4
#define SZ_INT 4 #define SZ_INT 4
#define SZ_LONG 4 #define SZ_LONG 4
#define SZ_FLOAT 4 #define SZ_FLOAT 4
#define SZ_DOUBLE 8 #define SZ_DOUBLE 8
#define SZ_LNGDBL 8 /* for now */ #define SZ_LNGDBL 8 /* for now */
#define SZ_POINTER 4 #define SZ_POINTER 4
/* target machine alignment requirements */ /* target machine alignment requirements */
#define AL_CHAR 1 #define AL_CHAR 1
#define AL_SHORT SZ_SHORT #define AL_SHORT SZ_SHORT
#define AL_WORD SZ_WORD #define AL_WORD SZ_WORD
#define AL_INT SZ_WORD #define AL_INT SZ_WORD
#define AL_LONG SZ_WORD #define AL_LONG SZ_WORD
#define AL_FLOAT SZ_WORD #define AL_FLOAT SZ_WORD
#define AL_DOUBLE SZ_WORD #define AL_DOUBLE SZ_WORD
#define AL_LNGDBL SZ_WORD #define AL_LNGDBL SZ_WORD
#define AL_POINTER SZ_WORD #define AL_POINTER SZ_WORD
#define AL_STRUCT 1 #define AL_STRUCT 1
#define AL_UNION 1 #define AL_UNION 1
!File: botch_free.h !File: botch_free.h
/*#define BOTCH_FREE 1 /* when defined, botch freed memory, as a check */ /*#define BOTCH_FREE 1* *//* when defined, botch freed memory, as a check */
!File: dataflow.h !File: dataflow.h
#define DATAFLOW 1 /* produce some compile-time xref */ #define DATAFLOW 1 /* produce some compile-time xref */
!File: debug.h !File: debug.h
/*#define DEBUG 1 /* perform various self-tests */ /*#define DEBUG 1 *//* perform various self-tests */
#define NDEBUG 1 /* disable assertions */ #define NDEBUG 1 /* disable assertions */
!File: use_tmp.h !File: use_tmp.h
#define PREPEND_SCOPES 1 /* collect exa, exp, ina and inp commands #define PREPEND_SCOPES 1 /* collect exa, exp, ina and inp commands
and if USE_TMP is defined let them and if USE_TMP is defined let them
precede the rest of the generated precede the rest of the generated
compact code */ compact code */
#define USE_TMP 1 /* use C_insertpart, C_endpart mechanism #define USE_TMP 1 /* use C_insertpart, C_endpart mechanism
to generate EM-code in the order needed to generate EM-code in the order needed
for the code-generators. If not defined, for the code-generators. If not defined,
the old-style peephole optimizer is the old-style peephole optimizer is
needed. */ needed. */
!File: parbufsize.h !File: parbufsize.h
#define PARBUFSIZE 1024 #define PARBUFSIZE 1024
!File: textsize.h !File: textsize.h
#define ITEXTSIZE 32 /* 1st piece of memory for repl. text */ #define ITEXTSIZE 32 /* 1st piece of memory for repl. text */
!File: inputtype.h !File: inputtype.h
#define INP_READ_IN_ONE 1 /* read input file in one */ #define INP_READ_IN_ONE 1 /* read input file in one */
!File: nobitfield.h !File: nobitfield.h
/*#define NOBITFIELD 1 /* if NOT defined, implement bitfields */ /*#define NOBITFIELD 1 *//* if NOT defined, implement bitfields */
!File: spec_arith.h !File: spec_arith.h
/* describes internal compiler arithmetics */ /* describes internal compiler arithmetics */
#undef SPECIAL_ARITHMETICS /* something different from native long */ #undef SPECIAL_ARITHMETICS /* something different from native long */
!File: static.h !File: static.h
#define GSTATIC /* for large global "static" arrays */ #define GSTATIC /* for large global "static" arrays */
!File: nocross.h !File: nocross.h
/*#define NOCROSS 1 /* if NOT defined, cross compiler */ /*#define NOCROSS 1 *//* if NOT defined, cross compiler */
!File: regcount.h !File: regcount.h
/*#define REGCOUNT 1 /* count occurrences for register messages */ /*#define REGCOUNT 1 *//* count occurrences for register messages */
!File: dbsymtab.h !File: dbsymtab.h
#define DBSYMTAB 1 /* ability to produce symbol table for debugger */ #define DBSYMTAB 1 /* ability to produce symbol table for debugger */

View file

@ -17,6 +17,8 @@
#include "Lpars.h" #include "Lpars.h"
#include "class.h" #include "class.h"
#include "sizes.h" #include "sizes.h"
#include "error.h"
#include "domacro.h"
#include "specials.h" /* registration of special identifiers */ #include "specials.h" /* registration of special identifiers */
/* Data about the token yielded */ /* Data about the token yielded */
@ -41,7 +43,16 @@ extern arith full_mask[];
extern int lint_skip_comment; extern int lint_skip_comment;
#endif #endif
int LLlex()
/* Internal function declarations */
static arith char_constant(char*);
static char* string_token(char *, int , int *);
static int quoted(register int);
static int hex_val(register int);
static void strflt2tok(char [], struct token *);
static void strint2tok(char [], struct token *);
int LLlex(void)
{ {
/* LLlex() plays the role of Lexical Analyzer for the C parser. /* LLlex() plays the role of Lexical Analyzer for the C parser.
The look-ahead and putting aside of tokens are taken into The look-ahead and putting aside of tokens are taken into
@ -72,10 +83,8 @@ int LLlex()
return DOT; return DOT;
} }
char* string_token();
arith char_constant();
int GetToken(ptok) register struct token* ptok; int GetToken(register struct token* ptok)
{ {
/* GetToken() is the actual token recognizer. It calls the /* GetToken() is the actual token recognizer. It calls the
control line interpreter if it encounters a "\n{w}*#" control line interpreter if it encounters a "\n{w}*#"
@ -379,7 +388,7 @@ go_on: /* rescan, the following character has been read */
/*NOTREACHED*/ /*NOTREACHED*/
} }
arith char_constant(nm) char* nm; static arith char_constant(char* nm)
{ {
register arith val = 0; register arith val = 0;
register int ch; register int ch;
@ -413,8 +422,7 @@ arith char_constant(nm) char* nm;
return val; return val;
} }
char* string_token(nm, stop_char, plen) char* nm; static char* string_token(char *nm, int stop_char, int *plen)
int* plen;
{ {
register int ch; register int ch;
register int str_size; register int str_size;
@ -447,7 +455,7 @@ int* plen;
return str; return str;
} }
int quoted(ch) register int ch; static int quoted(register int ch)
{ {
/* quoted() replaces an escaped character sequence by the /* quoted() replaces an escaped character sequence by the
character meant. character meant.
@ -510,12 +518,12 @@ int quoted(ch) register int ch;
return ch & 0377; return ch & 0377;
} }
int hex_val(ch) register int ch; static int hex_val(register int ch)
{ {
return is_dig(ch) ? ch - '0' : is_hex(ch) ? (ch - 'a' + 10) & 017 : -1; return is_dig(ch) ? ch - '0' : is_hex(ch) ? (ch - 'a' + 10) & 017 : -1;
} }
int GetChar() int GetChar(void)
{ {
/* The routines GetChar and trigraph parses the trigraph /* The routines GetChar and trigraph parses the trigraph
sequences and removes occurences of \\\n. sequences and removes occurences of \\\n.
@ -529,8 +537,7 @@ int GetChar()
/* strflt2tok only checks the syntax of the floating-point number and /* strflt2tok only checks the syntax of the floating-point number and
* selects the right type for the number. * selects the right type for the number.
*/ */
strflt2tok(fltbuf, ptok) char fltbuf[]; static void strflt2tok(char fltbuf[], struct token* ptok)
struct token* ptok;
{ {
register char* cp = fltbuf; register char* cp = fltbuf;
int malformed = 0; int malformed = 0;
@ -584,8 +591,7 @@ struct token* ptok;
} }
} }
strint2tok(intbuf, ptok) char intbuf[]; static void strint2tok(char intbuf[], struct token* ptok)
struct token* ptok;
{ {
register char* cp = intbuf; register char* cp = intbuf;
int base = 10; int base = 10;

View file

@ -9,6 +9,8 @@
called a "symbol", but it may have other information associated called a "symbol", but it may have other information associated
to it. to it.
*/ */
#ifndef LLLEX_H_
#define LLLEX_H_
#include "file_info.h" #include "file_info.h"
@ -56,3 +58,9 @@ extern int err_occurred; /* "error.c" */
#define ASIDE aside.tk_symb #define ASIDE aside.tk_symb
#define EOF (-1) #define EOF (-1)
int GetChar(void);
int LLlex(void);
int GetToken(register struct token* ptok);
#endif /* LLLEX_H_ */

View file

@ -10,21 +10,28 @@
#include "arith.h" #include "arith.h"
#include "LLlex.h" #include "LLlex.h"
#include "Lpars.h" #include "Lpars.h"
#include "error.h"
extern char *symbol2str(); extern char *symbol2str();
LLmessage(tk) { static void insert_token(int );
void LLmessage(int tk)
{
err_occurred = 1; err_occurred = 1;
if (tk < 0) { if (tk < 0)
{
error("end of file expected"); error("end of file expected");
} }
else if (tk) { else if (tk)
{
#ifndef LLNONCORR #ifndef LLNONCORR
error("%s missing before %s", symbol2str(tk), symbol2str(DOT)); error("%s missing before %s", symbol2str(tk), symbol2str(DOT));
#endif #endif
insert_token(tk); insert_token(tk);
} }
else { else
{
#ifndef LLNONCORR #ifndef LLNONCORR
error("%s deleted", symbol2str(DOT)); error("%s deleted", symbol2str(DOT));
#else #else
@ -34,14 +41,14 @@ LLmessage(tk) {
tk_nmb_at_last_syn_err = token_nmb; tk_nmb_at_last_syn_err = token_nmb;
} }
insert_token(tk) static void insert_token(int tk)
int tk;
{ {
aside = dot; aside = dot;
DOT = tk; DOT = tk;
switch (tk) { switch (tk)
{
/* The operands need some body */ /* The operands need some body */
case IDENTIFIER: case IDENTIFIER:
dot.tk_idf = gen_idf(); dot.tk_idf = gen_idf();

View file

@ -24,16 +24,19 @@
#include "Lpars.h" #include "Lpars.h"
#include "field.h" #include "field.h"
#include "mes.h" #include "mes.h"
#include "cstoper.h"
#include "ch3bin.h"
#include "ch3.h"
#include "error.h"
extern char *symbol2str(); extern char *symbol2str();
extern char options[]; extern char options[];
extern arith flt_flt2arith(); extern arith flt_flt2arith();
extern label code_string(); extern label code_string();
void /* 3.1.2.5 */
arithbalance(e1p, oper, e2p) /* 3.1.2.5 */ void arithbalance(register struct expr **e1p, int oper, register struct expr **e2p)
register struct expr **e1p, **e2p;
int oper;
{ {
/* The expressions *e1p and *e2p are balanced to be operands /* The expressions *e1p and *e2p are balanced to be operands
of the arithmetic operator oper. of the arithmetic operator oper.
@ -171,8 +174,7 @@ arithbalance(e1p, oper, e2p) /* 3.1.2.5 */
} }
} }
relbalance(e1p, oper, e2p) void relbalance(register struct expr **e1p, int oper, register struct expr **e2p)
register struct expr **e1p, **e2p;
{ {
/* The expressions *e1p and *e2p are balanced to be operands /* The expressions *e1p and *e2p are balanced to be operands
of the relational operator oper, or the ':'. of the relational operator oper, or the ':'.
@ -204,9 +206,7 @@ relbalance(e1p, oper, e2p)
arithbalance(e1p, oper, e2p); arithbalance(e1p, oper, e2p);
} }
ch3pointer(expp, oper, tp) void ch3pointer(struct expr **expp, int oper, register struct type *tp)
struct expr **expp;
register struct type *tp;
{ {
/* Checks whether *expp may be compared to tp using oper, /* Checks whether *expp may be compared to tp using oper,
as described in chapter 3.3.8 and 3.3.9. as described in chapter 3.3.8 and 3.3.9.
@ -238,9 +238,7 @@ ch3pointer(expp, oper, tp)
} }
int int
any2arith(expp, oper) any2arith(register struct expr **expp, register int oper)
register struct expr **expp;
register int oper;
{ {
/* Turns any expression into int_type, long_type, /* Turns any expression into int_type, long_type,
float_type, double_type or lngdbl_type. float_type, double_type or lngdbl_type.
@ -295,8 +293,7 @@ any2arith(expp, oper)
return (*expp)->ex_type->tp_fund; return (*expp)->ex_type->tp_fund;
} }
erroneous2int(expp) void erroneous2int(struct expr **expp)
struct expr **expp;
{ {
/* the (erroneous) expression *expp is replaced by an /* the (erroneous) expression *expp is replaced by an
int expression int expression
@ -310,11 +307,7 @@ erroneous2int(expp)
*expp = exp; *expp = exp;
} }
struct expr * struct expr *arith2arith(struct type *tp, int oper, register struct expr *expr)
arith2arith(tp, oper, expr)
struct type *tp;
int oper;
register struct expr *expr;
{ {
/* arith2arith constructs a new expression containing a /* arith2arith constructs a new expression containing a
run-time conversion between some arithmetic types. run-time conversion between some arithmetic types.
@ -328,10 +321,7 @@ arith2arith(tp, oper, expr)
return new_oper(tp, new, oper, expr); return new_oper(tp, new, oper, expr);
} }
int int int2int(struct expr **expp, register struct type *tp)
int2int(expp, tp)
struct expr **expp;
register struct type *tp;
{ {
/* The expression *expp, which is of some integral type, is /* The expression *expp, which is of some integral type, is
converted to the integral type tp. converted to the integral type tp.
@ -369,9 +359,7 @@ int2int(expp, tp)
/* With compile-time constants, we don't set fp_used, since this is done /* With compile-time constants, we don't set fp_used, since this is done
* only when necessary in eval.c. * only when necessary in eval.c.
*/ */
int2float(expp, tp) void int2float(register struct expr **expp, struct type *tp)
register struct expr **expp;
struct type *tp;
{ {
/* The expression *expp, which is of some integral type, is /* The expression *expp, which is of some integral type, is
converted to the floating type tp. converted to the floating type tp.
@ -390,9 +378,7 @@ int2float(expp, tp)
} }
} }
float2int(expp, tp) void float2int(struct expr **expp, struct type *tp)
struct expr **expp;
struct type *tp;
{ {
/* The expression *expp, which is of some floating type, is /* The expression *expp, which is of some floating type, is
converted to the integral type tp. converted to the integral type tp.
@ -418,9 +404,7 @@ float2int(expp, tp)
} }
} }
float2float(expp, tp) void float2float(register struct expr **expp, struct type *tp)
register struct expr **expp;
struct type *tp;
{ {
/* The expression *expp, which is of some floating type, is /* The expression *expp, which is of some floating type, is
converted to the floating type tp. converted to the floating type tp.
@ -436,8 +420,7 @@ float2float(expp, tp)
} }
} }
array2pointer(exp) void array2pointer(register struct expr *exp)
register struct expr *exp;
{ {
/* The expression, which must be an array, is converted /* The expression, which must be an array, is converted
to a pointer. to a pointer.
@ -447,8 +430,7 @@ array2pointer(exp)
, (arith)0, NO_PROTO); , (arith)0, NO_PROTO);
} }
function2pointer(exp) void function2pointer(register struct expr *exp)
register struct expr *exp;
{ {
/* The expression, which must be a function, is converted /* The expression, which must be a function, is converted
to a pointer to the function. to a pointer to the function.
@ -457,8 +439,7 @@ function2pointer(exp)
(arith)0, NO_PROTO); (arith)0, NO_PROTO);
} }
string2pointer(ex) void string2pointer(register struct expr *ex)
register struct expr *ex;
{ {
/* The expression, which must be a string constant, is converted /* The expression, which must be a string constant, is converted
to a pointer to the string-containing area. to a pointer to the string-containing area.
@ -472,9 +453,7 @@ string2pointer(ex)
ex->VL_VALUE = (arith)0; ex->VL_VALUE = (arith)0;
} }
opnd2integral(expp, oper) void opnd2integral(register struct expr **expp, int oper)
register struct expr **expp;
int oper;
{ {
register int fund = (*expp)->ex_type->tp_fund; register int fund = (*expp)->ex_type->tp_fund;
@ -486,9 +465,7 @@ opnd2integral(expp, oper)
} }
} }
opnd2logical(expp, oper) void opnd2logical(register struct expr **expp, int oper)
register struct expr **expp;
int oper;
{ {
int fund = (*expp)->ex_type->tp_fund; int fund = (*expp)->ex_type->tp_fund;
@ -525,8 +502,7 @@ opnd2logical(expp, oper)
} }
void void
opnd2test(expp, oper) opnd2test(register struct expr **expp, int oper)
register struct expr **expp;
{ {
opnd2logical(expp, oper); opnd2logical(expp, oper);
if ((*expp)->ex_class == Oper) { if ((*expp)->ex_class == Oper) {
@ -550,9 +526,7 @@ opnd2test(expp, oper)
ch3bin(expp, NOTEQUAL, intexpr((arith)0, INT)); ch3bin(expp, NOTEQUAL, intexpr((arith)0, INT));
} }
void void any2opnd(register struct expr **expp, int oper)
any2opnd(expp, oper)
register struct expr **expp;
{ {
if (!*expp) if (!*expp)
return; return;
@ -584,8 +558,7 @@ any2opnd(expp, oper)
} }
} }
any2parameter(expp) void any2parameter(register struct expr **expp)
register struct expr **expp;
{ {
/* To handle default argument promotions /* To handle default argument promotions
*/ */
@ -598,8 +571,7 @@ any2parameter(expp)
} }
#ifndef NOBITFIELD #ifndef NOBITFIELD
field2arith(expp) void field2arith(register struct expr **expp)
register struct expr **expp;
{ {
/* The expression to extract the bitfield value from the /* The expression to extract the bitfield value from the
memory word is put in the tree. memory word is put in the tree.
@ -630,8 +602,7 @@ field2arith(expp)
/* switch_sign_fp() negates the given floating constant expression, /* switch_sign_fp() negates the given floating constant expression,
* and frees the string representing the old value. * and frees the string representing the old value.
*/ */
switch_sign_fp(expr) void switch_sign_fp(register struct expr *expr)
register struct expr *expr;
{ {
flt_umin(&(expr->FL_ARITH)); flt_umin(&(expr->FL_ARITH));
} }

View file

@ -12,12 +12,15 @@
to save storage on small machines, SPECIAL_ARITHMETICS will to save storage on small machines, SPECIAL_ARITHMETICS will
be handy. be handy.
*/ */
#ifndef ARITH_H_
#define ARITH_H_
#include "parameters.h" #include "parameters.h"
#ifndef SPECIAL_ARITHMETICS #ifndef SPECIAL_ARITHMETICS
#include <em_arith.h> /* obtain definition of "arith" */ #include <em_arith.h> /* obtain definition of "arith" */
#include <flt_arith.h>
#else /* SPECIAL_ARITHMETICS */ #else /* SPECIAL_ARITHMETICS */
@ -27,6 +30,32 @@
#endif /* SPECIAL_ARITHMETICS */ #endif /* SPECIAL_ARITHMETICS */
struct expr;
struct type;
#define arith_size (sizeof(arith)) #define arith_size (sizeof(arith))
#define arith_sign ((arith) 1 << (arith_size * 8 - 1)) #define arith_sign ((arith) 1 << (arith_size * 8 - 1))
#define max_arith (~arith_sign) #define max_arith (~arith_sign)
void arithbalance(register struct expr **e1p, int oper, register struct expr **e2p);
void relbalance(register struct expr **e1p, int oper, register struct expr **e2p);
void ch3pointer(struct expr **expp, int oper, register struct type *tp);
int any2arith(register struct expr **expp, register int oper);
void erroneous2int(struct expr **expp);
struct expr *arith2arith(struct type *tp, int oper, register struct expr *expr);
int int2int(struct expr **expp, register struct type *tp);
void int2float(register struct expr **expp, struct type *tp);
void float2int(struct expr **expp, struct type *tp);
void float2float(register struct expr **expp, struct type *tp);
void array2pointer(register struct expr *exp);
void function2pointer(register struct expr *exp);
void string2pointer(register struct expr *ex);
void opnd2integral(register struct expr **expp, int oper);
void opnd2logical(register struct expr **expp, int oper);
void opnd2test(register struct expr **expp, int oper);
void any2opnd(register struct expr **expp, int oper);
void any2parameter(register struct expr **expp);
void field2arith(register struct expr **expp);
void switch_sign_fp(register struct expr *expr);
#endif /* ARITH_H_ */

View file

@ -18,7 +18,10 @@
#include "label.h" #include "label.h"
#include "stack.h" #include "stack.h"
#include "Lpars.h" #include "Lpars.h"
extern arith NewLocal(); #include "blocks.h"
#include "macro.h"
#include "util.h"
#define LocalPtrVar() NewLocal(pointer_size, pointer_align, reg_pointer, REGISTER) #define LocalPtrVar() NewLocal(pointer_size, pointer_align, reg_pointer, REGISTER)
#define LocalIntVar() NewLocal(int_size, int_align, reg_any, REGISTER) #define LocalIntVar() NewLocal(int_size, int_align, reg_any, REGISTER)
#endif /* STB */ #endif /* STB */
@ -52,9 +55,7 @@ extern arith NewLocal();
while we need a loop to store the stack block into a memory object. while we need a loop to store the stack block into a memory object.
*/ */
suitable_sz(sz, al) int suitable_sz(arith sz, int al)
arith sz;
int al;
{ {
return ((int)sz % (int)word_size == 0 && al % word_align == 0) || return ((int)sz % (int)word_size == 0 && al % word_align == 0) ||
( (
@ -64,9 +65,7 @@ suitable_sz(sz, al)
); );
} }
store_block(sz, al) void store_block(arith sz, int al)
arith sz;
int al;
{ {
if (suitable_sz(sz, al)) if (suitable_sz(sz, al))
C_sti(sz); C_sti(sz);
@ -102,9 +101,7 @@ store_block(sz, al)
} }
} }
load_block(sz, al) void load_block(arith sz, int al)
arith sz;
int al;
{ {
if (suitable_sz(sz, al)) if (suitable_sz(sz, al))
@ -138,9 +135,7 @@ load_block(sz, al)
} }
} }
copy_block(sz, al) void copy_block(arith sz, int al)
arith sz;
int al;
{ {
if (suitable_sz(sz, al)) if (suitable_sz(sz, al))
@ -167,8 +162,7 @@ copy_block(sz, al)
} }
#ifndef STB #ifndef STB
copy_loop(sz, src, dst) void copy_loop(arith sz, arith src, arith dst)
arith sz, src, dst;
{ {
/* generate inline byte-copy loop */ /* generate inline byte-copy loop */
label l_cont = text_label(), l_stop = text_label(); label l_cont = text_label(), l_stop = text_label();

View file

@ -0,0 +1,20 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-06
*
*/
#ifndef BLOCKS_H_
#define BLOCKS_H_
#include "parameters.h"
#include "arith.h"
int suitable_sz(arith sz, int al);
void store_block(arith sz, int al);
void load_block(arith sz, int al);
void copy_block(arith sz, int al);
void copy_loop(arith sz, arith src, arith dst);
#endif /* BLOCKS_H_ */

View file

@ -9,6 +9,7 @@
#include "parameters.h" #include "parameters.h"
#include <flt_arith.h> #include <flt_arith.h>
#include "arith.h" #include "arith.h"
#include "ch3.h"
#include "idf.h" #include "idf.h"
#include "proto.h" #include "proto.h"
#include "type.h" #include "type.h"
@ -17,23 +18,22 @@
#include "expr.h" #include "expr.h"
#include "def.h" #include "def.h"
#include "Lpars.h" #include "Lpars.h"
#include "error.h"
#include "ch3bin.h"
#include "file_info.h" #include "file_info.h"
extern char options[]; extern char options[];
extern char *symbol2str(); extern char *symbol2str();
extern struct type *qualifier_type(); extern struct type *qualifier_type();
void ch3cast();
/* Most expression-handling routines have a pointer to a /* Most expression-handling routines have a pointer to a
(struct type *) as first parameter. The object under the pointer (struct type *) as first parameter. The object under the pointer
gets updated in the process. gets updated in the process.
*/ */
void void ch3sel(struct expr **expp, int oper, struct idf *idf)
ch3sel(expp, oper, idf)
struct expr **expp;
struct idf *idf;
{ {
/* The selector idf is applied to *expp; oper may be '.' or /* The selector idf is applied to *expp; oper may be '.' or
ARROW. ARROW.
@ -163,8 +163,7 @@ ch3sel(expp, oper, idf)
*expp = exp; *expp = exp;
} }
ch3incr(expp, oper) void ch3incr(struct expr **expp, int oper)
struct expr **expp;
{ {
/* The monadic prefix/postfix incr/decr operator oper is /* The monadic prefix/postfix incr/decr operator oper is
applied to *expp. applied to *expp.
@ -172,10 +171,7 @@ ch3incr(expp, oper)
ch3asgn(expp, oper, intexpr((arith)1, INT)); ch3asgn(expp, oper, intexpr((arith)1, INT));
} }
void void ch3cast(register struct expr **expp, int oper, register struct type *tp)
ch3cast(expp, oper, tp)
register struct expr **expp;
register struct type *tp;
{ {
/* The expression *expp is cast to type tp; the cast is /* The expression *expp is cast to type tp; the cast is
caused by the operator oper. If the cast has caused by the operator oper. If the cast has
@ -412,9 +408,7 @@ ch3cast(expp, oper, tp)
/* Determine whether two types are equal. /* Determine whether two types are equal.
*/ */
equal_type(tp, otp, qual_lev, diag) int equal_type(register struct type *tp,register struct type *otp, int qual_lev, int diag)
register struct type *tp, *otp;
int qual_lev, diag;
{ {
if (tp == otp) if (tp == otp)
return 1; return 1;
@ -475,8 +469,7 @@ equal_type(tp, otp, qual_lev, diag)
} }
} }
check_pseudoproto(pl, opl, diag) int check_pseudoproto(register struct proto *pl,register struct proto *opl, int diag)
register struct proto *pl, *opl;
{ {
int retval = 1; int retval = 1;
@ -519,9 +512,7 @@ check_pseudoproto(pl, opl, diag)
return retval; return retval;
} }
legal_mixture(tp, otp, diag) int legal_mixture(struct type *tp, struct type *otp, int diag)
struct type *tp, *otp;
int diag;
{ {
struct proto *pl = tp->tp_proto, *opl = otp->tp_proto; struct proto *pl = tp->tp_proto, *opl = otp->tp_proto;
int retval = 1; int retval = 1;
@ -562,9 +553,7 @@ legal_mixture(tp, otp, diag)
return retval; return retval;
} }
equal_proto(pl, opl, diag) int equal_proto(register struct proto *pl, register struct proto *opl, int diag)
register struct proto *pl, *opl;
int diag;
{ {
if (pl == opl) if (pl == opl)
return 1; return 1;
@ -586,9 +575,7 @@ equal_proto(pl, opl, diag)
} }
/* check if a type has a consqualified member */ /* check if a type has a consqualified member */
recurqual(tp, qual) int recurqual(struct type *tp, int qual)
struct type *tp;
int qual;
{ {
register struct sdef *sdf; register struct sdef *sdf;
@ -610,9 +597,7 @@ int qual;
return 0; return 0;
} }
ch3asgn(expp, oper, expr) void ch3asgn(struct expr **expp, int oper, struct expr *expr)
struct expr **expp;
struct expr *expr;
{ {
/* The assignment operators. /* The assignment operators.
"f op= e" should be interpreted as "f op= e" should be interpreted as
@ -687,9 +672,7 @@ ch3asgn(expp, oper, expr)
/* Some interesting (?) questions answered. /* Some interesting (?) questions answered.
*/ */
int int is_integral_type(register struct type *tp)
is_integral_type(tp)
register struct type *tp;
{ {
switch (tp->tp_fund) { switch (tp->tp_fund) {
case CHAR: case CHAR:
@ -707,9 +690,7 @@ is_integral_type(tp)
} }
} }
int int is_arith_type(register struct type *tp)
is_arith_type(tp)
register struct type *tp;
{ {
switch (tp->tp_fund) { switch (tp->tp_fund) {
case CHAR: case CHAR:

View file

@ -0,0 +1,29 @@
/* Copyright (c) 2019 ACK Project. See the file Copyright in
* the project root directory for more information.
*
* Created on: 2019-02-06
*
*/
#ifndef CH3_H_
#define CH3_H_
/* Structure forward declarations. */
struct expr;
struct type;
struct proto;
struct idf;
void ch3sel(struct expr **expp, int oper, struct idf *idf);
void ch3incr(struct expr **expp, int oper);
void ch3cast(register struct expr **expp, int oper, register struct type *tp);
int equal_type(register struct type *tp,register struct type *otp, int qual_lev, int diag);
int check_pseudoproto(register struct proto *pl,register struct proto *opl, int diag);
int legal_mixture(struct type *tp, struct type *otp, int diag);
int equal_proto(register struct proto *pl, register struct proto *opl, int diag);
int recurqual(struct type *tp, int qual);
void ch3asgn(struct expr **expp, int oper, struct expr *expr);
int is_integral_type(register struct type *tp);
int is_arith_type(register struct type *tp);
#endif /* CH3_H_ */

View file

@ -15,6 +15,12 @@
#include "expr.h" #include "expr.h"
#include "Lpars.h" #include "Lpars.h"
#include "sizes.h" #include "sizes.h"
#include "ch3bin.h"
#include "ch3mon.h"
#include "ch3.h"
#include "error.h"
#include "cstoper.h"
#include "fltcstoper.h"
extern char options[]; extern char options[];
extern char *symbol2str(); extern char *symbol2str();
@ -34,10 +40,7 @@ void pntminuspnt();
#define commutative_binop(expp, oper, expr) mk_binop(expp, oper, expr, 1) #define commutative_binop(expp, oper, expr) mk_binop(expp, oper, expr, 1)
#define non_commutative_relop(expp, oper, expr) mk_binop(expp, oper, expr, 1) #define non_commutative_relop(expp, oper, expr) mk_binop(expp, oper, expr, 1)
void void ch3bin(register struct expr **expp, int oper, struct expr *expr)
ch3bin(expp, oper, expr)
register struct expr **expp;
struct expr *expr;
{ {
/* apply binary operator oper between *expp and expr. /* apply binary operator oper between *expp and expr.
NB: don't swap operands if op is one of the op= operators!!! NB: don't swap operands if op is one of the op= operators!!!
@ -295,9 +298,7 @@ ch3bin(expp, oper, expr)
} }
} }
void void pntminuspnt(register struct expr **expp, int oper, register struct expr *expr)
pntminuspnt(expp, oper, expr)
register struct expr **expp, *expr;
{ {
/* Subtracting two pointers is so complicated it merits a /* Subtracting two pointers is so complicated it merits a
routine of its own. routine of its own.
@ -328,8 +329,7 @@ pntminuspnt(expp, oper, expr)
* when the arguments are switched. This is special for some relational * when the arguments are switched. This is special for some relational
* operators. * operators.
*/ */
int int arg_switched(int oper)
arg_switched(oper)
{ {
switch (oper) { switch (oper) {
case '<': return '>'; case '<': return '>';
@ -340,9 +340,7 @@ arg_switched(oper)
} }
} }
mk_binop(expp, oper, expr, commutative) void mk_binop(struct expr **expp, int oper, register struct expr *expr, int commutative)
struct expr **expp;
register struct expr *expr;
{ {
/* Constructs in *expp the operation indicated by the operands. /* Constructs in *expp the operation indicated by the operands.
"commutative" indicates whether "oper" is a commutative "commutative" indicates whether "oper" is a commutative
@ -366,8 +364,7 @@ mk_binop(expp, oper, expr, commutative)
} }
} }
pointer_arithmetic(expp1, oper, expp2) void pointer_arithmetic(register struct expr **expp1, int oper, register struct expr **expp2)
register struct expr **expp1, **expp2;
{ {
int typ; int typ;
/* prepares the integral expression expp2 in order to /* prepares the integral expression expp2 in order to
@ -387,8 +384,7 @@ pointer_arithmetic(expp1, oper, expp2)
); );
} }
pointer_binary(expp, oper, expr) void pointer_binary(register struct expr **expp, int oper, register struct expr *expr)
register struct expr **expp, *expr;
{ {
/* constructs the pointer arithmetic expression out of /* constructs the pointer arithmetic expression out of
a pointer expression, a binary operator and an integral a pointer expression, a binary operator and an integral

View file

@ -0,0 +1,21 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-06
*
*/
#ifndef CH3BIN_H_
#define CH3BIN_H_
struct expr;
void ch3bin(register struct expr **expp, int oper, struct expr *expr);
void pntminuspnt(register struct expr **expp, int oper, register struct expr *expr);
int arg_switched(int oper);
void mk_binop(struct expr **expp, int oper, register struct expr *expr, int commutative);
void pointer_arithmetic(register struct expr **expp1, int oper, register struct expr **expp2);
void pointer_binary(register struct expr **expp, int oper, register struct expr *expr);
#endif /* CH3BIN_H_ */

View file

@ -5,6 +5,7 @@
/* $Id$ */ /* $Id$ */
/* SEMANTIC ANALYSIS (CHAPTER 3.3) -- MONADIC OPERATORS */ /* SEMANTIC ANALYSIS (CHAPTER 3.3) -- MONADIC OPERATORS */
#include "ch3mon.h"
#include "parameters.h" #include "parameters.h"
#include <alloc.h> #include <alloc.h>
#include "Lpars.h" #include "Lpars.h"
@ -16,13 +17,15 @@
#include "expr.h" #include "expr.h"
#include "def.h" #include "def.h"
#include "sizes.h" #include "sizes.h"
#include "ch3.h"
#include "error.h"
extern char options[]; extern char options[];
extern arith full_mask[/*MAXSIZE + 1*/]; /* cstoper.c */ extern arith full_mask[/*MAXSIZE + 1*/]; /* cstoper.c */
char *symbol2str(); char *symbol2str();
ch3mon(oper, expp) void ch3mon(int oper, register struct expr **expp)
register struct expr **expp;
{ {
/* The monadic prefix operator oper is applied to *expp. /* The monadic prefix operator oper is applied to *expp.
*/ */

View file

@ -0,0 +1,22 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-06
*
*/
#ifndef CH3MON_H_
#define CH3MON_H_
struct expr;
void ch3mon(int oper, register struct expr **expp);
void ch3bin(register struct expr **expp, int oper, struct expr *expr);
void pntminuspnt(register struct expr **expp, int oper, register struct expr *expr);
int arg_switched(int oper);
void mk_binop(struct expr **expp, int oper, register struct expr *expr, int commutative);
void pointer_arithmetic(register struct expr **expp1, int oper, register struct expr **expp2);
void pointer_binary(register struct expr **expp, int oper, register struct expr *expr);
#endif /* CH3MON_H_ */

View file

@ -27,14 +27,24 @@
#include "expr.h" #include "expr.h"
#include "sizes.h" #include "sizes.h"
#include "stack.h" #include "stack.h"
#include "blocks.h"
#include "struct.h"
#include "level.h" #include "level.h"
#include "dataflow.h"
#include "conversion.h"
#include "decspecs.h" #include "decspecs.h"
#include "declar.h" #include "declar.h"
#include "Lpars.h" #include "Lpars.h"
#include "specials.h" #include "specials.h"
#include "atw.h" #include "atw.h"
#include "ch3.h"
#include "eval.h"
#include "stab.h"
#include "LLlex.h" #include "LLlex.h"
#include "align.h" #include "align.h"
#include "util.h"
#include "error.h"
#ifdef LINT #ifdef LINT
#include "l_lint.h" #include "l_lint.h"
#endif /* LINT */ #endif /* LINT */
@ -46,7 +56,10 @@ label lab_count = 1;
label datlab_count = 1; label datlab_count = 1;
int fp_used; int fp_used;
extern arith NewLocal(); /* util.c */
extern void str_cst(register char *, register int, int); /* ival.c */
/* global function info */ /* global function info */
char *func_name; char *func_name;
@ -67,8 +80,7 @@ extern char *source;
void loc_init(); void loc_init();
#ifndef LINT #ifndef LINT
init_code(dst_file) void init_code(char *dst_file)
char *dst_file;
{ {
/* init_code() initialises the output file on which the /* init_code() initialises the output file on which the
compact EM code is written compact EM code is written
@ -105,10 +117,7 @@ init_code(dst_file)
struct string_cst *str_list = 0; struct string_cst *str_list = 0;
label label code_string(char* val, int len)
code_string(val, len)
char *val;
int len;
{ {
register struct string_cst *sc = new_string_cst(); register struct string_cst *sc = new_string_cst();
label dlb = data_label(); label dlb = data_label();
@ -122,8 +131,7 @@ code_string(val, len)
return dlb; return dlb;
} }
def_strings(sc) void def_strings(register struct string_cst *sc)
register struct string_cst *sc;
{ {
while (sc) { while (sc) {
struct string_cst *sc1 = sc; struct string_cst *sc1 = sc;
@ -137,7 +145,7 @@ def_strings(sc)
} }
/* flush_strings() is called from program.g after each external definition */ /* flush_strings() is called from program.g after each external definition */
flush_strings() { void flush_strings(void) {
if (str_list) { if (str_list) {
def_strings(str_list); def_strings(str_list);
str_list = 0; str_list = 0;
@ -145,7 +153,7 @@ flush_strings() {
} }
#ifndef LINT #ifndef LINT
end_code() void end_code(void)
{ {
/* end_code() performs the actions to be taken when closing /* end_code() performs the actions to be taken when closing
the output stream. the output stream.
@ -160,7 +168,7 @@ end_code()
#endif /* LINT */ #endif /* LINT */
#ifdef PREPEND_SCOPES #ifdef PREPEND_SCOPES
prepend_scopes() void prepend_scopes(void)
{ {
/* prepend_scopes() runs down the list of global idf's /* prepend_scopes() runs down the list of global idf's
and generates those exa's, exp's, ina's and inp's and generates those exa's, exp's, ina's and inp's
@ -185,9 +193,7 @@ prepend_scopes()
} }
#endif /* PREPEND_SCOPES */ #endif /* PREPEND_SCOPES */
code_scope(text, def) void code_scope(char* text, register struct def *def)
char *text;
register struct def *def;
{ {
/* generates code for one name, text, of the storage class /* generates code for one name, text, of the storage class
as given by def, if meaningful. as given by def, if meaningful.
@ -218,9 +224,7 @@ static int struct_return;
static char *last_fn_given = (char *)0; static char *last_fn_given = (char *)0;
static label file_name_label; static label file_name_label;
begin_proc(ds, idf) /* to be called when entering a procedure */ void begin_proc(struct decspecs *ds, struct idf *idf) /* to be called when entering a procedure */
struct decspecs *ds;
struct idf *idf;
{ {
/* begin_proc() is called at the entrance of a new function /* begin_proc() is called at the entrance of a new function
and performs the necessary code generation: and performs the necessary code generation:
@ -317,8 +321,7 @@ begin_proc(ds, idf) /* to be called when entering a procedure */
#endif #endif
} }
end_proc(fbytes) void end_proc(arith fbytes)
arith fbytes;
{ {
/* end_proc() deals with the code to be generated at the end of /* end_proc() deals with the code to be generated at the end of
a function, as there is: a function, as there is:
@ -388,7 +391,7 @@ end_proc(fbytes)
options['n'] = optionsn; options['n'] = optionsn;
} }
do_return() void do_return(void)
{ {
/* do_return handles the case of a return without expression. /* do_return handles the case of a return without expression.
This version branches to the return label, which is This version branches to the return label, which is
@ -401,8 +404,7 @@ do_return()
C_bra(return2_label); C_bra(return2_label);
} }
do_return_expr(expr) void do_return_expr(struct expr *expr)
struct expr *expr;
{ {
/* do_return_expr() generates the expression and the jump for /* do_return_expr() generates the expression and the jump for
a return statement with an expression. a return statement with an expression.
@ -418,11 +420,11 @@ do_return_expr(expr)
} }
void void
code_declaration(idf, expr, lvl, sc) code_declaration(
register struct idf *idf; /* idf to be declared */ register struct idf *idf, /* idf to be declared */
struct expr *expr; /* initialisation; NULL if absent */ struct expr *expr, /* initialisation; NULL if absent */
int lvl; /* declaration level */ int lvl, /* declaration level */
int sc; /* storage class, as in the declaration */ int sc) /* storage class, as in the declaration */
{ {
/* code_declaration() does the actual declaration of the /* code_declaration() does the actual declaration of the
variable indicated by "idf" on declaration level "lvl". variable indicated by "idf" on declaration level "lvl".
@ -530,10 +532,7 @@ code_declaration(idf, expr, lvl, sc)
} }
} }
void void loc_init(struct expr *expr, struct idf *id)
loc_init(expr, id)
struct expr *expr;
struct idf *id;
{ {
/* loc_init() generates code for the assignment of /* loc_init() generates code for the assignment of
expression expr to the local variable described by id. expression expr to the local variable described by id.
@ -609,8 +608,7 @@ loc_init(expr, id)
} }
} }
bss(idf) void bss(register struct idf *idf)
register struct idf *idf;
{ {
/* bss() allocates bss space for the global idf. /* bss() allocates bss space for the global idf.
*/ */
@ -640,9 +638,7 @@ bss(idf)
} }
} }
formal_cvt(hasproto,df) void formal_cvt(int hasproto, register struct def *df)
int hasproto;
register struct def *df;
{ {
/* formal_cvt() converts a formal parameter of type char or /* formal_cvt() converts a formal parameter of type char or
short from int to that type. It also converts a formal short from int to that type. It also converts a formal
@ -672,9 +668,7 @@ formal_cvt(hasproto,df)
#ifdef LINT #ifdef LINT
/*ARGSUSED*/ /*ARGSUSED*/
#endif /* LINT */ #endif /* LINT */
code_expr(expr, val, code, tlbl, flbl) void code_expr(struct expr *expr, int val, int code, label tlbl, label flbl)
struct expr *expr;
label tlbl, flbl;
{ {
/* code_expr() is the parser's interface to the expression code /* code_expr() is the parser's interface to the expression code
generator. If line number trace is wanted, it generates a generator. If line number trace is wanted, it generates a
@ -707,7 +701,7 @@ static struct stmt_block *stmt_stack; /* top of statement stack */
which are the only ones that are stacked, only the top of which are the only ones that are stacked, only the top of
the stack is interesting. the stack is interesting.
*/ */
code_break() void code_break(void)
{ {
register struct stmt_block *stmt_block = stmt_stack; register struct stmt_block *stmt_block = stmt_stack;
@ -726,7 +720,7 @@ code_break()
innermost statement in which continue has a meaning. innermost statement in which continue has a meaning.
*/ */
void void
code_continue() code_continue(void)
{ {
register struct stmt_block *stmt_block = stmt_stack; register struct stmt_block *stmt_block = stmt_stack;
@ -743,8 +737,7 @@ code_continue()
error("continue not inside for, while or do"); error("continue not inside for, while or do");
} }
stack_stmt(break_label, cont_label) void stack_stmt(label break_label, label cont_label)
label break_label, cont_label;
{ {
register struct stmt_block *stmt_block = new_stmt_block(); register struct stmt_block *stmt_block = new_stmt_block();
@ -754,7 +747,7 @@ stack_stmt(break_label, cont_label)
stmt_stack = stmt_block; stmt_stack = stmt_block;
} }
unstack_stmt() void unstack_stmt(void)
{ {
/* unstack_stmt() unstacks the data of a statement /* unstack_stmt() unstacks the data of a statement
which may contain break or continue which may contain break or continue
@ -766,8 +759,7 @@ unstack_stmt()
static label prc_name; static label prc_name;
prc_entry(name) void prc_entry(char* name)
char *name;
{ {
if (options['p']) { if (options['p']) {
C_df_dlb(prc_name = data_label()); C_df_dlb(prc_name = data_label());
@ -778,7 +770,7 @@ prc_entry(name)
} }
} }
prc_exit() void prc_exit(void)
{ {
if (options['p']) { if (options['p']) {
C_lae_dlb(prc_name, (arith) 0); C_lae_dlb(prc_name, (arith) 0);
@ -788,9 +780,7 @@ prc_exit()
} }
#ifdef DBSYMTAB #ifdef DBSYMTAB
db_line(file, line) void db_line(char *file, unsigned int line)
char *file;
unsigned int line;
{ {
static unsigned oldline; static unsigned oldline;
static char *oldfile; static char *oldfile;

View file

@ -2,9 +2,15 @@
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright". * See the copyright notice in the ACK home directory, in the file "Copyright".
*/ */
#ifndef CODE_H_
#define CODE_H_
/* $Id$ */ /* $Id$ */
/* C O D E - G E N E R A T O R D E F I N I T I O N S */ /* C O D E - G E N E R A T O R D E F I N I T I O N S */
#include "arith.h"
#include "label.h"
struct string_cst { /* storing string constants */ struct string_cst { /* storing string constants */
struct string_cst *next; struct string_cst *next;
char *sc_value; char *sc_value;
@ -20,3 +26,44 @@ extern struct string_cst *str_list;
#define RVAL 1 #define RVAL 1
#define FALSE 0 #define FALSE 0
#define TRUE 1 #define TRUE 1
#ifndef LINT
void init_code(char *dst_file);
void end_code(void);
#endif
struct expr;
struct def;
struct idf;
label code_string(char* val, int len);
void def_strings(register struct string_cst *sc);
void flush_strings(void);
void code_scope(char* text, register struct def *def);
void begin_proc(struct decspecs *ds, struct idf *idf);
void end_proc(arith fbytes);
void do_return(void);
void do_return_expr(struct expr *expr);
void code_declaration(register struct idf *idf, struct expr *expr,
int lvl, int sc);
void loc_init(struct expr *expr, struct idf *id);
void bss(register struct idf *idf);
void formal_cvt(int hasproto, register struct def *df);
void code_expr(struct expr *expr, int val, int code, label tlbl, label flbl);
void code_break(void);
void code_continue(void);
void stack_stmt(label break_label, label cont_label);
void unstack_stmt(void);
void prc_entry(char* name);
void prc_exit(void);
#ifdef PREPEND_SCOPES
void prepend_scopes(void);
#endif
#ifdef DBSYMTAB
void db_line(char *file, unsigned int line);
#endif
#endif

View file

@ -8,11 +8,15 @@
#include "parameters.h" #include "parameters.h"
#ifndef LINT #ifndef LINT
#include "conversion.h"
#include <em.h> #include <em.h>
#include "interface.h"
#include "arith.h" #include "arith.h"
#include "type.h" #include "type.h"
#include "sizes.h" #include "sizes.h"
#include "Lpars.h" #include "Lpars.h"
#include "error.h"
#define T_SIGNED 1 #define T_SIGNED 1
#define T_UNSIGNED 2 #define T_UNSIGNED 2
@ -27,10 +31,9 @@
C?? C??
*/ */
static int convtype(); static int convtype(register struct type *);
conversion(from_type, to_type) void conversion(register struct type *from_type, register struct type *to_type)
register struct type *from_type, *to_type;
{ {
register arith from_size = from_type->tp_size; register arith from_size = from_type->tp_size;
register arith to_size = to_type->tp_size; register arith to_size = to_type->tp_size;
@ -126,9 +129,7 @@ conversion(from_type, to_type)
/* convtype() returns in which category a given type falls: /* convtype() returns in which category a given type falls:
signed, unsigned or floating signed, unsigned or floating
*/ */
static int static int convtype(register struct type *tp)
convtype(tp)
register struct type *tp;
{ {
switch (tp->tp_fund) { switch (tp->tp_fund) {
case CHAR: case CHAR:

View file

@ -0,0 +1,15 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-06
*
*/
#ifndef CONVERSION_H_
#define CONVERSION_H_
struct type;
void conversion(register struct type *from_type, register struct type *to_type);
#endif /* CONVERSION_H_ */

View file

@ -6,6 +6,7 @@
/* C O N S T A N T E X P R E S S I O N H A N D L I N G */ /* C O N S T A N T E X P R E S S I O N H A N D L I N G */
#include <assert.h> #include <assert.h>
#include "cstoper.h"
#include "parameters.h" #include "parameters.h"
#include <flt_arith.h> #include <flt_arith.h>
#include "arith.h" #include "arith.h"
@ -14,6 +15,7 @@
#include "expr.h" #include "expr.h"
#include "sizes.h" #include "sizes.h"
#include "Lpars.h" #include "Lpars.h"
#include "error.h"
/* full_mask[1] == 0XFF, full_mask[2] == 0XFFFF, .. */ /* full_mask[1] == 0XFF, full_mask[2] == 0XFFFF, .. */
arith full_mask[MAXSIZE + 1]; arith full_mask[MAXSIZE + 1];
@ -23,8 +25,7 @@ arith max_unsigned; /* maximum unsigned on target machine */
#endif /* NOCROSS */ #endif /* NOCROSS */
extern int ResultKnown; extern int ResultKnown;
cstbin(expp, oper, expr) void cstbin(register struct expr **expp, int oper, register struct expr *expr)
register struct expr **expp, *expr;
{ {
/* The operation oper is performed on the constant /* The operation oper is performed on the constant
expressions *expp(ld) and expr(ct), and the result restored in expressions *expp(ld) and expr(ct), and the result restored in
@ -134,8 +135,7 @@ cstbin(expp, oper, expr)
free_expression(expr); free_expression(expr);
} }
cut_size(expr) void cut_size(register struct expr *expr)
register struct expr *expr;
{ {
/* The constant value of the expression expr is made to /* The constant value of the expression expr is made to
conform to the size of the type of the expression. conform to the size of the type of the expression.
@ -170,7 +170,7 @@ cut_size(expr)
expr->VL_VALUE = o1; expr->VL_VALUE = o1;
} }
init_cst() void init_cst(void)
{ {
register int i = 0; register int i = 0;
register arith bt = (arith)0; register arith bt = (arith)0;

View file

@ -0,0 +1,17 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-06
*
*/
#ifndef CSTOPER_H_
#define CSTOPER_H_
struct expr;
void cstbin(register struct expr **expp, int oper, register struct expr *expr);
void cut_size(register struct expr *expr);
void init_cst(void);
#endif /* CSTOPER_H_ */

View file

@ -10,26 +10,26 @@
*/ */
#include "parameters.h" /* UF */ #include "parameters.h" /* UF */
#include "dataflow.h"
#include "print.h"
#ifdef DATAFLOW #ifdef DATAFLOW
char *CurrentFunction = 0; char *CurrentFunction = 0;
int NumberOfCalls; int NumberOfCalls;
DfaStartFunction(nm) void DfaStartFunction(char* nm)
char *nm;
{ {
CurrentFunction = nm; CurrentFunction = nm;
NumberOfCalls = 0; NumberOfCalls = 0;
} }
DfaEndFunction() void DfaEndFunction(void)
{ {
if (NumberOfCalls == 0) if (NumberOfCalls == 0)
print("DFA: %s: --none--\n", CurrentFunction); print("DFA: %s: --none--\n", CurrentFunction);
} }
DfaCallFunction(s) void DfaCallFunction(char* s)
char *s;
{ {
print("DFA: %s: %s\n", CurrentFunction, s); print("DFA: %s: %s\n", CurrentFunction, s);
++NumberOfCalls; ++NumberOfCalls;

View file

@ -0,0 +1,19 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-06
*
*/
#ifndef DATAFLOW_H_
#define DATAFLOW_H_
#ifdef DATAFLOW
void DfaStartFunction(char* nm);
void DfaEndFunction(void);
void DfaCallFunction(char* s);
#endif
#endif /* DATAFLOW_H_ */

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,9 @@
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright". * See the copyright notice in the ACK home directory, in the file "Copyright".
*/ */
#ifndef DECLAR_H_
#define DECLAR_H_
/* $Id$ */ /* $Id$ */
/* DEFINITION OF DECLARATOR DESCRIPTORS */ /* DEFINITION OF DECLARATOR DESCRIPTORS */
@ -39,3 +42,5 @@ struct decl_unary {
extern struct type *declare_type(); extern struct type *declare_type();
extern struct declarator null_declarator; extern struct declarator null_declarator;
#endif

View file

@ -6,6 +6,7 @@
/* D E C L A R A T O R M A N I P U L A T I O N */ /* D E C L A R A T O R M A N I P U L A T I O N */
#include "parameters.h" #include "parameters.h"
#include "declarator.h"
#include <alloc.h> #include <alloc.h>
#include <flt_arith.h> #include <flt_arith.h>
#include "arith.h" #include "arith.h"
@ -14,18 +15,20 @@
#include "Lpars.h" #include "Lpars.h"
#include "declar.h" #include "declar.h"
#include "def.h" #include "def.h"
#include "idf.h"
#include "label.h" #include "label.h"
#include "expr.h" #include "expr.h"
#include "sizes.h" #include "sizes.h"
#include "level.h" #include "level.h"
#include "error.h"
extern char options[]; extern char options[];
struct declarator null_declarator; struct declarator null_declarator;
struct type * struct type *
declare_type(tp, dc) declare_type(
struct type *tp; struct type *tp,
struct declarator *dc; struct declarator *dc)
{ {
/* Applies the decl_unary list starting at dc->dc_decl_unary /* Applies the decl_unary list starting at dc->dc_decl_unary
to the type tp and returns the result. to the type tp and returns the result.
@ -43,12 +46,7 @@ declare_type(tp, dc)
return tp; return tp;
} }
add_decl_unary(dc, fund, qual, count, fm, pl) void add_decl_unary(register struct declarator *dc, int fund, int qual, arith count, struct formal *fm, struct proto *pl)
register struct declarator *dc;
int qual;
arith count;
struct formal *fm;
struct proto *pl;
{ {
/* A decl_unary describing a constructor with fundamental /* A decl_unary describing a constructor with fundamental
type fund and with size count is inserted in front of the type fund and with size count is inserted in front of the
@ -75,8 +73,7 @@ add_decl_unary(dc, fund, qual, count, fm, pl)
dc->dc_decl_unary = new; dc->dc_decl_unary = new;
} }
remove_declarator(dc) void remove_declarator(struct declarator *dc)
struct declarator *dc;
{ {
/* The decl_unary list starting at dc->dc_decl_unary is /* The decl_unary list starting at dc->dc_decl_unary is
removed. removed.
@ -91,8 +88,7 @@ remove_declarator(dc)
} }
} }
reject_params(dc) void reject_params(register struct declarator *dc)
register struct declarator *dc;
{ {
/* The declarator is checked to have no parameters, if it /* The declarator is checked to have no parameters, if it
is an old-style function. If it is a new-style function, is an old-style function. If it is a new-style function,
@ -120,8 +116,7 @@ reject_params(dc)
} }
} }
check_array_subscript(expr) void check_array_subscript(register struct expr *expr)
register struct expr *expr;
{ {
arith size = expr->VL_VALUE; arith size = expr->VL_VALUE;

View file

@ -0,0 +1,28 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-06
*
*/
#ifndef DECLARATOR_H_
#define DECLARATOR_H_
#include "arith.h"
/* Forward declarations. */
struct type;
struct declarator;
struct formal;
struct proto;
struct expr;
struct type *
declare_type(struct type *tp, struct declarator *dc);
void add_decl_unary(register struct declarator *dc, int fund, int qual,
arith count, struct formal *fm, struct proto *pl);
void remove_declarator(struct declarator *dc);
void reject_params(register struct declarator *dc);
void check_array_subscript(register struct expr *expr);
#endif /* DECLARATOR_H_ */

View file

@ -6,12 +6,13 @@
/* D E C L A R A T I O N S P E C I F I E R C H E C K I N G */ /* D E C L A R A T I O N S P E C I F I E R C H E C K I N G */
#include <assert.h> #include <assert.h>
#include "Lpars.h"
#include "decspecs.h" #include "decspecs.h"
#include "Lpars.h"
#include "arith.h" #include "arith.h"
#include "type.h" #include "type.h"
#include "level.h" #include "level.h"
#include "def.h" #include "def.h"
#include "error.h"
extern char options[]; extern char options[];
extern int level; extern int level;
@ -20,36 +21,35 @@ extern struct type *qualifier_type();
struct decspecs null_decspecs; struct decspecs null_decspecs;
do_decspecs(ds) void do_decspecs(register struct decspecs *ds)
register struct decspecs *ds;
{ {
/* The provisional decspecs ds as obtained from the program /* The provisional decspecs ds as obtained from the program
is turned into a legal consistent decspecs. is turned into a legal consistent decspecs.
*/ */
register struct type *tp = ds->ds_type; register struct type *tp = ds->ds_type;
assert(level != L_FORMAL1); assert(level != L_FORMAL1);
if ( level == L_GLOBAL && if (level == L_GLOBAL && (ds->ds_sc == AUTO || ds->ds_sc == REGISTER))
(ds->ds_sc == AUTO || ds->ds_sc == REGISTER) {
) { error("no global %s variable allowed", symbol2str(ds->ds_sc));
error("no global %s variable allowed",
symbol2str(ds->ds_sc));
ds->ds_sc = GLOBAL; ds->ds_sc = GLOBAL;
} }
if (level == L_FORMAL2) { if (level == L_FORMAL2)
if (ds->ds_sc_given && {
ds->ds_sc != REGISTER){ if (ds->ds_sc_given && ds->ds_sc != REGISTER)
{
error("%s formal illegal", symbol2str(ds->ds_sc)); error("%s formal illegal", symbol2str(ds->ds_sc));
ds->ds_sc = FORMAL; ds->ds_sc = FORMAL;
} }
} }
/* Since type qualifiers may be associated with types by means /* Since type qualifiers may be associated with types by means
of typedefs, we have to perform same basic tests down here. of typedefs, we have to perform same basic tests down here.
*/ */
if (tp != (struct type *)0) { if (tp != (struct type *) 0)
{
if ((ds->ds_typequal & TQ_VOLATILE) && (tp->tp_typequal & TQ_VOLATILE)) if ((ds->ds_typequal & TQ_VOLATILE) && (tp->tp_typequal & TQ_VOLATILE))
error("indirect repeated type qualifier"); error("indirect repeated type qualifier");
if ((ds->ds_typequal & TQ_CONST) && (tp->tp_typequal & TQ_CONST)) if ((ds->ds_typequal & TQ_CONST) && (tp->tp_typequal & TQ_CONST))
@ -58,49 +58,74 @@ do_decspecs(ds)
} }
/* The tests concerning types require a full knowledge of the /* The tests concerning types require a full knowledge of the
type and will have to be postponed to declare_idf. type and will have to be postponed to declare_idf.
*/ */
/* some adjustments as described in 3.5.2. */ /* some adjustments as described in 3.5.2. */
if (tp == 0) { if (tp == 0)
{
ds->ds_notypegiven = 1; ds->ds_notypegiven = 1;
tp = int_type; tp = int_type;
} }
if (ds->ds_size) { if (ds->ds_size)
{
register int ds_isshort = (ds->ds_size == SHORT); register int ds_isshort = (ds->ds_size == SHORT);
if (ds->ds_typedef) goto SIZE_ERROR; /* yes */ if (ds->ds_typedef)
if (tp == int_type) { goto SIZE_ERROR;
if (ds_isshort) tp = short_type; /* yes */
else tp = long_type; if (tp == int_type)
} else if (tp == double_type && !ds_isshort ) { {
if (ds_isshort)
tp = short_type;
else
tp = long_type;
}
else if (tp == double_type && !ds_isshort)
{
tp = lngdbl_type; tp = lngdbl_type;
} else { }
SIZE_ERROR: else
error("%s with illegal type",symbol2str(ds->ds_size)); {
SIZE_ERROR: error("%s with illegal type", symbol2str(ds->ds_size));
} }
ds->ds_notypegiven = 0; ds->ds_notypegiven = 0;
} }
if (ds->ds_unsigned) { if (ds->ds_unsigned)
{
register int ds_isunsigned = (ds->ds_unsigned == UNSIGNED); register int ds_isunsigned = (ds->ds_unsigned == UNSIGNED);
if (ds->ds_typedef) goto SIGN_ERROR; /* yes */ if (ds->ds_typedef)
goto SIGN_ERROR;
/* yes */
/* /*
* All integral types are signed by default (char too), * All integral types are signed by default (char too),
* so the case that ds->ds_unsigned == SIGNED can be ignored. * so the case that ds->ds_unsigned == SIGNED can be ignored.
*/ */
if (tp == schar_type) { if (tp == schar_type)
if (ds_isunsigned) tp = uchar_type; {
} else if (tp == short_type) { if (ds_isunsigned)
if (ds_isunsigned) tp = ushort_type; tp = uchar_type;
} else if (tp == int_type) { }
if (ds_isunsigned) tp = uint_type; else if (tp == short_type)
} else if (tp == long_type) { {
if (ds_isunsigned) tp = ulong_type; if (ds_isunsigned)
} else { tp = ushort_type;
SIGN_ERROR: }
error("%s with illegal type" else if (tp == int_type)
, symbol2str(ds->ds_unsigned)); {
if (ds_isunsigned)
tp = uint_type;
}
else if (tp == long_type)
{
if (ds_isunsigned)
tp = ulong_type;
}
else
{
SIGN_ERROR: error("%s with illegal type",
symbol2str(ds->ds_unsigned));
} }
ds->ds_notypegiven = 0; ds->ds_notypegiven = 0;
} }
@ -108,15 +133,12 @@ do_decspecs(ds)
} }
/* Make tp into a qualified type. This is not as trivial as it /* Make tp into a qualified type. This is not as trivial as it
may seem. If tp is a fundamental type the qualified type is may seem. If tp is a fundamental type the qualified type is
either existent or will be generated. either existent or will be generated.
In case of a complex type the top of the type list will be In case of a complex type the top of the type list will be
replaced by a qualified version. replaced by a qualified version.
*/ */
struct type * struct type *qualifier_type(register struct type *tp, int typequal)
qualifier_type(tp, typequal)
register struct type *tp;
int typequal;
{ {
register struct type *dtp = tp; register struct type *dtp = tp;
register int fund = tp->tp_fund; register int fund = tp->tp_fund;
@ -124,32 +146,34 @@ qualifier_type(tp, typequal)
while (dtp && dtp->tp_typequal != typequal) while (dtp && dtp->tp_typequal != typequal)
dtp = dtp->next; dtp = dtp->next;
if (!dtp) { if (!dtp)
{
dtp = create_type(fund); dtp = create_type(fund);
dtp->tp_unsigned = tp->tp_unsigned; dtp->tp_unsigned = tp->tp_unsigned;
dtp->tp_align = tp->tp_align; dtp->tp_align = tp->tp_align;
dtp->tp_typequal = typequal; dtp->tp_typequal = typequal;
dtp->tp_size = tp->tp_size; dtp->tp_size = tp->tp_size;
#if 0 #if 0
/* The tp_function field does not exist now. See the comment in the /* The tp_function field does not exist now. See the comment in the
function_of() routine. function_of() routine.
*/ */
dtp->tp_function = tp->tp_function; dtp->tp_function = tp->tp_function;
#endif #endif
switch (fund) { switch (fund)
{
case ARRAY: case ARRAY:
if (typequal) { if (typequal)
tp->tp_up = qualifier_type(tp->tp_up, typequal); {
dtp->tp_typequal = typequal = 0; tp->tp_up = qualifier_type(tp->tp_up, typequal);
dtp->tp_typequal = typequal = 0;
} }
goto nottagged; goto nottagged;
case FIELD: case FIELD:
dtp->tp_field = tp->tp_field; dtp->tp_field = tp->tp_field;
/* fallthrough */ /* fallthrough */
case POINTER: case POINTER:
case FUNCTION: /* dont't assign tp_proto */ case FUNCTION: /* dont't assign tp_proto */
nottagged: nottagged: dtp->tp_up = tp->tp_up;
dtp->tp_up = tp->tp_up;
break; break;
case STRUCT: case STRUCT:
case UNION: case UNION:
@ -163,6 +187,6 @@ qualifier_type(tp, typequal)
dtp->next = tp->next; /* don't know head or tail */ dtp->next = tp->next; /* don't know head or tail */
tp->next = dtp; tp->next = dtp;
} }
return(dtp); return (dtp);
} }

View file

@ -2,6 +2,9 @@
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright". * See the copyright notice in the ACK home directory, in the file "Copyright".
*/ */
#ifndef DECSPECS_H_
#define DECSPECS_H_
/* $Id$ */ /* $Id$ */
/* DECLARATION SPECIFIER DEFINITION */ /* DECLARATION SPECIFIER DEFINITION */
@ -19,3 +22,10 @@ struct decspecs {
extern struct type *qualifier_type(); extern struct type *qualifier_type();
extern struct decspecs null_decspecs; extern struct decspecs null_decspecs;
struct type;
void do_decspecs(register struct decspecs *ds);
struct type *qualifier_type(register struct type *tp, int typequal);
#endif

View file

@ -2,6 +2,9 @@
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright". * See the copyright notice in the ACK home directory, in the file "Copyright".
*/ */
#ifndef DEF_H_
#define DEF_H_
/* $Id$ */ /* $Id$ */
/* IDENTIFIER DEFINITION DESCRIPTOR */ /* IDENTIFIER DEFINITION DESCRIPTOR */
@ -38,3 +41,5 @@ struct def { /* for ordinary tags */
#define REG_BONUS 10 /* register candidate, declared as such */ #define REG_BONUS 10 /* register candidate, declared as such */
/* ALLOCDEF "def" 50 */ /* ALLOCDEF "def" 50 */
#endif

View file

@ -8,12 +8,17 @@
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "domacro.h"
#include "parameters.h" #include "parameters.h"
#include "idf.h" #include "idf.h"
#include "interface.h"
#include "arith.h" #include "arith.h"
#include "LLlex.h" #include "LLlex.h"
#include "Lpars.h" #include "Lpars.h"
#include "input.h" #include "input.h"
#include "pragma.h"
#include "skip.h"
#include "error.h"
#ifdef DBSYMTAB #ifdef DBSYMTAB
#include <stb.h> #include <stb.h>
@ -23,7 +28,9 @@ int IncludeLevel = 0;
extern char options[]; extern char options[];
struct idf* GetIdentifier(skiponerr) int skiponerr; /* skip the rest of the line on error */ static void do_line(unsigned int);
struct idf* GetIdentifier(int skiponerr) /* skip the rest of the line on error */
{ {
/* returns a pointer to the descriptor of the identifier that is /* returns a pointer to the descriptor of the identifier that is
read from the input stream. When the input does not contain read from the input stream. When the input does not contain
@ -44,7 +51,7 @@ struct idf* GetIdentifier(skiponerr) int skiponerr; /* skip the rest of the line
return tk.tk_idf; return tk.tk_idf;
} }
domacro() void domacro(void)
{ {
int tok; int tok;
struct token tk; struct token tk;
@ -70,7 +77,7 @@ domacro()
SkipToNewLine(); SkipToNewLine();
} }
do_line(l) unsigned int l; static void do_line(unsigned int l)
{ {
struct token tk; struct token tk;
int t = GetToken(&tk); int t = GetToken(&tk);

View file

@ -0,0 +1,16 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-06
*
*/
#ifndef DOMACRO_H_
#define DOMACRO_H_
struct idf;
struct idf* GetIdentifier(int skiponerr) ;
void domacro(void);
#endif /* DOMACRO_H_ */

View file

@ -6,6 +6,7 @@
/* E R R O R A N D D I A G N O S T I C R O U T I N E S */ /* E R R O R A N D D I A G N O S T I C R O U T I N E S */
#include "parameters.h" #include "parameters.h"
#include "error.h"
#if __STDC__ #if __STDC__
#include <stdarg.h> #include <stdarg.h>
#else #else
@ -17,13 +18,15 @@
#else #else
#include "l_em.h" #include "l_em.h"
#endif /* LINT */ #endif /* LINT */
#include <stdio.h>
#include "tokenname.h" #include "tokenname.h"
#include <flt_arith.h> #include <flt_arith.h>
#include "interface.h"
#include "arith.h" #include "arith.h"
#include "label.h" #include "label.h"
#include "expr.h" #include "expr.h"
#include "def.h" #include "def.h"
#include "print.h"
#include "LLlex.h" #include "LLlex.h"
/* This file contains the error-message and diagnostic /* This file contains the error-message and diagnostic
@ -56,12 +59,11 @@ extern char loptions[];
FileName, expression errors get their information from the FileName, expression errors get their information from the
expression, whereas other errors use the information in the token. expression, whereas other errors use the information in the token.
*/ */
static void _error(int, char *, unsigned int, char*, va_list);
static void _error();
#if __STDC__ #if __STDC__
/*VARARGS*/ /*VARARGS*/
error(char *fmt, ...) void error(char *fmt, ...)
{ {
va_list ap; va_list ap;
@ -73,7 +75,7 @@ error(char *fmt, ...)
} }
/*VARARGS*/ /*VARARGS*/
expr_error(struct expr *expr, char *fmt, ...) void expr_error(struct expr *expr, char *fmt, ...)
{ {
va_list ap; va_list ap;
@ -89,7 +91,7 @@ expr_error(struct expr *expr, char *fmt, ...)
} }
/*VARARGS*/ /*VARARGS*/
lexstrict(char *fmt, ...) void lexstrict(char *fmt, ...)
{ {
va_list ap; va_list ap;
@ -101,7 +103,7 @@ lexstrict(char *fmt, ...)
} }
/*VARARGS*/ /*VARARGS*/
strict(char *fmt, ...) void strict(char *fmt, ...)
{ {
va_list ap; va_list ap;
@ -113,7 +115,7 @@ strict(char *fmt, ...)
} }
/*VARARGS*/ /*VARARGS*/
expr_strict(struct expr *expr, char *fmt, ...) void expr_strict(struct expr *expr, char *fmt, ...)
{ {
va_list ap; va_list ap;
@ -129,7 +131,7 @@ expr_strict(struct expr *expr, char *fmt, ...)
#ifdef DEBUG #ifdef DEBUG
/*VARARGS*/ /*VARARGS*/
debug(char *fmt, ...) void debug(char *fmt, ...)
{ {
va_list ap; va_list ap;
@ -142,7 +144,7 @@ debug(char *fmt, ...)
#endif /* DEBUG */ #endif /* DEBUG */
/*VARARGS*/ /*VARARGS*/
warning(char *fmt, ...) void warning(char *fmt, ...)
{ {
va_list ap; va_list ap;
@ -154,7 +156,7 @@ warning(char *fmt, ...)
} }
/*VARARGS*/ /*VARARGS*/
expr_warning(struct expr *expr, char *fmt, ...) void expr_warning(struct expr *expr, char *fmt, ...)
{ {
va_list ap; va_list ap;
@ -171,7 +173,7 @@ expr_warning(struct expr *expr, char *fmt, ...)
#ifdef LINT #ifdef LINT
/*VARARGS*/ /*VARARGS*/
def_warning(struct def *def, char *fmt, ...) void def_warning(struct def *def, char *fmt, ...)
{ {
va_list ap; va_list ap;
@ -184,7 +186,7 @@ def_warning(struct def *def, char *fmt, ...)
/*VARARGS*/ /*VARARGS*/
hwarning(char *fmt, ...) void hwarning(char *fmt, ...)
{ {
va_list ap; va_list ap;
@ -197,7 +199,7 @@ hwarning(char *fmt, ...)
} }
/*VARARGS*/ /*VARARGS*/
awarning(char *fmt, ...) void awarning(char *fmt, ...)
{ {
va_list ap; va_list ap;
@ -212,7 +214,7 @@ awarning(char *fmt, ...)
#endif /* LINT */ #endif /* LINT */
/*VARARGS*/ /*VARARGS*/
lexerror(char *fmt, ...) void lexerror(char *fmt, ...)
{ {
va_list ap; va_list ap;
@ -224,7 +226,7 @@ lexerror(char *fmt, ...)
} }
/*VARARGS*/ /*VARARGS*/
lexwarning(char *fmt, ...) void lexwarning(char *fmt, ...)
{ {
va_list ap; va_list ap;
@ -236,7 +238,7 @@ lexwarning(char *fmt, ...)
} }
/*VARARGS*/ /*VARARGS*/
crash(char *fmt, ...) void crash(char *fmt, ...)
{ {
va_list ap; va_list ap;
@ -256,7 +258,7 @@ crash(char *fmt, ...)
} }
/*VARARGS*/ /*VARARGS*/
fatal(char *fmt, ...) void fatal(char *fmt, ...)
{ {
va_list ap; va_list ap;
@ -272,7 +274,7 @@ fatal(char *fmt, ...)
} }
#else #else
/*VARARGS*/ /*VARARGS*/
error(va_alist) /* fmt, args */ void error(va_alist) /* fmt, args */
va_dcl va_dcl
{ {
va_list ap; va_list ap;
@ -286,7 +288,7 @@ error(va_alist) /* fmt, args */
} }
/*VARARGS*/ /*VARARGS*/
expr_error(va_alist) /* expr, fmt, args */ void expr_error(va_alist) /* expr, fmt, args */
va_dcl va_dcl
{ {
va_list ap; va_list ap;
@ -306,7 +308,7 @@ expr_error(va_alist) /* expr, fmt, args */
} }
/*VARARGS*/ /*VARARGS*/
lexstrict(va_alist) void lexstrict(va_alist)
va_dcl va_dcl
{ {
va_list ap; va_list ap;
@ -320,7 +322,7 @@ lexstrict(va_alist)
} }
/*VARARGS*/ /*VARARGS*/
strict(va_alist) void strict(va_alist)
va_dcl va_dcl
{ {
va_list ap; va_list ap;
@ -334,7 +336,7 @@ strict(va_alist)
} }
/*VARARGS*/ /*VARARGS*/
expr_strict(va_alist) /* expr, fmt, args */ void expr_strict(va_alist) /* expr, fmt, args */
va_dcl va_dcl
{ {
va_list ap; va_list ap;
@ -354,7 +356,7 @@ expr_strict(va_alist) /* expr, fmt, args */
#ifdef DEBUG #ifdef DEBUG
/*VARARGS*/ /*VARARGS*/
debug(va_alist) void debug(va_alist)
va_dcl va_dcl
{ {
va_list ap; va_list ap;
@ -369,7 +371,7 @@ debug(va_alist)
#endif /* DEBUG */ #endif /* DEBUG */
/*VARARGS*/ /*VARARGS*/
warning(va_alist) void warning(va_alist)
va_dcl va_dcl
{ {
va_list ap; va_list ap;
@ -383,7 +385,7 @@ warning(va_alist)
} }
/*VARARGS*/ /*VARARGS*/
expr_warning(va_alist) /* expr, fmt, args */ void expr_warning(va_alist) /* expr, fmt, args */
va_dcl va_dcl
{ {
va_list ap; va_list ap;
@ -404,7 +406,7 @@ expr_warning(va_alist) /* expr, fmt, args */
#ifdef LINT #ifdef LINT
/*VARARGS*/ /*VARARGS*/
def_warning(va_alist) /* def, fmt, args */ void def_warning(va_alist) /* def, fmt, args */
va_dcl va_dcl
{ {
va_list ap; va_list ap;
@ -421,7 +423,7 @@ def_warning(va_alist) /* def, fmt, args */
/*VARARGS*/ /*VARARGS*/
hwarning(va_alist) /* fmt, args */ void hwarning(va_alist) /* fmt, args */
va_dcl va_dcl
{ {
va_list ap; va_list ap;
@ -436,7 +438,7 @@ hwarning(va_alist) /* fmt, args */
} }
/*VARARGS*/ /*VARARGS*/
awarning(va_alist) /* fmt, args */ void awarning(va_alist) /* fmt, args */
va_dcl va_dcl
{ {
va_list ap; va_list ap;
@ -453,7 +455,7 @@ awarning(va_alist) /* fmt, args */
#endif /* LINT */ #endif /* LINT */
/*VARARGS*/ /*VARARGS*/
lexerror(va_alist) /* fmt, args */ void lexerror(va_alist) /* fmt, args */
va_dcl va_dcl
{ {
va_list ap; va_list ap;
@ -467,7 +469,7 @@ lexerror(va_alist) /* fmt, args */
} }
/*VARARGS*/ /*VARARGS*/
lexwarning(va_alist) /* fmt, args */ void lexwarning(va_alist) /* fmt, args */
va_dcl va_dcl
{ {
va_list ap; va_list ap;
@ -481,7 +483,7 @@ lexwarning(va_alist) /* fmt, args */
} }
/*VARARGS*/ /*VARARGS*/
crash(va_alist) /* fmt, args */ void crash(va_alist) /* fmt, args */
va_dcl va_dcl
{ {
va_list ap; va_list ap;
@ -503,7 +505,7 @@ crash(va_alist) /* fmt, args */
} }
/*VARARGS*/ /*VARARGS*/
fatal(va_alist) /* fmt, args */ void fatal(va_alist) /* fmt, args */
va_dcl va_dcl
{ {
va_list ap; va_list ap;
@ -521,13 +523,7 @@ fatal(va_alist) /* fmt, args */
} }
#endif #endif
static void static void _error(int class, char *fn, unsigned int ln, char* fmt, va_list ap)
_error(class, fn, ln, fmt, ap)
int class;
char *fn;
unsigned int ln;
char *fmt;
va_list ap;
{ {
char *remark; char *remark;
@ -614,9 +610,9 @@ _error(class, fn, ln, fmt, ap)
#endif /* LINT */ #endif /* LINT */
if (fn) if (fn)
fprint(ERROUT, "\"%s\", line %u: ", fn, ln); fprint(stderr, "\"%s\", line %u: ", fn, ln);
if (remark) if (remark)
fprint(ERROUT, "%s ", remark); fprint(stderr, "%s ", remark);
doprnt(ERROUT, fmt, ap); /* contents of error */ doprnt(stderr, fmt, ap); /* contents of error */
fprint(ERROUT, "\n"); fprint(stderr, "\n");
} }

View file

@ -0,0 +1,94 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-06
*
*/
#ifndef ERROR_H_
#define ERROR_H_
struct expr;
#if __STDC__
/*VARARGS*/
void error(char *fmt, ...);
/*VARARGS*/
void expr_error(struct expr *expr, char *fmt, ...);
/*VARARGS*/
void lexstrict(char *fmt, ...);
/*VARARGS*/
void strict(char *fmt, ...);
/*VARARGS*/
void expr_strict(struct expr *expr, char *fmt, ...);
#ifdef DEBUG
/*VARARGS*/
void debug(char *fmt, ...);
#endif /* DEBUG */
/*VARARGS*/
void warning(char *fmt, ...);
/*VARARGS*/
void expr_warning(struct expr *expr, char *fmt, ...);
#ifdef LINT
/*VARARGS*/
void def_warning(struct def *def, char *fmt, ...);
/*VARARGS*/
void hwarning(char *fmt, ...);
/*VARARGS*/
void awarning(char *fmt, ...);
#endif /* LINT */
/*VARARGS*/
void lexerror(char *fmt, ...);
/*VARARGS*/
void lexwarning(char *fmt, ...);
/*VARARGS*/
void crash(char *fmt, ...);
/*VARARGS*/
void fatal(char *fmt, ...);
#else
/*VARARGS*/
void error(va_alist); /* fmt, args */
/*VARARGS*/
void expr_error(va_alist); /* expr, fmt, args */
/*VARARGS*/
void lexstrict(va_alist);
/*VARARGS*/
void strict(va_alist);
/*VARARGS*/
void expr_strict(va_alist); /* expr, fmt, args */
#ifdef DEBUG
/*VARARGS*/
void debug(va_alist);
#endif /* DEBUG */
/*VARARGS*/
void warning(va_alist);
/*VARARGS*/
void expr_warning(va_alist); /* expr, fmt, args */
#ifdef LINT
/*VARARGS*/
void def_warning(va_alist); /* def, fmt, args */
/*VARARGS*/
void hwarning(va_alist); /* fmt, args */
/*VARARGS*/
void awarning(va_alist); /* fmt, args */
#endif /* LINT */
/*VARARGS*/
void lexerror(va_alist); /* fmt, args */
/*VARARGS*/
void lexwarning(va_alist); /* fmt, args */
/*VARARGS*/
void crash(va_alist); /* fmt, args */
/*VARARGS*/
void fatal(va_alist); /* fmt, args */
#endif
#endif /* ERROR_H_ */

View file

@ -2,6 +2,9 @@
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright". * See the copyright notice in the ACK home directory, in the file "Copyright".
*/ */
#ifndef ESTACK_H_
#define ESTACK_H_
/* $Id$ */ /* $Id$ */
/* EXPRESSION STACK */ /* EXPRESSION STACK */
/* Used for global initializations */ /* Used for global initializations */
@ -19,3 +22,5 @@ struct e_stack {
#define last_offset s_cnt2 #define last_offset s_cnt2
#define elem_count s_cnt1 #define elem_count s_cnt1
#define nelem s_cnt2 #define nelem s_cnt2
#endif

View file

@ -14,6 +14,8 @@
#include <em_reg.h> #include <em_reg.h>
#include <alloc.h> #include <alloc.h>
#include <flt_arith.h> #include <flt_arith.h>
#include "interface.h"
#include "eval.h"
#include "idf.h" #include "idf.h"
#include "arith.h" #include "arith.h"
#include "type.h" #include "type.h"
@ -22,13 +24,21 @@
#include "def.h" #include "def.h"
#include "expr.h" #include "expr.h"
#include "sizes.h" #include "sizes.h"
#include "field.h"
#include "Lpars.h" #include "Lpars.h"
#include "level.h" #include "level.h"
#include "conversion.h"
#include "stack.h" #include "stack.h"
#include "struct.h"
#include "align.h" #include "align.h"
#include "mes.h" #include "mes.h"
#include "atw.h" #include "atw.h"
#include "ch3.h"
#include "util.h"
#include "blocks.h"
#include "dataflow.h"
#include "specials.h" #include "specials.h"
#include "error.h"
#define CRASH() crash("EVAL: CRASH at line %u", __LINE__) #define CRASH() crash("EVAL: CRASH at line %u", __LINE__)
@ -37,8 +47,12 @@ arith NewLocal(); /* util.c */
#define LocalPtrVar() NewLocal(pointer_size, pointer_align, reg_pointer, REGISTER) #define LocalPtrVar() NewLocal(pointer_size, pointer_align, reg_pointer, REGISTER)
extern int err_occurred; /* error.c */ extern int err_occurred; /* error.c */
void store_val();
void load_val(); /* Forward internal declarations */
static void operands(register struct expr *, int);
static void ptr_add(arith size);
static void truthvalue(int relop);
static void compare(int relop, label lbl);
/* EVAL() is the main expression-tree evaluator, which turns /* EVAL() is the main expression-tree evaluator, which turns
any legal expression tree into EM code. parameters.h: any legal expression tree into EM code. parameters.h:
@ -66,11 +80,7 @@ void load_val();
labels, in case they are specified (i.e. are non-zero) labels, in case they are specified (i.e. are non-zero)
*/ */
void void EVAL(register struct expr *expr, int val, int code, label true_label, label false_label)
EVAL(expr, val, code, true_label, false_label)
register struct expr *expr;
int val, code;
label true_label, false_label;
{ {
int vol = (code != TRUE && recurqual(expr->ex_type, TQ_VOLATILE)); int vol = (code != TRUE && recurqual(expr->ex_type, TQ_VOLATILE));
register int gencode = code == TRUE; register int gencode = code == TRUE;
@ -659,9 +669,7 @@ EVAL(expr, val, code, true_label, false_label)
} }
/* compare() serves as an auxiliary function of EVAL */ /* compare() serves as an auxiliary function of EVAL */
compare(relop, lbl) static void compare(int relop, label lbl)
int relop;
label lbl;
{ {
switch (relop) { switch (relop) {
case '<': case '<':
@ -688,8 +696,7 @@ compare(relop, lbl)
} }
/* truthvalue() serves as an auxiliary function of EVAL */ /* truthvalue() serves as an auxiliary function of EVAL */
truthvalue(relop) static void truthvalue(int relop)
int relop;
{ {
switch (relop) { switch (relop) {
case '<': case '<':
@ -717,12 +724,10 @@ truthvalue(relop)
/* assop() generates the opcode of an assignment operators op= */ /* assop() generates the opcode of an assignment operators op= */
assop(type, oper) void assop(register struct type *type, int oper)
register struct type *type;
int oper;
{ {
register arith size; register arith size;
register uns = type->tp_unsigned; register int uns = type->tp_unsigned;
if ((int)(size = type->tp_size) < (int)word_size) if ((int)(size = type->tp_size) < (int)word_size)
size = word_size; size = word_size;
@ -822,8 +827,7 @@ assop(type, oper)
} }
} }
ptr_add(size) static void ptr_add(arith size)
arith size;
{ {
if (size != pointer_size) { if (size != pointer_size) {
C_loc(size); C_loc(size);
@ -840,10 +844,7 @@ ptr_add(size)
- into a local static variable - into a local static variable
- absolute addressing - absolute addressing
*/ */
void void store_val(register struct value *vl, register struct type *tp)
store_val(vl, tp)
register struct value *vl;
register struct type *tp;
{ {
register int inword = 0; register int inword = 0;
register int indword = 0; register int indword = 0;
@ -911,11 +912,10 @@ store_val(vl, tp)
- global variable - global variable
- static variable - static variable
- local variable - local variable
rlval generate rlval or lval
*/ */
void void load_val(register struct expr *expr, int rlval)
load_val(expr, rlval)
register struct expr *expr; /* expression containing the value */
int rlval; /* generate either LVAL or RVAL */
{ {
register struct type *tp = expr->ex_type; register struct type *tp = expr->ex_type;
int rvalue = (rlval == RVAL && expr->ex_lvalue != 0); int rvalue = (rlval == RVAL && expr->ex_lvalue != 0);
@ -1012,8 +1012,7 @@ load_val(expr, rlval)
} }
} }
load_cst(val, siz) void load_cst(arith val, arith siz)
arith val, siz;
{ {
if ((int)siz <= (int)word_size) if ((int)siz <= (int)word_size)
C_loc(val); C_loc(val);
@ -1030,8 +1029,7 @@ load_cst(val, siz)
} }
} }
operands(expr, gencode) static void operands(register struct expr *expr, int gencode)
register struct expr *expr;
{ {
EVAL(expr->OP_LEFT, RVAL, gencode, NO_LABEL, NO_LABEL); EVAL(expr->OP_LEFT, RVAL, gencode, NO_LABEL, NO_LABEL);
EVAL(expr->OP_RIGHT, RVAL, gencode, NO_LABEL, NO_LABEL); EVAL(expr->OP_RIGHT, RVAL, gencode, NO_LABEL, NO_LABEL);

View file

@ -0,0 +1,37 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-06
*
*/
#ifndef EVAL_H_
#define EVAL_H_
#ifndef LINT
#include <em.h>
struct expr;
struct value;
struct type;
void EVAL(register struct expr *expr, int val, int code, label true_label, label false_label);
/* assop() generates the opcode of an assignment operators op= */
void assop(register struct type *type, int oper);
/* store_val() generates code for a store operation.
There are four ways of storing data:
- into a global variable
- into an automatic local variable
- into a local static variable
- absolute addressing
*/
void store_val(register struct value *vl, register struct type *tp);
void load_val(register struct expr *expr, int rlval);
void load_cst(arith val, arith siz);
#endif /* LINT */
#endif /* EVAL_H_ */

View file

@ -10,6 +10,7 @@
#include "parameters.h" #include "parameters.h"
#include <alloc.h> #include <alloc.h>
#include <flt_arith.h> #include <flt_arith.h>
#include "expr.h"
#include "idf.h" #include "idf.h"
#include "arith.h" #include "arith.h"
#include "def.h" #include "def.h"
@ -22,20 +23,21 @@
#include "declar.h" #include "declar.h"
#include "sizes.h" #include "sizes.h"
#include "level.h" #include "level.h"
#include "cstoper.h"
#include "error.h"
extern char *symbol2str(); extern char *symbol2str();
extern char options[]; extern char options[];
extern int InSizeof; extern int InSizeof;
int int rank_of(int oper)
rank_of(oper)
int oper;
{ {
/* The rank of the operator oper is returned. /* The rank of the operator oper is returned.
*/ */
switch (oper) { switch (oper)
{
default: default:
return 0; /* INT2INT etc. */ return 0; /* INT2INT etc. */
case '[': case '[':
case '(': case '(':
case '.': case '.':
@ -48,7 +50,7 @@ rank_of(oper)
case CAST: case CAST:
case SIZEOF: case SIZEOF:
case ADDRESSOF: case ADDRESSOF:
return 2; /* monadic */ return 2; /* monadic */
case '*': case '*':
case '/': case '/':
case '%': case '%':
@ -98,18 +100,18 @@ rank_of(oper)
/*NOTREACHED*/ /*NOTREACHED*/
} }
dot2expr(expp) void dot2expr(struct expr **expp)
struct expr **expp;
{ {
/* The token in dot is converted into an expression, a /* The token in dot is converted into an expression, a
pointer to which is stored in *expp. pointer to which is stored in *expp.
*/ */
register struct expr *ex = new_expr(); register struct expr *ex = new_expr();
*expp = ex; *expp = ex;
ex->ex_file = dot.tk_file; ex->ex_file = dot.tk_file;
ex->ex_line = dot.tk_line; ex->ex_line = dot.tk_line;
switch (DOT) { switch (DOT)
{
case IDENTIFIER: case IDENTIFIER:
idf2expr(ex); idf2expr(ex);
break; break;
@ -125,25 +127,27 @@ dot2expr(expp)
} }
} }
idf2expr(expr) void idf2expr(register struct expr *expr)
register struct expr *expr;
{ {
/* Dot contains an identifier which is turned into an /* Dot contains an identifier which is turned into an
expression. expression.
Note that this constitutes an applied occurrence of Note that this constitutes an applied occurrence of
the identifier. the identifier.
*/ */
register struct idf *idf = dot.tk_idf; /* != 0*/ register struct idf *idf = dot.tk_idf; /* != 0*/
register struct def *def = idf->id_def; register struct def *def = idf->id_def;
if (def == 0) { if (def == 0)
if (AHEAD == '(') { {
if (AHEAD == '(')
{
/* function call, declare name implicitly (3.3.2.2) */ /* function call, declare name implicitly (3.3.2.2) */
if (!options['o']) if (!options['o'])
warning("implicit declaration of function %s" warning("implicit declaration of function %s", idf->id_text);
, idf->id_text);
add_def(idf, EXTERN, funint_type, level); add_def(idf, EXTERN, funint_type, level);
} else { }
else
{
if (!is_anon_idf(idf)) if (!is_anon_idf(idf))
error("%s undefined", idf->id_text); error("%s undefined", idf->id_text);
/* declare idf anyway */ /* declare idf anyway */
@ -153,8 +157,10 @@ idf2expr(expr)
} }
/* now def != 0 */ /* now def != 0 */
#ifndef LINT #ifndef LINT
if (!InSizeof) { if (!InSizeof)
if (! def->df_used) { {
if (!def->df_used)
{
#ifndef PREPEND_SCOPES #ifndef PREPEND_SCOPES
code_scope(idf->id_text, def); code_scope(idf->id_text, def);
#endif /* PREPEND_SCOPES */ #endif /* PREPEND_SCOPES */
@ -163,46 +169,45 @@ idf2expr(expr)
} }
#endif /* LINT */ #endif /* LINT */
expr->ex_type = def->df_type; expr->ex_type = def->df_type;
if (expr->ex_type == error_type) { if (expr->ex_type == error_type)
{
expr->ex_flags |= EX_ERROR; expr->ex_flags |= EX_ERROR;
} }
expr->ex_lvalue = expr->ex_lvalue =
( def->df_type->tp_fund == FUNCTION || (def->df_type->tp_fund == FUNCTION || def->df_type->tp_fund == ARRAY
def->df_type->tp_fund == ARRAY || || def->df_sc == ENUM) ? 0 : 1;
def->df_sc == ENUM
) ? 0 : 1;
if (def->df_type->tp_typequal & TQ_CONST) if (def->df_type->tp_typequal & TQ_CONST)
expr->ex_flags |= EX_READONLY; expr->ex_flags |= EX_READONLY;
if (def->df_type->tp_typequal & TQ_VOLATILE) if (def->df_type->tp_typequal & TQ_VOLATILE)
expr->ex_flags |= EX_VOLATILE; expr->ex_flags |= EX_VOLATILE;
expr->ex_class = Value; expr->ex_class = Value;
if (def->df_sc == ENUM) { if (def->df_sc == ENUM)
{
expr->VL_CLASS = Const; expr->VL_CLASS = Const;
expr->VL_VALUE = def->df_address; expr->VL_VALUE = def->df_address;
} }
#ifndef LINT #ifndef LINT
else else if (def->df_sc == STATIC && def->df_level >= L_LOCAL)
if (def->df_sc == STATIC && def->df_level >= L_LOCAL) { {
expr->VL_CLASS = Label; expr->VL_CLASS = Label;
expr->VL_LBL = def->df_address; expr->VL_LBL = def->df_address;
expr->VL_VALUE = (arith)0; expr->VL_VALUE = (arith) 0;
} }
#endif /* LINT */ #endif /* LINT */
else { else
{
expr->VL_CLASS = Name; expr->VL_CLASS = Name;
expr->VL_IDF = idf; expr->VL_IDF = idf;
expr->VL_VALUE = (arith)0; expr->VL_VALUE = (arith) 0;
} }
} }
string2expr(expp, str, len) void string2expr(register struct expr **expp, char *str, int len)
register struct expr **expp;
int len;
char *str;
{ {
/* The string in the argument is converted into an expression, /* The string in the argument is converted into an expression,
a pointer to which is stored in *expp. a pointer to which is stored in *expp.
*/ */
register struct expr *ex = new_expr(); register struct expr *ex = new_expr();
*expp = ex; *expp = ex;
@ -217,25 +222,24 @@ string2expr(expp, str, len)
ex->SG_LEN = len; ex->SG_LEN = len;
} }
int2expr(expr) void int2expr(struct expr *expr)
struct expr *expr;
{ {
/* Dot contains an integer constant which is turned /* Dot contains an integer constant which is turned
into an expression. into an expression.
*/ */
fill_int_expr(expr, dot.tk_ival, dot.tk_fund); fill_int_expr(expr, dot.tk_ival, dot.tk_fund);
} }
float2expr(expr) void float2expr(register struct expr *expr)
register struct expr *expr;
{ {
/* Dot contains a floating point constant which is turned /* Dot contains a floating point constant which is turned
into an expression. into an expression.
*/ */
register int fund; register int fund;
fund = dot.tk_fund; fund = dot.tk_fund;
switch (fund) { switch (fund)
{
case FLOAT: case FLOAT:
expr->ex_type = float_type; expr->ex_type = float_type;
break; break;
@ -253,17 +257,15 @@ float2expr(expr)
free(dot.tk_fval); free(dot.tk_fval);
assert(flt_status != FLT_NOFLT); assert(flt_status != FLT_NOFLT);
if (flt_status == FLT_OVFL) if (flt_status == FLT_OVFL)
expr_warning(expr,"internal floating point overflow"); expr_warning(expr, "internal floating point overflow");
} }
struct expr* struct expr*intexpr(
intexpr(ivalue, fund) arith ivalue, int fund)
arith ivalue;
int fund;
{ {
/* The value ivalue is turned into an integer expression of /* The value ivalue is turned into an integer expression of
the size indicated by fund. the size indicated by fund.
*/ */
register struct expr *expr = new_expr(); register struct expr *expr = new_expr();
expr->ex_file = dot.tk_file; expr->ex_file = dot.tk_file;
@ -272,15 +274,14 @@ intexpr(ivalue, fund)
return expr; return expr;
} }
fill_int_expr(ex, ivalue, fund) void fill_int_expr(register struct expr *ex,
register struct expr *ex; arith ivalue, int fund)
arith ivalue;
int fund;
{ {
/* Details derived from ivalue and fund are put into the /* Details derived from ivalue and fund are put into the
constant integer expression ex. constant integer expression ex.
*/ */
switch (fund) { switch (fund)
{
case INT: case INT:
ex->ex_type = int_type; ex->ex_type = int_type;
break; break;
@ -288,7 +289,7 @@ fill_int_expr(ex, ivalue, fund)
ex->ex_type = uint_type; ex->ex_type = uint_type;
break; break;
case LONG: case LONG:
ex->ex_type = long_type; ex->ex_type = long_type;
break; break;
case ULONG: case ULONG:
ex->ex_type = ulong_type; ex->ex_type = ulong_type;
@ -303,38 +304,38 @@ fill_int_expr(ex, ivalue, fund)
cut_size(ex); cut_size(ex);
} }
struct expr * struct expr *new_oper(struct type *tp, register struct expr *e1, int oper,
new_oper(tp, e1, oper, e2) register struct expr *e2)
struct type *tp;
register struct expr *e1, *e2;
{ {
/* A new expression is constructed which consists of the /* A new expression is constructed which consists of the
operator oper which has e1 and e2 as operands; for a operator oper which has e1 and e2 as operands; for a
monadic operator e1 == NILEXPR. monadic operator e1 == NILEXPR.
During the construction of the right recursive initialisation During the construction of the right recursive initialisation
tree it is possible for e2 to be NILEXPR. tree it is possible for e2 to be NILEXPR.
*/ */
register struct expr *expr = new_expr(); register struct expr *expr = new_expr();
register struct oper *op; register struct oper *op;
if (e2) { if (e2)
{
register struct expr *e = e2; register struct expr *e = e2;
while (e->ex_class == Oper && e->OP_LEFT) while (e->ex_class == Oper && e->OP_LEFT)
e = e->OP_LEFT; e = e->OP_LEFT;
expr->ex_file = e->ex_file; expr->ex_file = e->ex_file;
expr->ex_line = e->ex_line; expr->ex_line = e->ex_line;
} }
else else if (e1)
if (e1) { {
register struct expr *e = e1; register struct expr *e = e1;
while (e->ex_class == Oper && e->OP_RIGHT) while (e->ex_class == Oper && e->OP_RIGHT)
e = e->OP_RIGHT; e = e->OP_RIGHT;
expr->ex_file = e->ex_file; expr->ex_file = e->ex_file;
expr->ex_line = e->ex_line; expr->ex_line = e->ex_line;
} }
else { else
{
expr->ex_file = dot.tk_file; expr->ex_file = dot.tk_file;
expr->ex_line = dot.tk_line; expr->ex_line = dot.tk_line;
} }
@ -342,20 +343,22 @@ new_oper(tp, e1, oper, e2)
expr->ex_type = tp; expr->ex_type = tp;
expr->ex_class = Oper; expr->ex_class = Oper;
/* combine depths and flags of both expressions */ /* combine depths and flags of both expressions */
if (e2) { if (e2)
{
int e1_depth = e1 ? e1->ex_depth : 0; int e1_depth = e1 ? e1->ex_depth : 0;
int e1_flags = e1 ? e1->ex_flags : 0; int e1_flags = e1 ? e1->ex_flags : 0;
expr->ex_depth = expr->ex_depth = (e1_depth > e2->ex_depth ? e1_depth : e2->ex_depth)
(e1_depth > e2->ex_depth ? e1_depth : e2->ex_depth) + 1; + 1;
expr->ex_flags = (e1_flags | e2->ex_flags) expr->ex_flags = (e1_flags | e2->ex_flags)
& ~(EX_PARENS | EX_READONLY | EX_VOLATILE ); & ~(EX_PARENS | EX_READONLY | EX_VOLATILE);
} }
/* /*
* A function call should be evaluated first when possible. Just say * A function call should be evaluated first when possible. Just say
* that the expression tree is very deep. * that the expression tree is very deep.
*/ */
if (oper == '(') { if (oper == '(')
{
expr->ex_depth = 50; expr->ex_depth = 50;
} }
op = &expr->ex_object.ex_oper; op = &expr->ex_object.ex_oper;
@ -369,42 +372,42 @@ new_oper(tp, e1, oper, e2)
return expr; return expr;
} }
void void chk_cst_expr(struct expr **expp)
chk_cst_expr(expp)
struct expr **expp;
{ {
/* The expression expr is checked for constancy. /* The expression expr is checked for constancy.
There are 6 places where constant expressions occur in C: There are 6 places where constant expressions occur in C:
1. after #if 1. after #if
2. in a global initialization 2. in a global initialization
3. as size in an array declaration 3. as size in an array declaration
4. as value in an enum declaration 4. as value in an enum declaration
5. as width in a bit field 5. as width in a bit field
6. as case value in a switch 6. as case value in a switch
The constant expression in a global initialization is The constant expression in a global initialization is
handled separately (by IVAL()). handled separately (by IVAL()).
There are various disparate restrictions on each of There are various disparate restrictions on each of
the others in the various C compilers. I have tried some the others in the various C compilers. I have tried some
hypotheses to unify them, but all have failed. hypotheses to unify them, but all have failed.
Special problems (of which there is only one, sizeof in Special problems (of which there is only one, sizeof in
Preprocessor #if) have to be dealt with locally Preprocessor #if) have to be dealt with locally
*/ */
register struct expr *expr = *expp; register struct expr *expr = *expp;
#ifdef DEBUG #ifdef DEBUG
print_expr("constant_expression", expr); print_expr("constant_expression", expr);
#endif /* DEBUG */ #endif /* DEBUG */
switch(expr->ex_type->tp_fund) { switch (expr->ex_type->tp_fund)
{
case CHAR: case CHAR:
case SHORT: case SHORT:
case INT: case INT:
case ENUM: case ENUM:
case LONG: case LONG:
if (is_ld_cst(expr)) { if (is_ld_cst(expr))
{
return; return;
} }
expr_error(expr, "expression is not constant"); expr_error(expr, "expression is not constant");
@ -416,67 +419,58 @@ chk_cst_expr(expp)
erroneous2int(expp); erroneous2int(expp);
} }
init_expression(eppp, expr) void init_expression(register struct expr ***eppp, struct expr *expr)
register struct expr ***eppp;
struct expr *expr;
{ {
/* The expression expr is added to the tree designated /* The expression expr is added to the tree designated
indirectly by **eppp. indirectly by **eppp.
The natural form of a tree representing an The natural form of a tree representing an
initial_value_list is right-recursive, ie. with the initial_value_list is right-recursive, ie. with the
left-most comma as main operator. The iterative grammar in left-most comma as main operator. The iterative grammar in
expression.g, however, tends to produce a left-recursive expression.g, however, tends to produce a left-recursive
tree, ie. one with the right-most comma as its main tree, ie. one with the right-most comma as its main
operator. operator.
To produce a right-recursive tree from the iterative To produce a right-recursive tree from the iterative
grammar, we keep track of the address of the pointer where grammar, we keep track of the address of the pointer where
the next expression must be hooked in. the next expression must be hooked in.
*/ */
**eppp = new_oper(void_type, expr, INITCOMMA, NILEXPR); **eppp = new_oper(void_type, expr, INITCOMMA, NILEXPR);
*eppp = &(**eppp)->OP_RIGHT; *eppp = &(**eppp)->OP_RIGHT;
} }
int int is_ld_cst(register struct expr *expr)
is_ld_cst(expr)
register struct expr *expr;
{ {
/* An expression is a `load-time constant' if it is of the form /* An expression is a `load-time constant' if it is of the form
<idf> +/- <integral> or <integral>. <idf> +/- <integral> or <integral>.
*/ */
#ifdef LINT #ifdef LINT
if (expr->ex_class == String) if (expr->ex_class == String)
return 1; return 1;
#endif /* LINT */ #endif /* LINT */
return expr->ex_lvalue == 0 && expr->ex_class == Value; return expr->ex_lvalue == 0 && expr->ex_class == Value;
} }
int int is_cp_cst(struct expr *expr)
is_cp_cst(expr)
struct expr *expr;
{ {
/* An expression is a `compile-time constant' if it is a /* An expression is a `compile-time constant' if it is a
load-time constant, and the idf is not there. load-time constant, and the idf is not there.
*/ */
return is_ld_cst(expr) && expr->VL_CLASS == Const; return is_ld_cst(expr) && expr->VL_CLASS == Const;
} }
int int is_fp_cst(struct expr *expr)
is_fp_cst(expr)
struct expr *expr;
{ {
/* An expression is a `floating-point constant' if it consists /* An expression is a `floating-point constant' if it consists
of the float only. of the float only.
*/ */
return expr->ex_class == Float; return expr->ex_class == Float;
} }
int int is_zero_cst(register struct expr *expr)
is_zero_cst(expr)
register struct expr *expr;
{ {
flt_arith var; flt_arith var;
switch(expr->ex_class) { switch (expr->ex_class)
{
case Value: case Value:
return expr->VL_VALUE == 0; return expr->VL_VALUE == 0;
case Float: case Float:
@ -486,13 +480,14 @@ is_zero_cst(expr)
/*NOTREACHED*/ /*NOTREACHED*/
} }
free_expression(expr) void free_expression(register struct expr *expr)
register struct expr *expr;
{ {
/* The expression expr is freed recursively. /* The expression expr is freed recursively.
*/ */
if (expr) { if (expr)
if (expr->ex_class == Oper) { {
if (expr->ex_class == Oper)
{
free_expression(expr->OP_LEFT); free_expression(expr->OP_LEFT);
free_expression(expr->OP_RIGHT); free_expression(expr->OP_RIGHT);
} }

View file

@ -4,6 +4,13 @@
*/ */
/* $Id$ */ /* $Id$ */
/* EXPRESSION DESCRIPTOR */ /* EXPRESSION DESCRIPTOR */
#ifndef EXPR_H_
#define EXPR_H_
#include "parameters.h"
#include "arith.h"
#include "label.h"
#include "flt_arith.h"
/* What we want to define is the struct expr, but since it contains /* What we want to define is the struct expr, but since it contains
a union of various goodies, we define them first; so be patient. a union of various goodies, we define them first; so be patient.
@ -97,3 +104,24 @@ extern struct expr *intexpr(), *new_oper();
/* ALLOCDEF "expr" 20 */ /* ALLOCDEF "expr" 20 */
int rank_of(int oper);
void dot2expr(struct expr **expp);
void idf2expr(register struct expr *expr);
void string2expr(register struct expr **expp, char *str, int len);
void int2expr(struct expr *expr);
void float2expr(register struct expr *expr);
struct expr* intexpr(arith ivalue, int fund);
void fill_int_expr(register struct expr *ex,arith ivalue, int fund);
struct expr *new_oper(struct type *tp, register struct expr *e1, int oper,
register struct expr *e2);
void chk_cst_expr(struct expr **expp);
void init_expression(register struct expr ***eppp, struct expr *expr);
int is_ld_cst(register struct expr *expr);
int is_cp_cst(struct expr *expr);
int is_fp_cst(struct expr *expr);
int is_zero_cst(register struct expr *expr);
void free_expression(register struct expr *expr);
#endif

View file

@ -1,349 +1,354 @@
/* /*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright". * See the copyright notice in the ACK home directory, in the file "Copyright".
*/ */
/* $Id$ */ /* $Id$ */
/* EXPRESSION SYNTAX PARSER */ /* EXPRESSION SYNTAX PARSER */
{ {
#include <alloc.h> #include <alloc.h>
#include "parameters.h" #include "parameters.h"
#include <flt_arith.h> #include <flt_arith.h>
#include "arith.h" #include "arith.h"
#include "LLlex.h" #include "LLlex.h"
#include "type.h" #include "type.h"
#include "label.h" #include "label.h"
#include "expr.h" #include "expr.h"
#include "code.h" #include "code.h"
#include "sizes.h" #include "error.h"
#include "ch3.h"
extern struct expr *intexpr(); #include "ch3bin.h"
int InSizeof = 0; /* inside a sizeof- expression */ #include "ch3mon.h"
int ResultKnown = 0; /* result of the expression is already known */ #include "proto.h"
#include "sizes.h"
/* Since the grammar in the standard is not LL(n), it is modified so that
* it accepts basically the same grammar. This means that there is no 1-1 extern struct expr *intexpr();
* mapping from the grammar in the standard to the grammar given here. int InSizeof = 0; /* inside a sizeof- expression */
* Such is life. int ResultKnown = 0; /* result of the expression is already known */
*/
} /* Since the grammar in the standard is not LL(n), it is modified so that
* it accepts basically the same grammar. This means that there is no 1-1
/* 3.3.1 */ * mapping from the grammar in the standard to the grammar given here.
primary(register struct expr **expp;) : * Such is life.
IDENTIFIER */
{dot2expr(expp);} }
|
constant(expp) /* 3.3.1 */
| primary(register struct expr **expp;) :
string(expp) IDENTIFIER
| {dot2expr(expp);}
'(' expression(expp) ')' |
{ (*expp)->ex_flags |= EX_PARENS; } constant(expp)
; |
string(expp)
|
/* Character string literals that are adjacent tokens '(' expression(expp) ')'
* are concatenated into a single character string { (*expp)->ex_flags |= EX_PARENS; }
* literal. ;
*/
string(register struct expr **expp;)
{ register int i, len; /* Character string literals that are adjacent tokens
register char *str; * are concatenated into a single character string
register int fund; * literal.
} */
: string(register struct expr **expp;)
STRING { register int i, len;
{ str = dot.tk_bts; register char *str;
len = dot.tk_len; register int fund;
fund = dot.tk_fund; }
} :
[ STRING
STRING { str = dot.tk_bts;
{ /* A pasted string keeps the type of the first len = dot.tk_len;
* string literal. fund = dot.tk_fund;
* The pasting of normal strings and wide }
* character strings are stated as having an [
* undefined behaviour. STRING
*/ { /* A pasted string keeps the type of the first
if (dot.tk_fund != fund) * string literal.
warning("illegal pasting of string literals"); * The pasting of normal strings and wide
str = Realloc(str, (unsigned) (--len + dot.tk_len)); * character strings are stated as having an
for (i = 0; i < dot.tk_len; i++) * undefined behaviour.
str[len++] = dot.tk_bts[i]; */
} if (dot.tk_fund != fund)
]* warning("illegal pasting of string literals");
{ string2expr(expp, str, len); } str = Realloc(str, (unsigned) (--len + dot.tk_len));
; for (i = 0; i < dot.tk_len; i++)
str[len++] = dot.tk_bts[i];
/* 3.3.2 */ }
postfix_expression(register struct expr **expp;) ]*
{ int oper; { string2expr(expp, str, len); }
struct expr *e1 = 0; ;
struct idf *idf;
} /* 3.3.2 */
: postfix_expression(register struct expr **expp;)
primary(expp) { int oper;
[ struct expr *e1 = 0;
'[' expression(&e1) ']' struct idf *idf;
{ ch3bin(expp, '[', e1); e1 = 0; } }
| :
'(' parameter_list(&e1)? ')' primary(expp)
{ ch3bin(expp, '(', e1); call_proto(expp); e1 = 0; } [
| '[' expression(&e1) ']'
[ '.' | ARROW ] { oper = DOT; } { ch3bin(expp, '[', e1); e1 = 0; }
identifier(&idf) { ch3sel(expp, oper, idf); } |
| '(' parameter_list(&e1)? ')'
[ { ch3bin(expp, '(', e1); call_proto(expp); e1 = 0; }
PLUSPLUS { oper = POSTINCR; } |
| [ '.' | ARROW ] { oper = DOT; }
MINMIN { oper = POSTDECR; } identifier(&idf) { ch3sel(expp, oper, idf); }
] |
{ ch3incr(expp, oper); } [
]* PLUSPLUS { oper = POSTINCR; }
; |
MINMIN { oper = POSTDECR; }
parameter_list(struct expr **expp;) ]
{struct expr *e1 = 0;} { ch3incr(expp, oper); }
: ]*
assignment_expression(expp) ;
{any2opnd(expp, PARCOMMA);}
[ %persistent parameter_list(struct expr **expp;)
',' {struct expr *e1 = 0;}
assignment_expression(&e1) :
{any2opnd(&e1, PARCOMMA);} assignment_expression(expp)
{ch3bin(expp, PARCOMMA, e1);} {any2opnd(expp, PARCOMMA);}
]* [ %persistent
; ','
assignment_expression(&e1)
%first first_of_type_specifier, type_specifier; {any2opnd(&e1, PARCOMMA);}
{ch3bin(expp, PARCOMMA, e1);}
/* 3.3.3 & 3.3.4 */ ]*
unary(register struct expr **expp;) ;
{struct type *tp; int oper;}
: %first first_of_type_specifier, type_specifier;
%if (first_of_type_specifier(AHEAD) && AHEAD != IDENTIFIER)
cast(&tp) unary(expp) /* 3.3.3 & 3.3.4 */
{ ch3cast(expp, CAST, tp); unary(register struct expr **expp;)
(*expp)->ex_flags |= EX_CAST; {struct type *tp; int oper;}
if (int_size != pointer_size) :
(*expp)->ex_flags &= ~EX_PTRDIFF; %if (first_of_type_specifier(AHEAD) && AHEAD != IDENTIFIER)
} cast(&tp) unary(expp)
| { ch3cast(expp, CAST, tp);
postfix_expression(expp) (*expp)->ex_flags |= EX_CAST;
| if (int_size != pointer_size)
unop(&oper) unary(expp) (*expp)->ex_flags &= ~EX_PTRDIFF;
{ch3mon(oper, expp);} }
| |
size_of(expp) postfix_expression(expp)
; |
unop(&oper) unary(expp)
/* When an identifier is used in a sizeof()-expression, we must stil not {ch3mon(oper, expp);}
* mark it as used. |
* extern int i; .... sizeof(i) .... need not have a definition for i size_of(expp)
*/ ;
size_of(register struct expr **expp;)
{struct type *tp;} /* When an identifier is used in a sizeof()-expression, we must stil not
: * mark it as used.
SIZEOF { InSizeof++; } /* handle (sizeof(sizeof(int))) too */ * extern int i; .... sizeof(i) .... need not have a definition for i
[%if (first_of_type_specifier(AHEAD) && AHEAD != IDENTIFIER) */
cast(&tp) size_of(register struct expr **expp;)
{ {struct type *tp;}
*expp = intexpr(size_of_type(tp, "type"), UNSIGNED); :
(*expp)->ex_flags |= EX_SIZEOF; SIZEOF { InSizeof++; } /* handle (sizeof(sizeof(int))) too */
} [%if (first_of_type_specifier(AHEAD) && AHEAD != IDENTIFIER)
| cast(&tp)
unary(expp) {
{ch3mon(SIZEOF, expp);} *expp = intexpr(size_of_type(tp, "type"), UNSIGNED);
] (*expp)->ex_flags |= EX_SIZEOF;
{ InSizeof--; } }
; |
unary(expp)
/* 3.3.5-3.3.17 */ {ch3mon(SIZEOF, expp);}
/* The set of operators in C is stratified in 15 levels, with level ]
N being treated in RM 7.N (although this is not the standard { InSizeof--; }
anymore). The standard describes this in phrase-structure-grammar, ;
which we are unable to parse. The description that follows comes
from the old C-compiler. /* 3.3.5-3.3.17 */
/* The set of operators in C is stratified in 15 levels, with level
In principle each operator is assigned a rank, ranging N being treated in RM 7.N (although this is not the standard
from 1 to 15. Such an expression can be parsed by a construct anymore). The standard describes this in phrase-structure-grammar,
like: which we are unable to parse. The description that follows comes
binary_expression(int maxrank;) from the old C-compiler.
{int oper;}
: In principle each operator is assigned a rank, ranging
binary_expression(maxrank - 1) from 1 to 15. Such an expression can be parsed by a construct
[%if (rank_of(DOT) <= maxrank) like:
binop(&oper) binary_expression(int maxrank;)
binary_expression(rank_of(oper)-1) {int oper;}
]? :
; binary_expression(maxrank - 1)
except that some call of 'unary' is necessary, depending on the [%if (rank_of(DOT) <= maxrank)
grammar. binop(&oper)
binary_expression(rank_of(oper)-1)
This simple view is marred by three complications: ]?
1. Level 15 (comma operator) is not allowed in many ;
contexts and is different. except that some call of 'unary' is necessary, depending on the
2. Level 13 (conditional operator) is a ternary operator, grammar.
which does not fit this scheme at all.
3. Level 14 (assignment operators) group right-to-left, as This simple view is marred by three complications:
opposed to 2-12, which group left-to-right (or are 1. Level 15 (comma operator) is not allowed in many
immaterial). contexts and is different.
4. The operators in level 14 start with operators in levels 2. Level 13 (conditional operator) is a ternary operator,
2-13 (RM 7.14: The two parts of a compound assignment which does not fit this scheme at all.
operator are separate tokens.) This causes LL1 problems. 3. Level 14 (assignment operators) group right-to-left, as
This forces us to have four rules: opposed to 2-12, which group left-to-right (or are
binary_expression for level 2-12 immaterial).
conditional_expression for level 13 4. The operators in level 14 start with operators in levels
assignment_expression for level 14 and 2-13 (RM 7.14: The two parts of a compound assignment
expression for the most general expression operator are separate tokens.) This causes LL1 problems.
*/ This forces us to have four rules:
binary_expression for level 2-12
binary_expression(int maxrank; struct expr **expp;) conditional_expression for level 13
{int oper, OldResultKnown; struct expr *e1;} assignment_expression for level 14 and
: expression for the most general expression
unary(expp) */
[%while (rank_of(DOT) <= maxrank )
/* '?', '=', and ',' are no binops binary_expression(int maxrank; struct expr **expp;)
*/ {int oper, OldResultKnown; struct expr *e1;}
binop(&oper) :
{ OldResultKnown = ResultKnown; unary(expp)
if (oper == OR || oper == AND) { [%while (rank_of(DOT) <= maxrank )
if (is_cp_cst(*expp) || is_fp_cst(*expp)) { /* '?', '=', and ',' are no binops
if (is_zero_cst(*expp)) { */
if (oper == AND) ResultKnown++; binop(&oper)
} else if (oper == OR) ResultKnown++; { OldResultKnown = ResultKnown;
} if (oper == OR || oper == AND) {
} if (is_cp_cst(*expp) || is_fp_cst(*expp)) {
} if (is_zero_cst(*expp)) {
binary_expression(rank_of(oper)-1, &e1) if (oper == AND) ResultKnown++;
{ } else if (oper == OR) ResultKnown++;
ch3bin(expp, oper, e1); }
ResultKnown = OldResultKnown; }
} }
]* binary_expression(rank_of(oper)-1, &e1)
; {
ch3bin(expp, oper, e1);
/* 3.3.15 */ ResultKnown = OldResultKnown;
conditional_expression(struct expr **expp;) }
{struct expr *e1 = 0, *e2 = 0; int OldResultKnown, ConstExpr=0;} ]*
: ;
/* allow all binary operators */
binary_expression(rank_of('?') - 1, expp) /* 3.3.15 */
[ '?' conditional_expression(struct expr **expp;)
{ OldResultKnown = ResultKnown; {struct expr *e1 = 0, *e2 = 0; int OldResultKnown, ConstExpr=0;}
if (is_cp_cst(*expp) || is_fp_cst(*expp)) { :
ConstExpr++; /* allow all binary operators */
if (is_zero_cst(*expp)) ResultKnown++; binary_expression(rank_of('?') - 1, expp)
} [ '?'
} { OldResultKnown = ResultKnown;
expression(&e1) if (is_cp_cst(*expp) || is_fp_cst(*expp)) {
':' ConstExpr++;
{ if (ConstExpr) { if (is_zero_cst(*expp)) ResultKnown++;
if (OldResultKnown == ResultKnown) ResultKnown++; }
else ResultKnown = OldResultKnown; }
} expression(&e1)
} ':'
conditional_expression(&e2) { if (ConstExpr) {
{ if (OldResultKnown == ResultKnown) ResultKnown++;
ResultKnown = OldResultKnown; else ResultKnown = OldResultKnown;
ch3bin(&e1, ':', e2); }
opnd2test(expp, '?'); }
ch3bin(expp, '?', e1); conditional_expression(&e2)
} {
]? ResultKnown = OldResultKnown;
; ch3bin(&e1, ':', e2);
opnd2test(expp, '?');
/* 3.3.16 */ ch3bin(expp, '?', e1);
assignment_expression(struct expr **expp;) }
{ int oper; ]?
struct expr *e1 = 0; ;
}
: /* 3.3.16 */
conditional_expression(expp) assignment_expression(struct expr **expp;)
[ { int oper;
asgnop(&oper) struct expr *e1 = 0;
assignment_expression(&e1) }
{ch3asgn(expp, oper, e1);} :
| conditional_expression(expp)
empty /* LLgen artefact ??? */ [
] asgnop(&oper)
; assignment_expression(&e1)
{ch3asgn(expp, oper, e1);}
/* 3.3.17 */ |
expression(struct expr **expp;) empty /* LLgen artefact ??? */
{struct expr *e1;} ]
: ;
assignment_expression(expp)
[ ',' /* 3.3.17 */
assignment_expression(&e1) expression(struct expr **expp;)
{ {struct expr *e1;}
ch3bin(expp, ',', e1); :
} assignment_expression(expp)
]* [ ','
; assignment_expression(&e1)
{
unop(int *oper;) : ch3bin(expp, ',', e1);
['*' | '&' | '-' | '+' | '!' | '~' | PLUSPLUS | MINMIN] }
{ if (DOT == '&') DOT = ADDRESSOF; ]*
*oper = DOT; ;
}
; unop(int *oper;) :
['*' | '&' | '-' | '+' | '!' | '~' | PLUSPLUS | MINMIN]
multop: { if (DOT == '&') DOT = ADDRESSOF;
'*' | '/' | '%' *oper = DOT;
; }
;
addop:
'+' | '-' multop:
; '*' | '/' | '%'
;
shiftop:
LEFT | RIGHT addop:
; '+' | '-'
;
relop:
'<' | '>' | LESSEQ | GREATEREQ shiftop:
; LEFT | RIGHT
;
eqop:
EQUAL | NOTEQUAL relop:
; '<' | '>' | LESSEQ | GREATEREQ
;
arithop:
multop | addop | shiftop eqop:
| EQUAL | NOTEQUAL
'&' | '^' | '|' ;
;
arithop:
binop(int *oper;) : multop | addop | shiftop
[ arithop | relop | eqop | AND | OR ] |
{*oper = DOT;} '&' | '^' | '|'
; ;
asgnop(register int *oper;): binop(int *oper;) :
[ '=' | PLUSAB | MINAB | TIMESAB | DIVAB | MODAB [ arithop | relop | eqop | AND | OR ]
| LEFTAB | RIGHTAB | ANDAB | XORAB | ORAB ] {*oper = DOT;}
{ *oper = DOT; } ;
; asgnop(register int *oper;):
[ '=' | PLUSAB | MINAB | TIMESAB | DIVAB | MODAB
constant(struct expr **expp;) : | LEFTAB | RIGHTAB | ANDAB | XORAB | ORAB ]
[ { *oper = DOT; }
INTEGER
| ;
FLOATING
] {dot2expr(expp);} constant(struct expr **expp;) :
; [
INTEGER
/* 3.4 */ |
constant_expression (struct expr **expp;) : FLOATING
conditional_expression(expp) ] {dot2expr(expp);}
{ chk_cst_expr(expp); } ;
;
/* 3.4 */
identifier(struct idf **idfp;) : constant_expression (struct expr **expp;) :
[ IDENTIFIER conditional_expression(expp)
| TYPE_IDENTIFIER { chk_cst_expr(expp); }
] ;
{ *idfp = dot.tk_idf; }
; identifier(struct idf **idfp;) :
[ IDENTIFIER
| TYPE_IDENTIFIER
]
{ *idfp = dot.tk_idf; }
;

View file

@ -23,8 +23,11 @@
#include "align.h" #include "align.h"
#include "Lpars.h" #include "Lpars.h"
#include "field.h" #include "field.h"
#include "util.h"
#include "conversion.h"
#include "eval.h"
arith NewLocal(); /* util.c */
extern arith full_mask[]; /* cstoper.c */ extern arith full_mask[]; /* cstoper.c */
/* Eval_field() evaluates expressions involving bit fields. /* Eval_field() evaluates expressions involving bit fields.
@ -39,9 +42,9 @@ extern arith full_mask[]; /* cstoper.c */
[3] atype: the type in which the bitfield arithmetic is done; [3] atype: the type in which the bitfield arithmetic is done;
and in which bitfields are stored! and in which bitfields are stored!
*/ */
eval_field(expr, code) void eval_field(
struct expr *expr; struct expr *expr,
int code; int code)
{ {
int op = expr->OP_OPER; int op = expr->OP_OPER;
register struct expr *leftop = expr->OP_LEFT; register struct expr *leftop = expr->OP_LEFT;
@ -126,12 +129,12 @@ eval_field(expr, code)
} }
} }
store_field(fd, uns, code, leftop, tmpvar) void store_field(
register struct field *fd; register struct field *fd,
int uns; int uns,
int code; int code,
register struct expr *leftop; register struct expr *leftop,
arith tmpvar; arith tmpvar)
{ {
C_loc(fd->fd_mask); C_loc(fd->fd_mask);
C_and(word_size); C_and(word_size);

View file

@ -2,6 +2,11 @@
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright". * See the copyright notice in the ACK home directory, in the file "Copyright".
*/ */
#ifndef FIELD_H_
#define FIELD_H_
#include "arith.h"
/* $Id$ */ /* $Id$ */
/* FIELD DESCRIPTOR */ /* FIELD DESCRIPTOR */
@ -13,3 +18,20 @@ struct field { /* for field specifiers */
}; };
/* ALLOCDEF "field" 10 */ /* ALLOCDEF "field" 10 */
#ifndef LINT
#ifndef NOBITFIELD
struct expr;
void store_field(register struct field *fd, int uns, int code,
register struct expr *leftop, arith tmpvar);
void eval_field(struct expr *expr, int code);
#endif /* NOBITFIELD */
#endif /* LINT */
#endif /* FIELD_H_ */

View file

@ -10,18 +10,19 @@
#include "parameters.h" #include "parameters.h"
#include <alloc.h> #include <alloc.h>
#include <flt_arith.h> #include <flt_arith.h>
#include "fltcstoper.h"
#include "arith.h" #include "arith.h"
#include "type.h" #include "type.h"
#include "label.h" #include "label.h"
#include "expr.h" #include "expr.h"
#include "sizes.h" #include "sizes.h"
#include "Lpars.h" #include "Lpars.h"
#include "error.h"
extern int ResultKnown; extern int ResultKnown;
extern char *symbol2str(); extern char *symbol2str();
fltcstbin(expp, oper, expr) void fltcstbin(register struct expr **expp, int oper, register struct expr *expr)
register struct expr **expp, *expr;
{ {
/* The operation oper is performed on the constant /* The operation oper is performed on the constant
expressions *expp(ld) and expr(ct), and the result restored in expressions *expp(ld) and expr(ct), and the result restored in

View file

@ -0,0 +1,15 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-07
*
*/
#ifndef FLTCSTOPER_H_
#define FLTCSTOPER_H_
struct expr;
void fltcstbin(register struct expr **expp, int oper, register struct expr *expr);
#endif /* FLTCSTOPER_H_ */

View file

@ -25,6 +25,12 @@
#include "declar.h" #include "declar.h"
#include "decspecs.h" #include "decspecs.h"
#include "sizes.h" #include "sizes.h"
#include "print.h"
#include "util.h"
#include "stab.h"
#include "code.h"
#include "error.h"
#include "ch3.h"
#include "Lpars.h" #include "Lpars.h"
extern char options[]; extern char options[];
@ -37,91 +43,92 @@ extern char *symbol2str();
#include <idf_pkg.body> #include <idf_pkg.body>
void global_redecl();
struct idf *
gen_idf() struct idf *gen_idf(void)
{ {
/* A new idf is created out of nowhere, to serve as an /* A new idf is created out of nowhere, to serve as an
anonymous name. anonymous name.
*/ */
static int name_cnt; static int name_cnt;
char *s = Malloc(strlen(dot.tk_file) + 50); char *s = Malloc(strlen(dot.tk_file) + 50);
sprint(s, "#%d in %s, line %u", sprint(s, "#%d in %s, line %u", ++name_cnt, dot.tk_file, dot.tk_line);
++name_cnt, dot.tk_file, dot.tk_line); s = Realloc(s, strlen(s) + 1);
s = Realloc(s, strlen(s)+1);
return str2idf(s, 0); return str2idf(s, 0);
} }
int int is_anon_idf(struct idf *idf)
is_anon_idf(idf)
struct idf *idf;
{ {
return idf->id_text[0] == '#'; return idf->id_text[0] == '#';
} }
declare_idf(ds, dc, lvl) void declare_idf(struct decspecs *ds, struct declarator *dc, int lvl)
struct decspecs *ds;
struct declarator *dc;
{ {
/* The identifier inside dc is declared on the level lvl, with /* The identifier inside dc is declared on the level lvl, with
properties deduced from the decspecs ds and the declarator properties deduced from the decspecs ds and the declarator
dc. dc.
The level is given explicitly to be able to insert, e.g., The level is given explicitly to be able to insert, e.g.,
labels on the outermost level inside the function. labels on the outermost level inside the function.
This routine implements the rich semantics of C This routine implements the rich semantics of C
declarations. declarations.
*/ */
register struct idf *idf = dc->dc_idf; register struct idf *idf = dc->dc_idf;
register int sc = ds->ds_sc; register int sc = ds->ds_sc;
/* This local copy is essential: /* This local copy is essential:
char b(), c; char b(), c;
makes b GLOBAL and c AUTO. makes b GLOBAL and c AUTO.
*/ */
register struct def *def = idf->id_def; /* may be NULL */ register struct def *def = idf->id_def; /* may be NULL */
register struct type *type; register struct type *type;
struct stack_level *stl = stack_level_of(lvl); struct stack_level *stl = stack_level_of(lvl);
char formal_array = 0; char formal_array = 0;
/* determine the present type */ /* determine the present type */
if (ds->ds_type == 0) { if (ds->ds_type == 0)
{
/* at the L_FORMAL1 level there is no type specified yet /* at the L_FORMAL1 level there is no type specified yet
*/ */
assert(lvl == L_FORMAL1); assert(lvl == L_FORMAL1);
type = int_type; /* may change at L_FORMAL2 */ type = int_type; /* may change at L_FORMAL2 */
} }
else { else
{
/* combine the decspecs and the declarator into one type */ /* combine the decspecs and the declarator into one type */
type = declare_type(ds->ds_type, dc); type = declare_type(ds->ds_type, dc);
if (type->tp_size <= (arith)0 && if (type->tp_size <= (arith) 0 && actual_declaration(sc, type))
actual_declaration(sc, type)) { {
if (type->tp_size == (arith) -1) { if (type->tp_size == (arith) -1)
{
/* the type is not yet known, /* the type is not yet known,
but it has to be: but it has to be:
*/ */
if (type->tp_fund != VOID) { if (type->tp_fund != VOID)
if (level != L_GLOBAL) {
error("unknown %s-type", if (level != L_GLOBAL)
symbol2str(type->tp_fund)); error("unknown %s-type", symbol2str(type->tp_fund));
} else error("void is not a complete type"); }
else
error("void is not a complete type");
} }
else strict("%s has size 0", idf->id_text); else
strict("%s has size 0", idf->id_text);
} }
} }
/* some additional work for formal definitions */ /* some additional work for formal definitions */
if (lvl == L_FORMAL2) { if (lvl == L_FORMAL2)
switch (type->tp_fund) { {
switch (type->tp_fund)
{
case FUNCTION: case FUNCTION:
warning("%s is a function; cannot be formal", warning("%s is a function; cannot be formal", idf->id_text);
idf->id_text); type = construct_type(POINTER, type, 0, (arith) 0,
type = construct_type(POINTER, type, 0, (arith)0, NO_PROTO);
NO_PROTO);
break; break;
case ARRAY: /* 3.7.1 */ case ARRAY: /* 3.7.1 */
type = construct_type(POINTER, type->tp_up, 0, (arith)0, type = construct_type(POINTER, type->tp_up, 0, (arith) 0,
NO_PROTO); NO_PROTO);
formal_array = 1; formal_array = 1;
break; break;
case FLOAT: case FLOAT:
@ -135,72 +142,77 @@ declare_idf(ds, dc, lvl)
} }
} }
/* The tests on types, postponed from do_decspecs(), can now /* The tests on types, postponed from do_decspecs(), can now
be performed. be performed.
*/ */
/* update the storage class */ /* update the storage class */
if (type && type->tp_fund == FUNCTION) { if (type && type->tp_fund == FUNCTION)
if (lvl != L_GLOBAL) { /* 3.5.1 */ {
if (lvl != L_GLOBAL)
{ /* 3.5.1 */
if (sc == 0) if (sc == 0)
sc = GLOBAL; sc = GLOBAL;
else if (sc != EXTERN && sc != TYPEDEF) { else if (sc != EXTERN && sc != TYPEDEF)
error("illegal storage class %s for function with block-scope" {
, symbol2str(sc)); error("illegal storage class %s for function with block-scope",
symbol2str(sc));
ds->ds_sc = sc = EXTERN; ds->ds_sc = sc = EXTERN;
} }
} }
else if (sc == 0) else if (sc == 0)
sc = GLOBAL; sc = GLOBAL;
} }
else /* non-FUNCTION */ else /* non-FUNCTION */
if (sc == 0) if (sc == 0)
sc = lvl == L_GLOBAL ? GLOBAL sc = lvl == L_GLOBAL ? GLOBAL :
: lvl == L_FORMAL1 || lvl == L_FORMAL2 ? FORMAL lvl == L_FORMAL1 || lvl == L_FORMAL2 ? FORMAL : AUTO;
: AUTO;
#ifdef LINT #ifdef LINT
check_hiding(idf, lvl, sc); /* of some idf by this idf */ check_hiding(idf, lvl, sc); /* of some idf by this idf */
#endif /* LINT */ #endif /* LINT */
if (def && lvl == L_LOCAL && def->df_level == L_FORMAL2) { if (def && lvl == L_LOCAL && def->df_level == L_FORMAL2)
{
error("%s redeclared", idf->id_text); error("%s redeclared", idf->id_text);
} }
if (def && if (def
( def->df_level == lvl || && (def->df_level == lvl || (lvl != L_GLOBAL && def->df_level > lvl)
( lvl != L_GLOBAL && def->df_level > lvl ) || || (lvl == L_GLOBAL && def->df_level == L_PROTO && def->next
(lvl == L_GLOBAL && def->next->df_level == L_GLOBAL)))
&& def->df_level == L_PROTO {
&& def->next && def->next->df_level == L_GLOBAL)
)) {
/* There is already a declaration for idf on this /* There is already a declaration for idf on this
level, or even more inside. level, or even more inside.
The rules differ for different levels. The rules differ for different levels.
*/ */
switch (lvl) { switch (lvl)
{
case L_GLOBAL: case L_GLOBAL:
global_redecl(idf, sc, type); global_redecl(idf, sc, type);
def->df_file = idf->id_file; def->df_file = idf->id_file;
def->df_line = idf->id_line; def->df_line = idf->id_line;
break; break;
case L_FORMAL1: /* formal declaration */ case L_FORMAL1: /* formal declaration */
error("formal %s redeclared", idf->id_text); error("formal %s redeclared", idf->id_text);
break; break;
case L_FORMAL2: /* formal definition */ case L_FORMAL2: /* formal definition */
default: /* local */ default: /* local */
if (sc != EXTERN) error("%s redeclared", idf->id_text); if (sc != EXTERN)
error("%s redeclared", idf->id_text);
break; break;
} }
} }
else /* the idf is unknown on this level */ else /* the idf is unknown on this level */
if (lvl == L_FORMAL2 && sc != ENUM && good_formal(def, idf)) { if (lvl == L_FORMAL2 && sc != ENUM && good_formal(def, idf))
{
/* formal declaration, update only */ /* formal declaration, update only */
def->df_type = type; def->df_type = type;
def->df_formal_array = formal_array; def->df_formal_array = formal_array;
def->df_sc = sc; def->df_sc = sc;
def->df_level = L_FORMAL2; /* CJ */ def->df_level = L_FORMAL2; /* CJ */
def->df_file = idf->id_file; def->df_file = idf->id_file;
def->df_line = idf->id_line; def->df_line = idf->id_line;
} }
else { /* fill in the def block */ else
{ /* fill in the def block */
register struct def *newdef = new_def(); register struct def *newdef = new_def();
newdef->next = def; newdef->next = def;
@ -218,28 +230,27 @@ declare_idf(ds, dc, lvl)
update_ahead(idf); update_ahead(idf);
stack_idf(idf, stl); stack_idf(idf, stl);
/* We now calculate the address. /* We now calculate the address.
Globals have names and don't get addresses, they Globals have names and don't get addresses, they
get numbers instead (through data_label()). get numbers instead (through data_label()).
Formals are handled by declare_formals(). Formals are handled by declare_formals().
So here we hand out local addresses only. So here we hand out local addresses only.
*/ */
if (lvl >= L_LOCAL) { if (lvl >= L_LOCAL)
{
assert(sc); assert(sc);
switch (sc) { switch (sc)
{
case REGISTER: case REGISTER:
case AUTO: case AUTO:
if (type->tp_size == (arith)-1 if (type->tp_size == (arith) -1 && type->tp_fund != ARRAY)
&& type->tp_fund != ARRAY) { {
error("size of local %s unknown", error("size of local %s unknown", idf->id_text);
idf->id_text); /** type = idf->id_def->df_type = int_type; **/
/** type = idf->id_def->df_type = int_type; **/
} }
if (type->tp_size != (arith) -1) { if (type->tp_size != (arith) -1)
newdef->df_address = {
NewLocal(type->tp_size, newdef->df_address = NewLocal(type->tp_size, type->tp_align,
type->tp_align, regtype(type), sc);
regtype(type),
sc);
} }
break; break;
case STATIC: case STATIC:
@ -250,21 +261,19 @@ declare_idf(ds, dc, lvl)
} }
} }
int int actual_declaration(int sc, struct type *tp)
actual_declaration(sc, tp)
int sc;
struct type *tp;
{ {
/* An actual_declaration needs space, right here and now. /* An actual_declaration needs space, right here and now.
*/ */
register int fund = tp->tp_fund; register int fund = tp->tp_fund;
if (sc == ENUM || sc == TYPEDEF) /* virtual declarations */ if (sc == ENUM || sc == TYPEDEF) /* virtual declarations */
return 0; return 0;
if (fund == FUNCTION || fund == ARRAY) if (fund == FUNCTION || fund == ARRAY)
/* allocation solved in other ways */ /* allocation solved in other ways */
return 0; return 0;
if (sc == EXTERN && fund == VOID) { if (sc == EXTERN && fund == VOID)
{
/* strange, but should be accepted */ /* strange, but should be accepted */
return 0; return 0;
} }
@ -272,51 +281,59 @@ actual_declaration(sc, tp)
return 1; return 1;
} }
void void global_redecl(register struct idf *idf, int new_sc, struct type *tp)
global_redecl(idf, new_sc, tp)
register struct idf *idf;
struct type *tp;
{ {
/* A global identifier may be declared several times, /* A global identifier may be declared several times,
provided the declarations do not conflict; they might provided the declarations do not conflict; they might
conflict in type (or supplement each other in the case of conflict in type (or supplement each other in the case of
an array) or they might conflict or supplement each other an array) or they might conflict or supplement each other
in storage class. in storage class.
*/ */
register struct def *def = idf->id_def; register struct def *def = idf->id_def;
while (def->df_level != L_GLOBAL) def = def->next; while (def->df_level != L_GLOBAL)
if (!equal_type(tp, def->df_type, 0, 1)) { def = def->next;
if (!equal_type(tp, def->df_type, 0, 1))
{
error("redeclaration of %s with different type", idf->id_text); error("redeclaration of %s with different type", idf->id_text);
return; return;
} else update_proto(tp, def->df_type); }
if (tp->tp_fund == ARRAY) { else
update_proto(tp, def->df_type);
if (tp->tp_fund == ARRAY)
{
/* Multiple array declaration; this may be interesting */ /* Multiple array declaration; this may be interesting */
if (tp->tp_size < 0) { /* new decl has [] */ if (tp->tp_size < 0)
{ /* new decl has [] */
/* nothing new */ /* nothing new */
} else }
if (def->df_type->tp_size < 0) { /* old decl has [] */ else if (def->df_type->tp_size < 0)
{ /* old decl has [] */
def->df_type = tp; def->df_type = tp;
} }
} if (tp->tp_fund == FUNCTION && new_sc == GLOBAL) { }
if (tp->tp_fund == FUNCTION && new_sc == GLOBAL)
{
/* see 3.1.2.2 */ /* see 3.1.2.2 */
new_sc = EXTERN; new_sc = EXTERN;
} }
/* Now we may be able to update the storage class. /* Now we may be able to update the storage class.
Clean out this mess as soon as we know all the possibilities Clean out this mess as soon as we know all the possibilities
for new_sc. for new_sc.
For now we have: For now we have:
EXTERN: we have seen the word "extern" EXTERN: we have seen the word "extern"
GLOBAL: the item was declared on the outer GLOBAL: the item was declared on the outer
level, without either "extern" or level, without either "extern" or
"static". "static".
STATIC: we have seen the word "static" STATIC: we have seen the word "static"
*/ */
switch (def->df_sc) { /* the old storage class */ switch (def->df_sc)
{ /* the old storage class */
case EXTERN: case EXTERN:
switch (new_sc) { /* the new storage class */ switch (new_sc)
{ /* the new storage class */
case STATIC: case STATIC:
warning("%s redeclared static", idf->id_text); warning("%s redeclared static", idf->id_text);
/* fallthrough */ /* fallthrough */
@ -331,8 +348,9 @@ global_redecl(idf, new_sc, tp)
} }
break; break;
case GLOBAL: case GLOBAL:
switch (new_sc) { /* the new storage class */ switch (new_sc)
case STATIC: /* linkage disagreement */ { /* the new storage class */
case STATIC: /* linkage disagreement */
warning("%s redeclared static", idf->id_text); warning("%s redeclared static", idf->id_text);
def->df_sc = new_sc; def->df_sc = new_sc;
/* fallthrough */ /* fallthrough */
@ -345,8 +363,9 @@ global_redecl(idf, new_sc, tp)
} }
break; break;
case STATIC: case STATIC:
switch (new_sc) { /* the new storage class */ switch (new_sc)
case GLOBAL: /* linkage disagreement */ { /* the new storage class */
case GLOBAL: /* linkage disagreement */
case EXTERN: case EXTERN:
warning("%s is already declared static", idf->id_text); warning("%s is already declared static", idf->id_text);
/* fallthrough */ /* fallthrough */
@ -367,142 +386,147 @@ global_redecl(idf, new_sc, tp)
} }
} }
int int good_formal(register struct def *def, register struct idf *idf)
good_formal(def, idf)
register struct def *def;
register struct idf *idf;
{ {
/* Succeeds if def is a proper L_FORMAL1 definition and /* Succeeds if def is a proper L_FORMAL1 definition and
gives an error message otherwise. gives an error message otherwise.
*/ */
if (!def || def->df_level != L_FORMAL1) { /* not in parameter list */ if (!def || def->df_level != L_FORMAL1)
{ /* not in parameter list */
if (!is_anon_idf(idf)) if (!is_anon_idf(idf))
error("%s not in parameter list", idf->id_text); error("%s not in parameter list", idf->id_text);
return 0; return 0;
} }
assert(def->df_sc == FORMAL); /* CJ */ assert(def->df_sc == FORMAL); /* CJ */
return 1; return 1;
} }
declare_params(dc) void declare_params(struct declarator *dc)
struct declarator *dc;
{ {
/* Declares the formal parameters if they exist. /* Declares the formal parameters if they exist.
*/ */
register struct formal *fm = dc->dc_formal; register struct formal *fm = dc->dc_formal;
while (fm) { while (fm)
{
declare_parameter(fm->fm_idf); declare_parameter(fm->fm_idf);
fm = fm->next; fm = fm->next;
} }
} }
void void idf_initialized(register struct idf *idf)
idf_initialized(idf)
register struct idf *idf;
{ {
/* The topmost definition of idf is set to initialized. /* The topmost definition of idf is set to initialized.
*/ */
register struct def *def = idf->id_def; /* the topmost */ register struct def *def = idf->id_def; /* the topmost */
while (def->df_level <= L_PROTO) def = def->next; while (def->df_level <= L_PROTO)
def = def->next;
if (def->df_initialized) if (def->df_initialized)
error("multiple initialization of %s", idf->id_text); error("multiple initialization of %s", idf->id_text);
if (def->df_sc == TYPEDEF) { if (def->df_sc == TYPEDEF)
{
error("typedef cannot be initialized"); error("typedef cannot be initialized");
return; return;
} }
def->df_initialized = 1; def->df_initialized = 1;
} }
declare_parameter(idf) void declare_parameter(struct idf *idf)
struct idf *idf;
{ {
/* idf is declared as a formal. /* idf is declared as a formal.
*/ */
add_def(idf, FORMAL, int_type, level); add_def(idf, FORMAL, int_type, level);
} }
declare_enum(tp, idf, l) void declare_enum(struct type *tp, struct idf *idf, arith l)
struct type *tp;
struct idf *idf;
arith l;
{ {
/* idf is declared as an enum constant with value l. /* idf is declared as an enum constant with value l.
*/ */
add_def(idf, ENUM, tp, level); add_def(idf, ENUM, tp, level);
idf->id_def->df_address = l; idf->id_def->df_address = l;
} }
void void check_formals(struct idf *idf, struct declarator *dc)
check_formals(idf, dc)
struct idf *idf;
struct declarator *dc;
{ {
register struct formal *fm = dc->dc_formal; register struct formal *fm = dc->dc_formal;
register struct proto *pl = idf->id_def->df_type->tp_proto; register struct proto *pl = idf->id_def->df_type->tp_proto;
register struct decl_unary *du = dc->dc_decl_unary; register struct decl_unary *du = dc->dc_decl_unary;
if (!du) { /* error or typdef'ed function */ if (!du)
{ /* error or typdef'ed function */
error("illegal definition of %s", idf->id_text); error("illegal definition of %s", idf->id_text);
return; return;
} }
while (du while (du
&& (du->du_fund != FUNCTION && (du->du_fund != FUNCTION || du->next != (struct decl_unary *) 0))
|| du->next != (struct decl_unary *) 0)) { {
du = du->next; du = du->next;
} }
if (!du) return; /* terrible error, signalled earlier */ if (!du)
return; /* terrible error, signalled earlier */
if (du->du_proto) return; if (du->du_proto)
return;
if (pl) { if (pl)
{
/* Don't give a warning about an old-style definition, /* Don't give a warning about an old-style definition,
* since the arguments will be checked anyway. * since the arguments will be checked anyway.
*/ */
if (pl->pl_flag & PL_ELLIPSIS) { if (pl->pl_flag & PL_ELLIPSIS)
if (!(du->du_proto) && !(pl->pl_flag & PL_ERRGIVEN)) {
error("ellipsis terminator in previous declaration"); if (!(du->du_proto) && !(pl->pl_flag & PL_ERRGIVEN))
pl = pl->next; error("ellipsis terminator in previous declaration");
pl = pl->next;
} }
else if (pl->pl_flag & PL_VOID) { else if (pl->pl_flag & PL_VOID)
pl = pl->next; /* should be 0 */ {
pl = pl->next; /* should be 0 */
} }
while(fm && pl) { while (fm && pl)
if (!equal_type(promoted_type(fm->fm_idf->id_def->df_type) {
, pl->pl_type, -1, 1)) { if (!equal_type(promoted_type(fm->fm_idf->id_def->df_type),
if (!(pl->pl_flag & PL_ERRGIVEN)) pl->pl_type, -1, 1))
error("incorrect type for parameter %s" {
, fm->fm_idf->id_text); if (!(pl->pl_flag & PL_ERRGIVEN))
pl->pl_flag |= PL_ERRGIVEN; error("incorrect type for parameter %s",
} fm->fm_idf->id_text);
fm = fm->next; pl->pl_flag |= PL_ERRGIVEN;
pl = pl->next; }
fm = fm->next;
pl = pl->next;
} }
if (pl || fm) { if (pl || fm)
{
error("incorrect number of parameters"); error("incorrect number of parameters");
} }
} else { /* make a pseudo-prototype */ }
else
{ /* make a pseudo-prototype */
register struct proto *lpl = new_proto(); register struct proto *lpl = new_proto();
if (!options['o']) if (!options['o'])
warning("'%s' old-fashioned function definition" warning("'%s' old-fashioned function definition",
, dc->dc_idf->id_text); dc->dc_idf->id_text);
while (fm) { while (fm)
if (pl == 0) pl = lpl; {
else { if (pl == 0)
pl = lpl;
else
{
lpl->next = new_proto(); lpl->next = new_proto();
lpl = lpl->next; lpl = lpl->next;
} }
lpl->pl_flag = PL_FORMAL; lpl->pl_flag = PL_FORMAL;
lpl->pl_idf = fm->fm_idf; lpl->pl_idf = fm->fm_idf;
lpl->pl_type = lpl->pl_type = promoted_type(fm->fm_idf->id_def->df_type);
promoted_type(fm->fm_idf->id_def->df_type);
fm = fm->next; fm = fm->next;
} }
if (pl == 0) { /* make func(void) */ if (pl == 0)
{ /* make func(void) */
pl = lpl; pl = lpl;
pl->pl_type = void_type; pl->pl_type = void_type;
pl->pl_flag = PL_FORMAL | PL_VOID; pl->pl_flag = PL_FORMAL | PL_VOID;
@ -513,26 +537,26 @@ check_formals(idf, dc)
dc->dc_formal = 0; dc->dc_formal = 0;
} }
declare_formals(idf, fp) void declare_formals(struct idf *idf, arith *fp)
struct idf *idf;
arith *fp;
{ {
/* Declares those formals as int that haven't been declared /* Declares those formals as int that haven't been declared
by the user. by the user.
An address is assigned to each formal parameter. An address is assigned to each formal parameter.
The total size of the formals is returned in *fp; The total size of the formals is returned in *fp;
*/ */
register struct stack_entry *se = stack_level_of(L_FORMAL1)->sl_entry; register struct stack_entry *se = stack_level_of(L_FORMAL1)->sl_entry;
arith f_offset = (arith)0; arith f_offset = (arith) 0;
register int nparams = 0; register int nparams = 0;
int hasproto; int hasproto;
struct def *df = idf->id_def; struct def *df = idf->id_def;
/* When one of the formals has the same name as the function, /* When one of the formals has the same name as the function,
it hides the function def. Get it. it hides the function def. Get it.
*/ */
while (se) { while (se)
if (se->se_idf == idf) { {
if (se->se_idf == idf)
{
df = df->next; df = df->next;
break; break;
} }
@ -540,49 +564,53 @@ declare_formals(idf, fp)
} }
se = stack_level_of(L_FORMAL1)->sl_entry; se = stack_level_of(L_FORMAL1)->sl_entry;
hasproto = df->df_type->tp_proto != 0; hasproto = df->df_type->tp_proto != 0;
#ifdef DEBUG #ifdef DEBUG
if (options['t']) if (options['t'])
dumpidftab("start declare_formals", 0); dumpidftab("start declare_formals", 0);
#endif /* DEBUG */ #endif /* DEBUG */
if (is_struct_or_union(df->df_type->tp_up->tp_fund)) { if (is_struct_or_union(df->df_type->tp_up->tp_fund))
{
/* create space for address of return value */ /* create space for address of return value */
f_offset = pointer_size; f_offset = pointer_size;
} }
while (se) { while (se)
{
df = se->se_idf->id_def; df = se->se_idf->id_def;
/* this stacklevel may also contain tags. ignore them */ /* this stacklevel may also contain tags. ignore them */
if (!df || df->df_level < L_FORMAL1 ) { if (!df || df->df_level < L_FORMAL1)
{
se = se->next; se = se->next;
continue; continue;
} }
df->df_address = f_offset; df->df_address = f_offset;
/* the alignment convention for parameters is: align on /* the alignment convention for parameters is: align on
word boundaries, i.e. take care that the following word boundaries, i.e. take care that the following
parameter starts on a new word boundary. parameter starts on a new word boundary.
*/ */
if (! hasproto if (!hasproto && df->df_type->tp_fund == FLOAT
&& df->df_type->tp_fund == FLOAT && df->df_type->tp_size != double_size)
&& df->df_type->tp_size != double_size) { {
f_offset = align(f_offset + double_size, (int) word_size); f_offset = align(f_offset + double_size, (int) word_size);
} }
else f_offset = align(f_offset + df->df_type->tp_size, (int) word_size); else
f_offset = align(f_offset + df->df_type->tp_size, (int) word_size);
RegisterAccount(df->df_address, df->df_type->tp_size, RegisterAccount(df->df_address, df->df_type->tp_size,
regtype(df->df_type), regtype(df->df_type), df->df_sc);
df->df_sc);
/* cvt int to char or short and double to float, if necessary /* cvt int to char or short and double to float, if necessary
*/ */
formal_cvt(hasproto, df); formal_cvt(hasproto, df);
df->df_level = L_FORMAL2; /* CJ */ df->df_level = L_FORMAL2; /* CJ */
if (nparams++ >= STDC_NPARAMS) if (nparams++ >= STDC_NPARAMS)
strict("number of formal parameters exceeds ANSI limit"); strict("number of formal parameters exceeds ANSI limit");
#ifdef DBSYMTAB #ifdef DBSYMTAB
if (options['g']) { if (options['g'])
{
stb_string(df, FORMAL, se->se_idf->id_text); stb_string(df, FORMAL, se->se_idf->id_text);
} }
#endif /* DBSYMTAB */ #endif /* DBSYMTAB */
@ -591,11 +619,10 @@ declare_formals(idf, fp)
*fp = f_offset; *fp = f_offset;
} }
int int regtype(struct type *tp)
regtype(tp)
struct type *tp;
{ {
switch(tp->tp_fund) { switch (tp->tp_fund)
{
case INT: case INT:
case LONG: case LONG:
return reg_any; return reg_any;
@ -609,18 +636,15 @@ regtype(tp)
return -1; return -1;
} }
add_def(idf, sc, tp, lvl) void add_def(struct idf *idf, int sc, struct type *tp, int lvl)
struct idf *idf;
struct type *tp;
int lvl;
int sc;
{ {
/* The identifier idf is declared on level lvl with storage /* The identifier idf is declared on level lvl with storage
class sc and type tp, through a faked C declaration. class sc and type tp, through a faked C declaration.
This is probably the wrong way to structure the problem, This is probably the wrong way to structure the problem,
but it will have to do for the time being. but it will have to do for the time being.
*/ */
struct decspecs Ds; struct declarator Dc; struct decspecs Ds;
struct declarator Dc;
Ds = null_decspecs; Ds = null_decspecs;
Ds.ds_type = tp; Ds.ds_type = tp;
@ -630,25 +654,24 @@ add_def(idf, sc, tp, lvl)
declare_idf(&Ds, &Dc, lvl); declare_idf(&Ds, &Dc, lvl);
} }
update_ahead(idf) void update_ahead(register struct idf *idf)
register struct idf *idf;
{ {
/* The tk_symb of the token ahead is updated in the light of new /* The tk_symb of the token ahead is updated in the light of new
information about the identifier idf. information about the identifier idf.
*/ */
register int tk_symb = AHEAD; register int tk_symb = AHEAD;
if ( (tk_symb == IDENTIFIER || tk_symb == TYPE_IDENTIFIER) && if ((tk_symb == IDENTIFIER || tk_symb == TYPE_IDENTIFIER)
ahead.tk_idf == idf && ahead.tk_idf == idf)
)
AHEAD = idf->id_def && idf->id_def->df_sc == TYPEDEF ? AHEAD = idf->id_def && idf->id_def->df_sc == TYPEDEF ?
TYPE_IDENTIFIER : IDENTIFIER; TYPE_IDENTIFIER :
IDENTIFIER;
} }
free_formals(fm) void free_formals(register struct formal *fm)
register struct formal *fm;
{ {
while (fm) { while (fm)
{
struct formal *tmp = fm->next; struct formal *tmp = fm->next;
free_formal(fm); free_formal(fm);

View file

@ -2,10 +2,15 @@
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright". * See the copyright notice in the ACK home directory, in the file "Copyright".
*/ */
#ifndef IDF_H_
#define IDF_H_
/* $Id$ */ /* $Id$ */
/* IDENTIFIER DESCRIPTOR */ /* IDENTIFIER DESCRIPTOR */
#include "parameters.h" #include "parameters.h"
#include "arith.h"
struct id_u { struct id_u {
int idd_reserved; /* non-zero for reserved words */ int idd_reserved; /* non-zero for reserved words */
@ -33,4 +38,28 @@ struct id_u {
#include <idf_pkg.spec> #include <idf_pkg.spec>
extern int level; extern int level;
extern struct idf *gen_idf();
struct decspecs;
struct declarator;
struct type;
struct formal;
struct idf *gen_idf(void);
int is_anon_idf(struct idf *idf);
void declare_idf(struct decspecs *ds, struct declarator *dc, int lvl);
int actual_declaration(int sc, struct type *tp);
void global_redecl(register struct idf *idf, int new_sc, struct type *tp);
int good_formal(register struct def *def, register struct idf *idf);
void declare_params(struct declarator *dc);
void idf_initialized(register struct idf *idf);
void declare_parameter(struct idf *idf);
void declare_enum(struct type *tp, struct idf *idf, arith l);
void check_formals(struct idf *idf, struct declarator *dc);
void declare_formals(struct idf *idf, arith *fp);
int regtype(struct type *tp);
void add_def(struct idf *idf, int sc, struct type *tp, int lvl);
void update_ahead(register struct idf *idf);
void free_formals(register struct formal *fm);
#endif

View file

@ -10,6 +10,7 @@
#include <string.h> #include <string.h>
#include "file_info.h" #include "file_info.h"
#include "input.h" #include "input.h"
#include "error.h"
#define INP_PUSHBACK 3 #define INP_PUSHBACK 3
#define INP_TYPE struct file_info #define INP_TYPE struct file_info
@ -20,14 +21,14 @@ struct file_info finfo;
int NoUnstack; int NoUnstack;
AtEoIT() int AtEoIT(void)
{ {
return 0; return 0;
} }
extern char *source; extern char *source;
AtEoIF() int AtEoIF(void)
{ {
if (NoUnstack) lexerror("unexpected EOF"); if (NoUnstack) lexerror("unexpected EOF");
return 0; return 0;

View file

@ -12,4 +12,4 @@
#define UnGetChar() ((LexSave != EOI) ? ChPushBack(LexSave) : 0) #define UnGetChar() ((LexSave != EOI) ? ChPushBack(LexSave) : 0)
extern int LexSave; /* last character read by GetChar */ extern int LexSave; /* last character read by GetChar */
extern int GetChar(); /* character input, with trigraph parsing */

File diff suppressed because it is too large Load diff

View file

@ -14,11 +14,12 @@
#include "def.h" #include "def.h"
#include "type.h" #include "type.h"
#include "stack.h" #include "stack.h"
#include "error.h"
extern char options[]; extern char options[];
enter_label(idf, defining) void enter_label(register struct idf *idf, int defining)
register struct idf *idf;
{ {
/* The identifier idf is entered as a label. If it is new, /* The identifier idf is entered as a label. If it is new,
it is entered into the idf list with the largest possible it is entered into the idf list with the largest possible
@ -45,8 +46,7 @@ enter_label(idf, defining)
def->df_initialized = 1; def->df_initialized = 1;
} }
unstack_label(idf) void unstack_label(register struct idf *idf)
register struct idf *idf;
{ {
/* The scope in which the label idf occurred is left. /* The scope in which the label idf occurred is left.
*/ */

View file

@ -4,6 +4,8 @@
*/ */
/* $Id$ */ /* $Id$ */
/* L A B E L D E F I N I T I O N */ /* L A B E L D E F I N I T I O N */
#ifndef LABEL_H_
#define LABEL_H_
#include <em_label.h> /* obtain definition of "label" */ #include <em_label.h> /* obtain definition of "label" */
@ -26,3 +28,10 @@ extern label datlab_count;
not be there, and if it is there, it may be from a not be there, and if it is there, it may be from a
declaration or another application. declaration or another application.
*/ */
struct idf;
void enter_label(register struct idf *idf, int defining);
void unstack_label(register struct idf *idf);
#endif /* LABEL_H_ */

View file

@ -23,7 +23,13 @@
#include "specials.h" #include "specials.h"
#include "sizes.h" #include "sizes.h"
#include "align.h" #include "align.h"
#include "stack.h"
#include "macro.h" #include "macro.h"
#include "options.h"
#include "error.h"
#include "code.h"
#include "cstoper.h"
#include "tokenname.h"
extern struct tokenname tkidf[]; extern struct tokenname tkidf[];
extern char *symbol2str(); extern char *symbol2str();
@ -34,7 +40,15 @@ struct sp_id special_ids[] = {
{0, 0} {0, 0}
}; };
void dependency(); void compile(int argc, char *argv[]);
static void init(void);
static void init_specials(register struct sp_id *si);
#ifdef DEBUG
void Info(void);
#endif
extern void C_program(void); /* program.c */
#ifndef NOCROSS #ifndef NOCROSS
arith arith
@ -63,8 +77,7 @@ int
char *prog_name; char *prog_name;
main(argc, argv) int main(int argc, char *argv[])
char *argv[];
{ {
/* parse and interpret the command line options */ /* parse and interpret the command line options */
prog_name = argv[0]; prog_name = argv[0];
@ -104,8 +117,7 @@ char *source = 0;
char *nmlist = 0; char *nmlist = 0;
#endif /* GEN_NM_LIST */ #endif /* GEN_NM_LIST */
compile(argc, argv) void compile(int argc, char *argv[])
char *argv[];
{ {
char *result; char *result;
#ifndef LINT #ifndef LINT
@ -190,7 +202,7 @@ compile(argc, argv)
} }
} }
init() static void init(void)
{ {
init_cst(); /* initialize variables of "cstoper.c" */ init_cst(); /* initialize variables of "cstoper.c" */
reserve(tkidf); /* mark the C reserved words as such */ reserve(tkidf); /* mark the C reserved words as such */
@ -255,8 +267,7 @@ init()
stack_level(); stack_level();
} }
init_specials(si) static void init_specials(register struct sp_id *si)
register struct sp_id *si;
{ {
while (si->si_identifier) { while (si->si_identifier) {
struct idf *idf = str2idf(si->si_identifier, 0); struct idf *idf = str2idf(si->si_identifier, 0);
@ -269,7 +280,7 @@ init_specials(si)
} }
#ifdef DEBUG #ifdef DEBUG
Info() void Info(void)
{ {
extern int cnt_string_cst, cnt_formal, extern int cnt_string_cst, cnt_formal,
cnt_decl_unary, cnt_def, cnt_expr, cnt_field, cnt_decl_unary, cnt_def, cnt_expr, cnt_field,
@ -301,14 +312,12 @@ Info()
} }
#endif /* DEBUG */ #endif /* DEBUG */
void void No_Mem(void) /* called by alloc package */
No_Mem() /* called by alloc package */
{ {
fatal("out of memory"); fatal("out of memory");
} }
void void C_failed(void) /* called by EM_code module */
C_failed() /* called by EM_code module */
{ {
fatal("write failed"); fatal("write failed");
} }

View file

@ -0,0 +1 @@
#include "parameters.h"

View file

@ -9,12 +9,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <alloc.h> #include <alloc.h>
#include "options.h"
#include "class.h" #include "class.h"
#include "macro.h" #include "macro.h"
#include "idf.h" #include "idf.h"
#include "arith.h" #include "arith.h"
#include "sizes.h" #include "sizes.h"
#include "align.h" #include "align.h"
#include "error.h"
char options[128]; /* one for every char */ char options[128]; /* one for every char */
#ifdef LINT #ifdef LINT
@ -24,10 +26,11 @@ char loptions[128]; /* one for every char */
extern int idfsize; extern int idfsize;
extern int density; extern int density;
static int txt2int();
do_option(text)
char *text; static int txt2int(register char **);
void do_option(char *text)
{ {
register char opt; register char opt;
@ -209,9 +212,7 @@ next_option: /* to allow combined one-char options */
} }
} }
static int static int txt2int(register char **tp)
txt2int(tp)
register char **tp;
{ {
/* the integer pointed to by *tp is read, while increasing /* the integer pointed to by *tp is read, while increasing
*tp; the resulting value is yielded. *tp; the resulting value is yielded.

View file

@ -0,0 +1,13 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-07
*
*/
#ifndef OPTIONS_H_
#define OPTIONS_H_
void do_option(char *text);
#endif /* OPTIONS_H_ */

View file

@ -6,37 +6,43 @@
/* PREPROCESSOR: PRAGMA INTERPRETER */ /* PREPROCESSOR: PRAGMA INTERPRETER */
#include "parameters.h" #include "parameters.h"
#include "pragma.h"
#include "skip.h"
#define P_UNKNOWN 0 #define P_UNKNOWN 0
#define NR_PRAGMAS 0 #define NR_PRAGMAS 0
struct pkey { struct pkey
{
char *pk_name; char *pk_name;
int pk_key; int pk_key;
} pragmas[NR_PRAGMAS + 1] = { } pragmas[NR_PRAGMAS + 1] =
{0, P_UNKNOWN} {
}; { 0, P_UNKNOWN } };
extern struct idf *GetIdentifier(); extern struct idf *GetIdentifier();
do_pragma() void do_pragma(void)
{ {
#if NR_PRAGMAS #if NR_PRAGMAS
register struct pkey *pkp = &pragmas[0]; register struct pkey *pkp = &pragmas[0];
#endif #endif
register struct idf *id = GetIdentifier(1); register struct idf *id = GetIdentifier(1);
if (id != (struct idf *)0) { if (id != (struct idf *) 0)
{
#if NR_PRAGMAS #if NR_PRAGMAS
while(pkp->pk_name) { while(pkp->pk_name)
{
if (strcmp(pkp->pk_name, id->id_text) == 0) if (strcmp(pkp->pk_name, id->id_text) == 0)
break; break;
pkp++; pkp++;
} }
switch (pkp->pk_key) { switch (pkp->pk_key)
case P_UNKNOWN: {
default: case P_UNKNOWN:
default:
break; break;
} }
#endif #endif

View file

@ -0,0 +1,13 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-07
*
*/
#ifndef PRAGMA_H_
#define PRAGMA_H_
void do_pragma(void);
#endif /* PRAGMA_H_ */

View file

@ -1,224 +1,227 @@
/* /*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright". * See the copyright notice in the ACK home directory, in the file "Copyright".
*/ */
/* $Id$ */ /* $Id$ */
/* PROGRAM PARSER */ /* PROGRAM PARSER */
/* The presence of typedef declarations renders it impossible to /* The presence of typedef declarations renders it impossible to
make a context-free grammar of C. Consequently we need make a context-free grammar of C. Consequently we need
context-sensitive parsing techniques, the simplest one being context-sensitive parsing techniques, the simplest one being
a subtle cooperation between the parser and the lexical scanner. a subtle cooperation between the parser and the lexical scanner.
The lexical scanner has to know whether to return IDENTIFIER The lexical scanner has to know whether to return IDENTIFIER
or TYPE_IDENTIFIER for a given tag, and it obtains this information or TYPE_IDENTIFIER for a given tag, and it obtains this information
from the definition list, as constructed by the parser. from the definition list, as constructed by the parser.
The present grammar is essentially LL(2), and is processed by The present grammar is essentially LL(2), and is processed by
a parser generator which accepts LL(1) with tie breaking rules a parser generator which accepts LL(1) with tie breaking rules
in C, of the form %if(cond) and %while(cond). To solve the LL(1) in C, of the form %if(cond) and %while(cond). To solve the LL(1)
ambiguities, the lexical scanner does a one symbol look-ahead. ambiguities, the lexical scanner does a one symbol look-ahead.
This symbol, however, cannot always be correctly assessed, since This symbol, however, cannot always be correctly assessed, since
the present symbol may cause a change in the definition list the present symbol may cause a change in the definition list
which causes the identification of the look-ahead symbol to be which causes the identification of the look-ahead symbol to be
invalidated. invalidated.
The lexical scanner relies on the parser (or its routines) to The lexical scanner relies on the parser (or its routines) to
detect this situation and then update the look-ahead symbol. detect this situation and then update the look-ahead symbol.
An alternative approach would be to reassess the look-ahead symbol An alternative approach would be to reassess the look-ahead symbol
in the lexical scanner when it is promoted to dot symbol. This in the lexical scanner when it is promoted to dot symbol. This
would be more beautiful but less correct, since then for a short would be more beautiful but less correct, since then for a short
while there would be a discrepancy between the look-ahead symbol while there would be a discrepancy between the look-ahead symbol
and the definition list; I think it would nevertheless work in and the definition list; I think it would nevertheless work in
correct programs. correct programs.
A third solution would be to enter the identifier as soon as it A third solution would be to enter the identifier as soon as it
is found; its storage class is then known, although its full type is found; its storage class is then known, although its full type
isn't. We would have to fill that in afterwards. isn't. We would have to fill that in afterwards.
At block exit the situation is even worse. Upon reading the At block exit the situation is even worse. Upon reading the
closing brace, the names declared inside the function are cleared closing brace, the names declared inside the function are cleared
from the name list. This action may expose a type identifier that from the name list. This action may expose a type identifier that
is the same as the identifier in the look-ahead symbol. This is the same as the identifier in the look-ahead symbol. This
situation certainly invalidates the third solution, and casts situation certainly invalidates the third solution, and casts
doubts upon the second. doubts upon the second.
*/ */
%lexical LLlex; %lexical LLlex;
%start C_program, program; %start C_program, program;
%start If_expr, control_if_expression; %start If_expr, control_if_expression;
{ {
#include "parameters.h" #include "parameters.h"
#include <flt_arith.h> #include <flt_arith.h>
#include "arith.h" #include "arith.h"
#include "LLlex.h" #include "LLlex.h"
#include "label.h" #include "label.h"
#include "type.h" #include "type.h"
#include "declar.h" #include "declar.h"
#include "decspecs.h" #include "decspecs.h"
#include "code.h" #include "code.h"
#include "expr.h" #include "expr.h"
#include "def.h" #include "def.h"
#include "stack.h" #include "idf.h"
#ifdef LINT #include "declarator.h"
#include "l_lint.h" #include "stack.h"
#endif /* LINT */ #include "proto.h"
#include "error.h"
extern error(); #ifdef LINT
} #include "l_lint.h"
#endif /* LINT */
control_if_expression
{ }
struct expr *exprX;
} control_if_expression
: {
constant_expression(&exprX) struct expr *exprX;
{ }
} :
; constant_expression(&exprX)
{
/* 3.7 */ }
program: ;
[%persistent external_definition]*
{ unstack_world(); } /* 3.7 */
; program:
[%persistent external_definition]*
/* A C identifier definition is remarkable in that it formulates { unstack_world(); }
the declaration in a way different from most other languages: ;
e.g., rather than defining x as a pointer-to-integer, it defines
*x as an integer and lets the compiler deduce that x is actually /* A C identifier definition is remarkable in that it formulates
pointer-to-integer. This has profound consequences, both for the the declaration in a way different from most other languages:
structure of an identifier definition and for the compiler. e.g., rather than defining x as a pointer-to-integer, it defines
*x as an integer and lets the compiler deduce that x is actually
A definition starts with a decl_specifiers, which contains things pointer-to-integer. This has profound consequences, both for the
like structure of an identifier definition and for the compiler.
typedef int
which is implicitly repeated for every definition in the list, and A definition starts with a decl_specifiers, which contains things
then for each identifier a declarator is given, of the form like
*a() typedef int
or so. The decl_specifiers is kept in a struct decspecs, to be which is implicitly repeated for every definition in the list, and
used again and again, while the declarator is stored in a struct then for each identifier a declarator is given, of the form
declarator, only to be passed to declare_idf together with the *a()
struct decspecs. or so. The decl_specifiers is kept in a struct decspecs, to be
used again and again, while the declarator is stored in a struct
With the introduction of prototypes, extra problems for the scope declarator, only to be passed to declare_idf together with the
administration were introduced as well. We can have, for example, struct decspecs.
int x(double x);
and With the introduction of prototypes, extra problems for the scope
int x(double x) { ... use(x) ... } administration were introduced as well. We can have, for example,
In the first case, the parameter name can be forgotten, whereas in int x(double x);
the second case, the parameter should have a block scope. The and
problem lies in the fact that the parameter's type is known before int x(double x) { ... use(x) ... }
the type of the function, which causes the def structure to be on In the first case, the parameter name can be forgotten, whereas in
the end of the list. Our solution is as follows: the second case, the parameter should have a block scope. The
1- In case of a declaration, throw the parameter identifier away problem lies in the fact that the parameter's type is known before
before the declaration of the outer x. the type of the function, which causes the def structure to be on
2- In case of a definition, the function begin_proc() changes the the end of the list. Our solution is as follows:
def list for the identifier. This means that declare_idf() 1- In case of a declaration, throw the parameter identifier away
contains an extra test in case we already saw a declaration of before the declaration of the outer x.
such a function, because this function is called before 2- In case of a definition, the function begin_proc() changes the
begin_proc(). def list for the identifier. This means that declare_idf()
*/ contains an extra test in case we already saw a declaration of
such a function, because this function is called before
external_definition begin_proc().
{ struct decspecs Ds; */
struct declarator Dc;
} external_definition
: { struct decspecs Ds;
{ Ds = null_decspecs; struct declarator Dc;
Dc = null_declarator; }
} :
[ %if (DOT != IDENTIFIER || AHEAD == IDENTIFIER) { Ds = null_decspecs;
decl_specifiers(&Ds) Dc = null_declarator;
| }
{do_decspecs(&Ds);} [ %if (DOT != IDENTIFIER || AHEAD == IDENTIFIER)
] decl_specifiers(&Ds)
[ |
declarator(&Dc) {do_decspecs(&Ds);}
{ ]
declare_idf(&Ds, &Dc, level); [
#ifdef LINT declarator(&Dc)
lint_ext_def(Dc.dc_idf, Ds.ds_sc); {
#endif /* LINT */ declare_idf(&Ds, &Dc, level);
} #ifdef LINT
[ lint_ext_def(Dc.dc_idf, Ds.ds_sc);
function(&Ds, &Dc) #endif /* LINT */
| }
{ if (! Ds.ds_sc_given && ! Ds.ds_typequal && [
Ds.ds_notypegiven) { function(&Ds, &Dc)
strict("declaration specifiers missing"); |
} { if (! Ds.ds_sc_given && ! Ds.ds_typequal &&
} Ds.ds_notypegiven) {
non_function(&Ds, &Dc) strict("declaration specifiers missing");
] }
| }
{ if (! Ds.ds_sc_given && ! Ds.ds_typequal && non_function(&Ds, &Dc)
Ds.ds_notypegiven) { ]
strict("declaration missing"); |
} { if (! Ds.ds_sc_given && ! Ds.ds_typequal &&
} Ds.ds_notypegiven) {
';' strict("declaration missing");
] }
{remove_declarator(&Dc); flush_strings(); } }
; ';'
]
non_function(register struct decspecs *ds; register struct declarator *dc;) {remove_declarator(&Dc); flush_strings(); }
: ;
{ reject_params(dc);
} non_function(register struct decspecs *ds; register struct declarator *dc;)
[ :
initializer(dc->dc_idf, ds->ds_sc) { reject_params(dc);
| }
{ code_declaration(dc->dc_idf, (struct expr *) 0, level, ds->ds_sc); } [
] initializer(dc->dc_idf, ds->ds_sc)
{ |
#ifdef LINT { code_declaration(dc->dc_idf, (struct expr *) 0, level, ds->ds_sc); }
lint_non_function_decl(ds, dc); ]
#endif /* LINT */ {
} #ifdef LINT
[ lint_non_function_decl(ds, dc);
',' #endif /* LINT */
init_declarator(ds) }
]* [
';' ','
; init_declarator(ds)
]*
/* 3.7.1 */ ';'
function(struct decspecs *ds; struct declarator *dc;) ;
{
arith fbytes; /* 3.7.1 */
register struct idf *idf = dc->dc_idf; function(struct decspecs *ds; struct declarator *dc;)
} {
: arith fbytes;
{ register struct idf *idf = dc->dc_idf;
#ifdef LINT }
lint_start_function(); :
#endif /* LINT */ {
idf_initialized(idf); #ifdef LINT
stack_level(); /* L_FORMAL1 declarations */ lint_start_function();
declare_params(dc); #endif /* LINT */
begin_proc(ds, idf); /* sets global function info */ idf_initialized(idf);
stack_level(); /* L_FORMAL2 declarations */ stack_level(); /* L_FORMAL1 declarations */
declare_protos(dc); declare_params(dc);
} begin_proc(ds, idf); /* sets global function info */
declaration* stack_level(); /* L_FORMAL2 declarations */
{ declare_protos(dc);
check_formals(idf, dc); /* check style-mixtures */ }
declare_formals(idf, &fbytes); declaration*
#ifdef LINT {
lint_formals(); check_formals(idf, dc); /* check style-mixtures */
#endif /* LINT */ declare_formals(idf, &fbytes);
} #ifdef LINT
compound_statement lint_formals();
{ #endif /* LINT */
end_proc(fbytes); }
#ifdef LINT compound_statement
lint_implicit_return(); {
#endif /* LINT */ end_proc(fbytes);
unstack_level(); /* L_FORMAL2 declarations */ #ifdef LINT
#ifdef LINT lint_implicit_return();
lint_end_formals(); #endif /* LINT */
#endif /* LINT */ unstack_level(); /* L_FORMAL2 declarations */
unstack_level(); /* L_FORMAL1 declarations */ #ifdef LINT
#ifdef LINT lint_end_formals();
lint_end_function(); #endif /* LINT */
#endif /* LINT */ unstack_level(); /* L_FORMAL1 declarations */
} #ifdef LINT
; lint_end_function();
#endif /* LINT */
}
;

View file

@ -23,20 +23,24 @@
#include "declar.h" #include "declar.h"
#include "decspecs.h" #include "decspecs.h"
#include "proto.h" #include "proto.h"
#include "error.h"
#include "ch3.h"
extern char options[]; extern char options[];
void void check_for_void(register struct proto *pl)
check_for_void(pl)
register struct proto *pl;
{ {
register int errcnt = 0; register int errcnt = 0;
if (!pl) return; if (!pl)
if ((pl->pl_flag & PL_VOID) && !(pl->next)) return; return;
if ((pl->pl_flag & PL_VOID) && !(pl->next))
return;
while (pl) { while (pl)
if (pl->pl_flag & PL_VOID) { {
if (pl->pl_flag & PL_VOID)
{
if (!errcnt && !(pl->pl_flag & PL_ERRGIVEN)) if (!errcnt && !(pl->pl_flag & PL_ERRGIVEN))
error("illegal use of void in argument list"); error("illegal use of void in argument list");
pl->pl_flag |= PL_ERRGIVEN; pl->pl_flag |= PL_ERRGIVEN;
@ -46,37 +50,35 @@ check_for_void(pl)
} }
} }
add_proto(pl, ds, dc, lvl) void add_proto(struct proto *pl, struct decspecs *ds, struct declarator *dc,
struct proto *pl; int lvl)
struct decspecs *ds;
struct declarator *dc;
int lvl;
{ {
/* The full typed identifier or abstract type, described /* The full typed identifier or abstract type, described
by the structures decspecs and declarator are turned by the structures decspecs and declarator are turned
a into parameter type list structure. a into parameter type list structure.
The parameters will be declared at level L_FORMAL2, The parameters will be declared at level L_FORMAL2,
later on it's decided whether they were prototypes later on it's decided whether they were prototypes
or actual declarations. or actual declarations.
*/ */
register struct idf *idf = dc->dc_idf; register struct idf *idf = dc->dc_idf;
register struct def *def = idf ? idf->id_def : (struct def *)0; register struct def *def = idf ? idf->id_def : (struct def *) 0;
register int sc = ds->ds_sc; register int sc = ds->ds_sc;
register struct type *type; register struct type *type;
char formal_array = 0; char formal_array = 0;
assert(ds->ds_type != (struct type *)0); assert(ds->ds_type != (struct type * )0);
pl->pl_flag = PL_FORMAL; pl->pl_flag = PL_FORMAL;
type = declare_type(ds->ds_type, dc); type = declare_type(ds->ds_type, dc);
if (type->tp_size < (arith)0 && actual_declaration(sc, type)) { if (type->tp_size < (arith) 0 && actual_declaration(sc, type))
{
extern char *symbol2str(); extern char *symbol2str();
if (type->tp_fund != VOID) if (type->tp_fund != VOID)
error("unknown %s-type", symbol2str(type->tp_fund)); error("unknown %s-type", symbol2str(type->tp_fund));
else { else
if (idf != (struct idf *)0 {
|| ds->ds_sc_given if (idf != (struct idf *) 0 || ds->ds_sc_given || ds->ds_typequal)
|| ds->ds_typequal) { {
error("illegal use of void in argument list"); error("illegal use of void in argument list");
pl->pl_flag |= PL_ERRGIVEN; pl->pl_flag |= PL_ERRGIVEN;
} }
@ -84,43 +86,54 @@ add_proto(pl, ds, dc, lvl)
pl->pl_flag |= PL_VOID; pl->pl_flag |= PL_VOID;
} }
} }
if (ds->ds_sc_given && ds->ds_sc != REGISTER) { if (ds->ds_sc_given && ds->ds_sc != REGISTER)
if (!(pl->pl_flag & PL_ERRGIVEN)) { {
if (ds->ds_sc != AUTO) { if (!(pl->pl_flag & PL_ERRGIVEN))
error("illegal storage class in parameter declaration"); {
} else { if (ds->ds_sc != AUTO)
warning("illegal storage class in parameter declaration"); {
} error("illegal storage class in parameter declaration");
}
else
{
warning("illegal storage class in parameter declaration");
}
} }
} }
/* Perform some special conversions for parameters. /* Perform some special conversions for parameters.
*/ */
if (type->tp_fund == FUNCTION) { if (type->tp_fund == FUNCTION)
{
type = construct_type(POINTER, type, 0, (arith) 0, NO_PROTO); type = construct_type(POINTER, type, 0, (arith) 0, NO_PROTO);
} else if (type->tp_fund == ARRAY) { }
else if (type->tp_fund == ARRAY)
{
type = construct_type(POINTER, type->tp_up, 0, (arith) 0, NO_PROTO); type = construct_type(POINTER, type->tp_up, 0, (arith) 0, NO_PROTO);
formal_array = 1; formal_array = 1;
} }
/* According to the standard we should ignore the storage /* According to the standard we should ignore the storage
class of a parameter, unless it's part of a function class of a parameter, unless it's part of a function
definition. definition.
However, in the routine declare_protos we don't know decspecs, However, in the routine declare_protos we don't know decspecs,
and therefore we can't complain up there. So we build up the and therefore we can't complain up there. So we build up the
storage class, and keep quiet until we reach declare_protos. storage class, and keep quiet until we reach declare_protos.
*/ */
sc = (ds->ds_sc_given && ds->ds_sc != REGISTER) ? sc = (ds->ds_sc_given && ds->ds_sc != REGISTER) ? 0 :
0 : sc == 0 ? FORMAL : REGISTER; sc == 0 ? FORMAL : REGISTER;
if (def && (def->df_level == lvl /* || def->df_level < L_PROTO */ )) { if (def && (def->df_level == lvl /* || def->df_level < L_PROTO */))
{
/* redeclaration at the same level */ /* redeclaration at the same level */
error("parameter %s redeclared", idf->id_text); error("parameter %s redeclared", idf->id_text);
} else if (idf != (struct idf *)0) { }
else if (idf != (struct idf *) 0)
{
/* New definition, redefinition hides earlier one /* New definition, redefinition hides earlier one
*/ */
register struct def *newdef = new_def(); register struct def *newdef = new_def();
newdef->next = def; newdef->next = def;
newdef->df_level = lvl; newdef->df_level = lvl;
newdef->df_sc = sc; newdef->df_sc = sc;
@ -133,28 +146,28 @@ add_proto(pl, ds, dc, lvl)
/* newdef->df_firstbrace = 0; */ /* newdef->df_firstbrace = 0; */
#endif #endif
/* We can't put the idf onto the stack, since these kinds /* We can't put the idf onto the stack, since these kinds
of declaration may occurs at any level, and the idf of declaration may occurs at any level, and the idf
does not necessarily go at this level. E.g. does not necessarily go at this level. E.g.
f() { f() {
... ...
{ int func(int a, int b); { int func(int a, int b);
... ...
} }
} }
The idf's a and b declared in the prototype declaration The idf's a and b declared in the prototype declaration
do not go at any level, they are simply ignored. do not go at any level, they are simply ignored.
However, in However, in
f(int a, int b) { f(int a, int b) {
... ...
} }
They should go at level L_FORMAL2. But at this stage They should go at level L_FORMAL2. But at this stage
we don't know whether we have a prototype or function we don't know whether we have a prototype or function
definition. So, this process is postponed. definition. So, this process is postponed.
*/ */
idf->id_def = newdef; idf->id_def = newdef;
update_ahead(idf); update_ahead(idf);
} }
@ -163,35 +176,33 @@ add_proto(pl, ds, dc, lvl)
pl->pl_type = type; pl->pl_type = type;
} }
struct tag * static struct tag * gettag(struct type *tp, struct idf **idpp)
gettag(tp, idpp)
struct type *tp;
struct idf **idpp;
{ {
struct tag *tg = (struct tag *)0; struct tag *tg = (struct tag *) 0;
register int fund = tp->tp_fund; register int fund = tp->tp_fund;
while (fund == FIELD || fund == POINTER while (fund == FIELD || fund == POINTER || fund == ARRAY || fund == FUNCTION)
|| fund == ARRAY || fund == FUNCTION) { {
tp = tp->tp_up; tp = tp->tp_up;
fund = tp->tp_fund; fund = tp->tp_fund;
} }
*idpp = tp->tp_idf; *idpp = tp->tp_idf;
switch(tp->tp_fund) { switch (tp->tp_fund)
{
case ENUM: case ENUM:
case UNION: case UNION:
case STRUCT: tg = tp->tp_idf->id_tag; break; case STRUCT:
tg = tp->tp_idf->id_tag;
break;
} }
return tg; return tg;
} }
void declare_protos(register struct declarator *dc)
declare_protos(dc)
register struct declarator *dc;
{ {
/* At this points we know that the idf's in protolist are formal /* At this points we know that the idf's in protolist are formal
parameters. So it's time to declare them at level L_FORMAL2. parameters. So it's time to declare them at level L_FORMAL2.
*/ */
struct stack_level *stl = stack_level_of(L_FORMAL1); struct stack_level *stl = stack_level_of(L_FORMAL1);
register struct decl_unary *du; register struct decl_unary *du;
register struct type *type; register struct type *type;
@ -200,31 +211,39 @@ declare_protos(dc)
#ifdef DEBUG #ifdef DEBUG
if (options['t']) if (options['t'])
dumpidftab("start declare_protos", 0); dumpidftab("start declare_protos", 0);
#endif /* DEBUG */ #endif /* DEBUG */
du = dc->dc_decl_unary; du = dc->dc_decl_unary;
while (du) { while (du)
if (du->du_fund == FUNCTION) { {
if (du->next != (struct decl_unary *) 0) { if (du->du_fund == FUNCTION)
{
if (du->next != (struct decl_unary *) 0)
{
remove_proto_idfs(du->du_proto); remove_proto_idfs(du->du_proto);
du->du_proto = 0; du->du_proto = 0;
} else break; }
else
break;
} }
du = du->next; du = du->next;
} }
pl = du ? du->du_proto : NO_PROTO; pl = du ? du->du_proto : NO_PROTO;
if (pl) { if (pl)
{
#if 0 /* the id_proto member is deleted (???) */ #if 0 /* the id_proto member is deleted (???) */
idf->id_proto = 0; idf->id_proto = 0;
#endif /* 0 */ #endif /* 0 */
do { do
{
struct tag *tg; struct tag *tg;
struct idf *idp = 0; struct idf *idp = 0;
type = pl->pl_type; type = pl->pl_type;
/* `...' only for type checking */ /* `...' only for type checking */
if (pl->pl_flag & PL_ELLIPSIS) { if (pl->pl_flag & PL_ELLIPSIS)
{
pl = pl->next; pl = pl->next;
continue; continue;
} }
@ -233,14 +252,15 @@ declare_protos(dc)
if (type->tp_fund == VOID) if (type->tp_fund == VOID)
break; break;
if (!pl->pl_idf || !(def = pl->pl_idf->id_def)) { if (!pl->pl_idf || !(def = pl->pl_idf->id_def))
{
error("no parameter identifier supplied"); error("no parameter identifier supplied");
pl = pl->next; pl = pl->next;
continue; continue;
} }
/* Postponed storage class checking. /* Postponed storage class checking.
*/ */
if (def->df_sc == 0) if (def->df_sc == 0)
error("illegal storage class in parameter declaration"); error("illegal storage class in parameter declaration");
@ -249,7 +269,8 @@ declare_protos(dc)
pl = pl->next; pl = pl->next;
tg = gettag(type, &idp); tg = gettag(type, &idp);
if (tg && tg->tg_level <= L_PROTO) { if (tg && tg->tg_level <= L_PROTO)
{
tg->tg_level = L_FORMAL2; tg->tg_level = L_FORMAL2;
stack_idf(idp, stl); stack_idf(idp, stl);
} }
@ -257,43 +278,47 @@ declare_protos(dc)
} }
#ifdef DEBUG #ifdef DEBUG
if (options['t']) if (options['t'])
dumpidftab("end declare_protos", 0); dumpidftab("end declare_protos", 0);
#endif /* DEBUG */ #endif /* DEBUG */
} }
void update_proto(register struct type *tp, register struct type *otp)
void
update_proto(tp, otp)
register struct type *tp, *otp;
{ {
/* This routine performs the proto type updates. /* This routine performs the proto type updates.
Consider the following code: Consider the following code:
int f(double g()); int f(double g());
int f(double g(int f(), int)); int f(double g(int f(), int));
int f(double g(int f(long double), int)); int f(double g(int f(long double), int));
The most accurate definition is the third line. The most accurate definition is the third line.
This routine will silently update all lists, This routine will silently update all lists,
and removes the redundant occupied space. and removes the redundant occupied space.
*/ */
register struct proto *pl, *opl; register struct proto *pl, *opl;
if (tp == otp) return; if (tp == otp)
if (!tp || !otp) return; return;
if (!tp || !otp)
return;
while (tp->tp_fund != FUNCTION) { while (tp->tp_fund != FUNCTION)
if (tp->tp_fund != POINTER && tp->tp_fund != ARRAY) return; {
if (tp->tp_fund != POINTER && tp->tp_fund != ARRAY)
return;
tp = tp->tp_up; tp = tp->tp_up;
otp = otp->tp_up; otp = otp->tp_up;
if (!tp) return; if (!tp)
return;
} }
pl = tp->tp_proto; pl = tp->tp_proto;
opl = otp->tp_proto; opl = otp->tp_proto;
if (pl && opl) { if (pl && opl)
{
/* both have prototypes */ /* both have prototypes */
while (pl && opl) { while (pl && opl)
{
update_proto(pl->pl_type, opl->pl_type); update_proto(pl->pl_type, opl->pl_type);
pl = pl->next; pl = pl->next;
opl = opl->next; opl = opl->next;
@ -302,9 +327,13 @@ update_proto(tp, otp)
* a typedef. * a typedef.
*/ */
otp->tp_proto = tp->tp_proto; otp->tp_proto = tp->tp_proto;
} else if (opl) { }
else if (opl)
{
/* old decl has type */ /* old decl has type */
} else if (pl) { }
else if (pl)
{
otp->tp_proto = pl; otp->tp_proto = pl;
} }
@ -314,39 +343,44 @@ update_proto(tp, otp)
/* struct/union and enum tags can be declared inside prototypes /* struct/union and enum tags can be declared inside prototypes
* remove them from the symbol-table * remove them from the symbol-table
*/ */
void static void remove_proto_tag(struct type *tp)
remove_proto_tag(tp)
struct type *tp;
{ {
register struct idf *ident; register struct idf *ident;
register struct tag *tgp, **tgpp; register struct tag *tgp, **tgpp;
register int fund = tp->tp_fund; register int fund = tp->tp_fund;
while (fund == FIELD || fund == POINTER while (fund == FIELD || fund == POINTER || fund == ARRAY || fund == FUNCTION)
|| fund == ARRAY || fund == FUNCTION) { {
tp = tp->tp_up; tp = tp->tp_up;
fund = tp->tp_fund; fund = tp->tp_fund;
} }
ident = tp->tp_idf; ident = tp->tp_idf;
switch (tp->tp_fund) { switch (tp->tp_fund)
{
case ENUM: case ENUM:
case STRUCT: case STRUCT:
case UNION: tgpp = &(ident->id_tag); break; case UNION:
default: return; tgpp = &(ident->id_tag);
break;
default:
return;
} }
while((*tgpp) && (*tgpp)->tg_type != tp) { while ((*tgpp) && (*tgpp)->tg_type != tp)
{
tgpp = &((*tgpp)->next); tgpp = &((*tgpp)->next);
} }
if (!*tgpp) return; if (!*tgpp)
return;
tgp = *tgpp; tgp = *tgpp;
if (tgp->tg_level > L_PROTO) return; if (tgp->tg_level > L_PROTO)
return;
#ifdef DEBUG #ifdef DEBUG
if (options['t']) if (options['t'])
print("Removing idf %s from list\n", print("Removing idf %s from list\n",
ident->id_text); ident->id_text);
#endif #endif
@ -354,52 +388,55 @@ struct type *tp;
free_tag(tgp); free_tag(tgp);
} }
remove_proto_idfs(pl) /* Remove all the identifier definitions from the
register struct proto *pl; prototype list. */
void remove_proto_idfs(register struct proto *pl)
{ {
/* Remove all the identifier definitions from the
prototype list.
*/
register struct def *def; register struct def *def;
while (pl) { while (pl)
if (pl->pl_idf) { {
if (pl->pl_idf)
{
#ifdef DEBUG #ifdef DEBUG
if (options['t']) if (options['t'])
print("Removing idf %s from list\n", print("Removing idf %s from list\n",
pl->pl_idf->id_text); pl->pl_idf->id_text);
#endif #endif
def = pl->pl_idf->id_def; def = pl->pl_idf->id_def;
if (def && def->df_level <= L_PROTO) { if (def && def->df_level <= L_PROTO)
{
pl->pl_idf->id_def = def->next; pl->pl_idf->id_def = def->next;
free_def(def); free_def(def);
} }
pl->pl_idf = (struct idf *) 0; pl->pl_idf = (struct idf *) 0;
} }
if (pl->pl_type) { if (pl->pl_type)
{
remove_proto_tag(pl->pl_type); remove_proto_tag(pl->pl_type);
} }
pl = pl->next; pl = pl->next;
} }
} }
void void call_proto(register struct expr **expp)
call_proto(expp)
register struct expr **expp;
{ {
/* If the function specified by (*expp)->OP_LEFT has a prototype, /* If the function specified by (*expp)->OP_LEFT has a prototype,
the parameters are converted according the rules specified in the parameters are converted according the rules specified in
par. 3.3.2.2. E.i. the parameters are converted to the prototype par. 3.3.2.2. E.i. the parameters are converted to the prototype
counter parts as if by assignment. For the parameters falling counter parts as if by assignment. For the parameters falling
under ellipsis clause the old parameters conversion stuff under ellipsis clause the old parameters conversion stuff
applies. applies.
*/ */
register struct expr *left = (*expp)->OP_LEFT; register struct expr *left = (*expp)->OP_LEFT;
register struct expr *right = (*expp)->OP_RIGHT; register struct expr *right = (*expp)->OP_RIGHT;
register struct proto *pl = NO_PROTO; register struct proto *pl = NO_PROTO;
static struct proto ellipsis = { 0, 0, 0, PL_ELLIPSIS }; static struct proto ellipsis =
{ 0, 0, 0, PL_ELLIPSIS };
if (left != NILEXPR) { /* in case of an error */ if (left != NILEXPR)
{ /* in case of an error */
register struct type *tp = left->ex_type; register struct type *tp = left->ex_type;
while (tp && tp->tp_fund != FUNCTION && tp != error_type) while (tp && tp->tp_fund != FUNCTION && tp != error_type)
@ -408,17 +445,20 @@ call_proto(expp)
pl = tp->tp_proto; pl = tp->tp_proto;
} }
if (right != NILEXPR) { /* function call with parameters */ if (right != NILEXPR)
{ /* function call with parameters */
register struct expr **ep = &((*expp)->OP_RIGHT); register struct expr **ep = &((*expp)->OP_RIGHT);
register int ecnt = 0, pcnt = 0; register int ecnt = 0, pcnt = 0;
struct expr **estack[NPARAMS]; struct expr **estack[NPARAMS];
struct proto *pstack[NPARAMS]; struct proto *pstack[NPARAMS];
/* stack up the parameter expressions */ /* stack up the parameter expressions */
while (right->ex_class == Oper && right->OP_OPER == PARCOMMA) { while (right->ex_class == Oper && right->OP_OPER == PARCOMMA)
{
if (ecnt == STDC_NPARAMS) if (ecnt == STDC_NPARAMS)
expr_strict(right, "number of parameters exceeds ANSI limit"); expr_strict(right, "number of parameters exceeds ANSI limit");
if (ecnt >= NPARAMS-1) { if (ecnt >= NPARAMS - 1)
{
expr_error(right, "too many parameters"); expr_error(right, "too many parameters");
return; return;
} }
@ -429,45 +469,56 @@ call_proto(expp)
estack[ecnt] = ep; estack[ecnt] = ep;
/* Declarations like int f(void) do not expect any /* Declarations like int f(void) do not expect any
parameters. parameters.
*/ */
if (pl && pl->pl_flag & PL_VOID) { if (pl && pl->pl_flag & PL_VOID)
{
expr_strict(*expp, "no parameters expected"); expr_strict(*expp, "no parameters expected");
pl = NO_PROTO; pl = NO_PROTO;
} }
/* stack up the prototypes */ /* stack up the prototypes */
if (pl) { if (pl)
{
pcnt--; pcnt--;
do { do
{
/* stack prototypes */ /* stack prototypes */
pstack[++pcnt] = pl; pstack[++pcnt] = pl;
pl = pl->next; pl = pl->next;
} while (pl); } while (pl);
} }
else { else
{
pstack[0] = &ellipsis; pstack[0] = &ellipsis;
} }
for (ecnt; ecnt >= 0; ecnt--) { for (ecnt; ecnt >= 0; ecnt--)
{
/* Only the parameters specified in the prototype /* Only the parameters specified in the prototype
are checked and converted. The parameters that are checked and converted. The parameters that
fall under the ellipsis clause are neither fall under the ellipsis clause are neither
checked nor converted ! checked nor converted !
*/ */
if (pcnt < 0) { if (pcnt < 0)
expr_error(*expp, "more parameters than specified in prototype"); {
expr_error(*expp,
"more parameters than specified in prototype");
break; break;
} }
else if (!(pstack[pcnt]->pl_flag & PL_ELLIPSIS)) { else if (!(pstack[pcnt]->pl_flag & PL_ELLIPSIS))
ch3cast(estack[ecnt],CASTAB,pstack[pcnt]->pl_type); {
ch3cast(estack[ecnt], CASTAB, pstack[pcnt]->pl_type);
pcnt--; pcnt--;
} else }
else
any2parameter(estack[ecnt]); any2parameter(estack[ecnt]);
} }
if (pcnt > 0 || (pcnt == 0 && !(pstack[0]->pl_flag & PL_ELLIPSIS))) if (pcnt > 0 || (pcnt == 0 && !(pstack[0]->pl_flag & PL_ELLIPSIS)))
expr_error(*expp, "fewer parameters than specified in prototype"); expr_error(*expp, "fewer parameters than specified in prototype");
} else { }
else
{
if (pl && !(pl->pl_flag & PL_VOID)) if (pl && !(pl->pl_flag & PL_VOID))
expr_error(*expp, "fewer parameters than specified in prototype"); expr_error(*expp, "fewer parameters than specified in prototype");
} }

View file

@ -2,6 +2,9 @@
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright". * See the copyright notice in the ACK home directory, in the file "Copyright".
*/ */
#ifndef PROTO_H
#define PROTO_H
/* $Id$ */ /* $Id$ */
/* PARAMETER TYPE LIST DEFINITION */ /* PARAMETER TYPE LIST DEFINITION */
@ -20,3 +23,20 @@ struct proto {
#define PL_ERRGIVEN 0x08 #define PL_ERRGIVEN 0x08
/* ALLOCDEF "proto" 20 */ /* ALLOCDEF "proto" 20 */
/* Forward structure declarations */
struct expr;
struct type;
struct declarator;
struct decspecs;
void remove_proto_idfs(register struct proto *pl);
void call_proto(register struct expr **expp);
void update_proto(register struct type *tp, register struct type *otp);
void declare_protos(register struct declarator *dc);
void add_proto(struct proto *pl, struct decspecs *ds, struct declarator *dc,
int lvl);
void check_for_void(register struct proto *pl);
#endif

View file

@ -10,9 +10,10 @@
#include "LLlex.h" #include "LLlex.h"
#include "class.h" #include "class.h"
#include "input.h" #include "input.h"
#include "skip.h"
SkipToNewLine() int SkipToNewLine(void)
{ {
register int ch; register int ch;
register int garbage = 0; register int garbage = 0;

View file

@ -0,0 +1,13 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-07
*
*/
#ifndef SKIP_H_
#define SKIP_H_
int SkipToNewLine(void);
#endif /* SKIP_H_ */

View file

@ -20,6 +20,7 @@
#include <flt_arith.h> #include <flt_arith.h>
#include <stb.h> #include <stb.h>
#include "stab.h"
#include "idf.h" #include "idf.h"
#include "LLlex.h" #include "LLlex.h"
#include "stack.h" #include "stack.h"
@ -29,34 +30,34 @@
#include "field.h" #include "field.h"
#include "Lpars.h" #include "Lpars.h"
#include "level.h" #include "level.h"
#include "print.h"
extern long full_mask[]; extern long full_mask[];
extern char *sprint();
#define INCR_SIZE 64 #define INCR_SIZE 64
static struct db_str { static struct db_str
unsigned sz; {
char *base; unsigned sz;
char *currpos; char *base;
char *currpos;
} db_str; } db_str;
static static void create_db_str(void)
create_db_str()
{ {
if (! db_str.base) { if (!db_str.base)
{
db_str.base = Malloc(INCR_SIZE); db_str.base = Malloc(INCR_SIZE);
db_str.sz = INCR_SIZE; db_str.sz = INCR_SIZE;
} }
db_str.currpos = db_str.base; db_str.currpos = db_str.base;
} }
static static void addc_db_str(int c)
addc_db_str(c)
int c;
{ {
int df = db_str.currpos - db_str.base; int df = db_str.currpos - db_str.base;
if (df >= db_str.sz-1) { if (df >= db_str.sz - 1)
{
db_str.sz += INCR_SIZE; db_str.sz += INCR_SIZE;
db_str.base = Realloc(db_str.base, db_str.sz); db_str.base = Realloc(db_str.base, db_str.sz);
db_str.currpos = db_str.base + df; db_str.currpos = db_str.base + df;
@ -65,34 +66,35 @@ addc_db_str(c)
*db_str.currpos = '\0'; *db_str.currpos = '\0';
} }
static static void adds_db_str(char *s)
adds_db_str(s)
char *s;
{ {
while (*s) addc_db_str(*s++); while (*s)
addc_db_str(*s++);
} }
static void static void stb_type(register struct type *tp)
stb_type(tp)
register struct type *tp;
{ {
char buf[128]; char buf[128];
static int stb_count; static int stb_count;
long l; long l;
if (tp->tp_dbindex > 0) { if (tp->tp_dbindex > 0)
{
adds_db_str(sprint(buf, "%d", tp->tp_dbindex)); adds_db_str(sprint(buf, "%d", tp->tp_dbindex));
return; return;
} }
if (tp->tp_dbindex < 0 && tp->tp_size < 0) { if (tp->tp_dbindex < 0 && tp->tp_size < 0)
{
adds_db_str(sprint(buf, "%d", -tp->tp_dbindex)); adds_db_str(sprint(buf, "%d", -tp->tp_dbindex));
return; return;
} }
if (tp->tp_dbindex <= 0) { if (tp->tp_dbindex <= 0)
{
tp->tp_dbindex = ++stb_count; tp->tp_dbindex = ++stb_count;
} }
adds_db_str(sprint(buf, "%d=", tp->tp_dbindex)); adds_db_str(sprint(buf, "%d=", tp->tp_dbindex));
switch(tp->tp_fund) { switch (tp->tp_fund)
{
/* simple types ... */ /* simple types ... */
case VOID: case VOID:
adds_db_str(sprint(buf, "%d", void_type->tp_dbindex)); adds_db_str(sprint(buf, "%d", void_type->tp_dbindex));
@ -101,49 +103,44 @@ stb_type(tp)
case LONG: case LONG:
case CHAR: case CHAR:
case SHORT: case SHORT:
l = full_mask[(int)tp->tp_size]; l = full_mask[(int) tp->tp_size];
if (tp->tp_unsigned) { if (tp->tp_unsigned)
adds_db_str(sprint(buf, {
"r%d;0;%ld", adds_db_str(sprint(buf, "r%d;0;%ld", tp->tp_dbindex, l));
tp->tp_dbindex,
l));
} }
else { else
l &= ~ (1L << ((int)tp->tp_size * 8 - 1)); {
adds_db_str(sprint(buf, l &= ~(1L << ((int) tp->tp_size * 8 - 1));
"r%d;%ld;%ld", adds_db_str(sprint(buf, "r%d;%ld;%ld", tp->tp_dbindex, -l - 1, l));
tp->tp_dbindex,
-l-1,
l));
} }
break; break;
case FLOAT: case FLOAT:
case DOUBLE: case DOUBLE:
case LNGDBL: case LNGDBL:
adds_db_str(sprint(buf, adds_db_str(
"r%d;%ld;0", sprint(buf, "r%d;%ld;0", tp->tp_dbindex, (long) tp->tp_size));
tp->tp_dbindex,
(long)tp->tp_size));
break; break;
/* constructed types ... */ /* constructed types ... */
case POINTER: case POINTER:
addc_db_str('*'); addc_db_str('*');
stb_type(tp->tp_up); stb_type(tp->tp_up);
break; break;
case ARRAY: case ARRAY:
if (tp->tp_size > 0) { if (tp->tp_size > 0)
{
adds_db_str("ar"); adds_db_str("ar");
stb_type(int_type); stb_type(int_type);
adds_db_str(sprint(buf, ";0;%ld;", tp->tp_size / tp->tp_up->tp_size - 1)); adds_db_str(
sprint(buf, ";0;%ld;",
tp->tp_size / tp->tp_up->tp_size - 1));
stb_type(tp->tp_up); stb_type(tp->tp_up);
} }
break; break;
case ENUM: case ENUM:
if (tp->tp_size < 0) { if (tp->tp_size < 0)
adds_db_str(sprint(buf, {
"xe%s:", adds_db_str(sprint(buf, "xe%s:", tp->tp_idf->id_text));
tp->tp_idf->id_text));
tp->tp_dbindex = -tp->tp_dbindex; tp->tp_dbindex = -tp->tp_dbindex;
break; break;
} }
@ -151,15 +148,16 @@ stb_type(tp)
{ {
register struct stack_entry *se = local_level->sl_entry; register struct stack_entry *se = local_level->sl_entry;
while (se) { while (se)
register struct def *edef = se->se_idf->id_def; {
while (edef) { register struct def *edef = se->se_idf->id_def;
if (edef->df_type == tp && while (edef)
edef->df_sc == ENUM) { {
adds_db_str(sprint(buf, if (edef->df_type == tp && edef->df_sc == ENUM)
"%s:%ld,", {
se->se_idf->id_text, adds_db_str(
edef->df_address)); sprint(buf, "%s:%ld,", se->se_idf->id_text,
edef->df_address));
} }
edef = edef->next; edef = edef->next;
} }
@ -170,37 +168,39 @@ stb_type(tp)
break; break;
case STRUCT: case STRUCT:
case UNION: case UNION:
if (tp->tp_size < 0) { if (tp->tp_size < 0)
adds_db_str(sprint(buf, {
"x%c%s:", adds_db_str(
tp->tp_fund == STRUCT ? 's' : 'u', sprint(buf, "x%c%s:", tp->tp_fund == STRUCT ? 's' : 'u',
tp->tp_idf->id_text)); tp->tp_idf->id_text));
tp->tp_dbindex = -tp->tp_dbindex; tp->tp_dbindex = -tp->tp_dbindex;
break; break;
} }
adds_db_str(sprint(buf, adds_db_str(
"%c%ld", sprint(buf, "%c%ld", tp->tp_fund == STRUCT ? 's' : 'u',
tp->tp_fund == STRUCT ? 's' : 'u', tp->tp_size));
tp->tp_size));
{ {
register struct sdef *sdef = tp->tp_sdef; register struct sdef *sdef = tp->tp_sdef;
while (sdef) { while (sdef)
{
adds_db_str(sdef->sd_idf->id_text); adds_db_str(sdef->sd_idf->id_text);
addc_db_str(':'); addc_db_str(':');
if (sdef->sd_type->tp_fund == FIELD) { if (sdef->sd_type->tp_fund == FIELD)
{
stb_type(sdef->sd_type->tp_up); stb_type(sdef->sd_type->tp_up);
adds_db_str(sprint(buf, adds_db_str(
",%ld,%ld;", sprint(buf, ",%ld,%ld;",
sdef->sd_offset*8+sdef->sd_type->tp_field->fd_shift, sdef->sd_offset * 8
sdef->sd_type->tp_field->fd_width)); + sdef->sd_type->tp_field->fd_shift,
sdef->sd_type->tp_field->fd_width));
} }
else { else
{
stb_type(sdef->sd_type); stb_type(sdef->sd_type);
adds_db_str(sprint(buf, adds_db_str(
",%ld,%ld;", sprint(buf, ",%ld,%ld;", sdef->sd_offset * 8,
sdef->sd_offset*8, sdef->sd_type->tp_size * 8));
sdef->sd_type->tp_size*8));
} }
sdef = sdef->sd_sdef; sdef = sdef->sd_sdef;
} }
@ -213,9 +213,7 @@ stb_type(tp)
} }
} }
stb_tag(tg, str) void stb_tag(register struct tag *tg, char *str)
register struct tag *tg;
char *str;
{ {
create_db_str(); create_db_str();
adds_db_str(str); adds_db_str(str);
@ -223,16 +221,12 @@ stb_tag(tg, str)
stb_type(tg->tg_type); stb_type(tg->tg_type);
addc_db_str(';'); addc_db_str(';');
C_ms_stb_cst(db_str.base, C_ms_stb_cst(db_str.base,
N_LSYM, N_LSYM,
tg->tg_type == void_type || tg->tg_type->tp_size >= 32767 tg->tg_type == void_type || tg->tg_type->tp_size >= 32767 ?
? 0 0 : (int) tg->tg_type->tp_size, (arith) 0);
: (int)tg->tg_type->tp_size,
(arith) 0);
} }
stb_typedef(tp, str) void stb_typedef(register struct type *tp, char *str)
register struct type *tp;
char *str;
{ {
create_db_str(); create_db_str();
adds_db_str(str); adds_db_str(str);
@ -240,23 +234,19 @@ stb_typedef(tp, str)
stb_type(tp); stb_type(tp);
addc_db_str(';'); addc_db_str(';');
C_ms_stb_cst(db_str.base, C_ms_stb_cst(db_str.base,
N_LSYM, N_LSYM, tp == void_type || tp->tp_size >= 32767 ? 0 : (int) tp->tp_size,
tp == void_type || tp->tp_size >= 32767 (arith) 0);
? 0
: (int)tp->tp_size,
(arith) 0);
} }
stb_string(df, kind, str) void stb_string(register struct def *df, int kind, char* str)
register struct def *df;
char *str;
{ {
register struct type *tp = df->df_type; register struct type *tp = df->df_type;
create_db_str(); create_db_str();
adds_db_str(str); adds_db_str(str);
addc_db_str(':'); addc_db_str(':');
switch(kind) { switch (kind)
{
case FUNCTION: case FUNCTION:
addc_db_str(df->df_sc == STATIC ? 'f' : 'F'); addc_db_str(df->df_sc == STATIC ? 'f' : 'F');
stb_type(tp->tp_up); stb_type(tp->tp_up);
@ -264,40 +254,50 @@ stb_string(df, kind, str)
C_ms_stb_pnam(db_str.base, N_FUN, 1 /* proclevel */, str); C_ms_stb_pnam(db_str.base, N_FUN, 1 /* proclevel */, str);
break; break;
default: default:
if (df->df_sc == FORMAL || if (df->df_sc == FORMAL
(df->df_sc == REGISTER && df->df_address >= 0)) { || (df->df_sc == REGISTER && df->df_address >= 0))
/* value parameter */ {
/* value parameter */
addc_db_str('p'); addc_db_str('p');
stb_type(tp); stb_type(tp);
addc_db_str(';'); addc_db_str(';');
C_ms_stb_cst(db_str.base, N_PSYM, 0, df->df_address); C_ms_stb_cst(db_str.base, N_PSYM, 0, df->df_address);
} }
else if (df->df_sc != AUTO && df->df_sc != REGISTER) { else if (df->df_sc != AUTO && df->df_sc != REGISTER)
/* global */ {
/* global */
int stabtp = df->df_initialized ? N_STSYM : N_LCSYM; int stabtp = df->df_initialized ? N_STSYM : N_LCSYM;
if (df->df_sc == STATIC) { if (df->df_sc == STATIC)
if (df->df_level >= L_LOCAL) { {
if (df->df_level >= L_LOCAL)
{
addc_db_str('V'); addc_db_str('V');
} }
else { else
{
addc_db_str('S'); addc_db_str('S');
} }
} }
else { else
{
addc_db_str('G'); addc_db_str('G');
} }
stb_type(tp); stb_type(tp);
addc_db_str(';'); addc_db_str(';');
if (df->df_sc == STATIC && df->df_level >= L_LOCAL) { if (df->df_sc == STATIC && df->df_level >= L_LOCAL)
C_ms_stb_dlb(db_str.base, stabtp, 0, (label) df->df_address, (arith) 0); {
C_ms_stb_dlb(db_str.base, stabtp, 0, (label) df->df_address,
(arith) 0);
} }
else { else
{
C_ms_stb_dnam(db_str.base, stabtp, 0, str, (arith) 0); C_ms_stb_dnam(db_str.base, stabtp, 0, str, (arith) 0);
} }
} }
else { /* local variable */ else
stb_type(tp); /* assign type num to avoid { /* local variable */
difficult to parse string */ stb_type(tp); /* assign type num to avoid
difficult to parse string */
addc_db_str(';'); addc_db_str(';');
C_ms_stb_cst(db_str.base, N_LSYM, 0, df->df_address); C_ms_stb_cst(db_str.base, N_LSYM, 0, df->df_address);
} }

View file

@ -0,0 +1,20 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-07
*
*/
#ifndef STAB_H_
#define STAB_H_
struct def;
struct type;
struct tag;
void stb_tag(register struct tag *tg, char *str);
void stb_typedef(register struct type *tp, char *str);
void stb_string(register struct def *df, int kind, char* str);
#endif /* STAB_H_ */

View file

@ -22,6 +22,9 @@
#include "struct.h" #include "struct.h"
#include "level.h" #include "level.h"
#include "mes.h" #include "mes.h"
#include "code.h"
#include "util.h"
#include "error.h"
/* #include <em_reg.h> */ /* #include <em_reg.h> */
@ -41,7 +44,7 @@ struct stack_level *local_level = &UniversalLevel;
int level; /* Always equal to local_level->sl_level. */ int level; /* Always equal to local_level->sl_level. */
stack_level() { void stack_level(void) {
/* A new level is added on top of the identifier stack. /* A new level is added on top of the identifier stack.
*/ */
register struct stack_level *stl = new_stack_level(); register struct stack_level *stl = new_stack_level();
@ -57,10 +60,9 @@ stack_level() {
#endif /* LINT */ #endif /* LINT */
} }
void void stack_idf(
stack_idf(idf, stl) struct idf *idf,
struct idf *idf; register struct stack_level *stl)
register struct stack_level *stl;
{ {
/* The identifier idf is inserted in the stack on level stl, /* The identifier idf is inserted in the stack on level stl,
but only if it is not already present at this level. but only if it is not already present at this level.
@ -81,8 +83,7 @@ stack_idf(idf, stl)
stl->sl_entry = se; stl->sl_entry = se;
} }
struct stack_level * struct stack_level *stack_level_of(int lvl)
stack_level_of(lvl)
{ {
/* The stack_level corresponding to level lvl is returned. /* The stack_level corresponding to level lvl is returned.
The stack should probably be an array, to be extended with The stack should probably be an array, to be extended with
@ -100,7 +101,7 @@ stack_level_of(lvl)
return stl; return stl;
} }
unstack_level() void unstack_level(void)
{ {
/* The top level of the identifier stack is removed. /* The top level of the identifier stack is removed.
*/ */
@ -174,7 +175,7 @@ unstack_level()
#endif /* DEBUG */ #endif /* DEBUG */
} }
unstack_world() void unstack_world(void)
{ {
/* The global level of identifiers is scanned, and final /* The global level of identifiers is scanned, and final
decisions are taken about such issues as decisions are taken about such issues as
@ -263,14 +264,13 @@ unstack_world()
extern char *nmlist; /* BAH! -- main.c */ extern char *nmlist; /* BAH! -- main.c */
static File *nfp = 0; static File *nfp = 0;
open_name_list() void open_name_list(void)
{ {
if (nmlist && sys_open(nmlist, OP_WRITE, &nfp) == 0) if (nmlist && sys_open(nmlist, OP_WRITE, &nfp) == 0)
fatal("cannot create namelist %s", nmlist); fatal("cannot create namelist %s", nmlist);
} }
namelist(nm) void namelist(char *nm)
char *nm;
{ {
if (nmlist) { if (nmlist) {
sys_write(nfp, nm, strlen(nm)); sys_write(nfp, nm, strlen(nm));

View file

@ -2,9 +2,14 @@
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright". * See the copyright notice in the ACK home directory, in the file "Copyright".
*/ */
#ifndef STACK_H_
#define STACK_H_
/* $Id$ */ /* $Id$ */
/* IDENTIFIER STACK DEFINITIONS */ /* IDENTIFIER STACK DEFINITIONS */
struct idf;
/* The identifier stack is implemented as a stack of sets. /* The identifier stack is implemented as a stack of sets.
The stack is implemented by a doubly linked list, The stack is implemented by a doubly linked list,
the sets by singly linked lists. the sets by singly linked lists.
@ -30,5 +35,26 @@ struct stack_entry {
/* ALLOCDEF "stack_entry" 50 */ /* ALLOCDEF "stack_entry" 50 */
extern struct stack_level *local_level; extern struct stack_level *local_level;
extern struct stack_level *stack_level_of();
extern int level; extern int level;
/* A new level is added on top of the identifier stack. */
void stack_level(void);
/* The identifier idf is inserted in the stack on level stl,
but only if it is not already present at this level.
*/
void stack_idf(struct idf *idf, register struct stack_level *stl);
/*The stack_level corresponding to level lvl is returned.
The stack should probably be an array, to be extended with
realloc where needed.
*/
struct stack_level *stack_level_of(int lvl);
/* The top level of the identifier stack is removed. */
void unstack_level(void);
void unstack_world(void);
#ifdef GEN_NM_LIST
void open_name_list(void);
void namelist(char *nm);
#endif /* GEN_NM_LIST */
#endif

File diff suppressed because it is too large Load diff

View file

@ -3,10 +3,10 @@
* See the copyright notice in the ACK home directory, in the file "Copyright". * See the copyright notice in the ACK home directory, in the file "Copyright".
*/ */
/* $Id$ */ /* $Id$ */
/* library routine for copying structs */
__stb(n, f, t)
register char *f, *t; register n; /* library routine for copying structs */
void __stb(register int n, register char *f, register char *t)
{ {
if (n > 0) if (n > 0)
do do

View file

@ -2,6 +2,9 @@
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright". * See the copyright notice in the ACK home directory, in the file "Copyright".
*/ */
#ifndef STMT_H_
#define STMT_H_
/* $Id$ */ /* $Id$ */
/* S T A T E M E N T - B L O C K D E F I N I T I O N S */ /* S T A T E M E N T - B L O C K D E F I N I T I O N S */
@ -12,3 +15,5 @@ struct stmt_block {
}; };
/* ALLOCDEF "stmt_block" 5 */ /* ALLOCDEF "stmt_block" 5 */
#endif

View file

@ -19,16 +19,23 @@
#include "Lpars.h" #include "Lpars.h"
#include "align.h" #include "align.h"
#include "level.h" #include "level.h"
#include "ch3.h"
#include "sizes.h" #include "sizes.h"
#include "error.h"
/* Type of previous selector declared with a field width specified, /* Type of previous selector declared with a field width specified,
if any. If a selector is declared with no field with it is set to 0. if any. If a selector is declared with no field with it is set to 0.
*/ */
static field_busy = 0; static int field_busy = 0;
extern char options[]; extern char options[];
char *symbol2str(); char *symbol2str();
int lcm();
static void check_selector(register struct idf *, struct type *);
/* Greatest Common Divisor */
static int gcd(register int , register int );
/* Least Common Multiple */
static int lcm(register int, register int);
/* The semantics of the identification of structure/union tags is /* The semantics of the identification of structure/union tags is
obscure. Some highly regarded compilers are found out to accept, obscure. Some highly regarded compilers are found out to accept,
@ -51,13 +58,13 @@ int lcm();
as well). as well).
*/ */
add_sel(stp, tp, idf, sdefpp, szp, fd) /* this is horrible */ void add_sel( /* this is horrible */
register struct type *stp; /* type of the structure */ register struct type *stp, /* type of the structure */
struct type *tp; /* type of the selector */ struct type *tp, /* type of the selector */
register struct idf *idf; /* idf of the selector */ register struct idf *idf, /* idf of the selector */
struct sdef ***sdefpp; /* address of hook to selector definition */ struct sdef ***sdefpp, /* address of hook to selector definition */
arith *szp; /* pointer to struct size upto here */ arith *szp, /* pointer to struct size upto here */
struct field *fd; struct field *fd)
{ {
/* The selector idf with type tp is added to two chains: the /* The selector idf with type tp is added to two chains: the
selector identification chain starting at idf->id_sdef, selector identification chain starting at idf->id_sdef,
@ -147,12 +154,11 @@ add_sel(stp, tp, idf, sdefpp, szp, fd) /* this is horrible */
} }
} }
check_selector(idf, stp) static void check_selector(register struct idf *idf, struct type *stp)
register struct idf *idf;
struct type *stp; /* the type of the struct */
{ {
/* checks if idf occurs already as a selector in /* checks if idf occurs already as a selector in
struct or union *stp. struct or union *stp. "stp" indicates the type
of the struct.
*/ */
register struct sdef *sdef = stp->tp_sdef; register struct sdef *sdef = stp->tp_sdef;
@ -163,9 +169,7 @@ check_selector(idf, stp)
} }
} }
declare_struct(fund, idf, tpp) void declare_struct(int fund, register struct idf *idf, struct type **tpp)
register struct idf *idf;
struct type **tpp;
{ {
/* A struct, union or enum (depending on fund) with tag (!) /* A struct, union or enum (depending on fund) with tag (!)
idf is declared, and its type (incomplete as it may be) is idf is declared, and its type (incomplete as it may be) is
@ -232,9 +236,9 @@ declare_struct(fund, idf, tpp)
} }
} }
apply_struct(fund, idf, tpp) void apply_struct(int fund,
register struct idf *idf; register struct idf *idf,
struct type **tpp; struct type **tpp)
{ {
/* The occurrence of a struct, union or enum (depending on /* The occurrence of a struct, union or enum (depending on
fund) with tag idf is noted. It may or may not have been fund) with tag idf is noted. It may or may not have been
@ -258,10 +262,9 @@ apply_struct(fund, idf, tpp)
declare_struct(fund, idf, tpp); declare_struct(fund, idf, tpp);
} }
struct sdef * struct sdef *idf2sdef(
idf2sdef(idf, tp) register struct idf *idf,
register struct idf *idf; struct type *tp)
struct type *tp;
{ {
/* The identifier idf is identified as a selector /* The identifier idf is identified as a selector
in the struct tp. in the struct tp.
@ -296,9 +299,7 @@ idf2sdef(idf, tp)
} }
#if 0 #if 0
int int uniq_selector(register struct sdef *idf_sdef)
uniq_selector(idf_sdef)
register struct sdef *idf_sdef;
{ {
/* Returns true if idf_sdef (which is guaranteed to exist) /* Returns true if idf_sdef (which is guaranteed to exist)
is unique for this level, i.e there is no other selector is unique for this level, i.e there is no other selector
@ -324,12 +325,12 @@ uniq_selector(idf_sdef)
#ifndef NOBITFIELD #ifndef NOBITFIELD
arith arith
add_field(szp, fd, fdtpp, idf, stp) add_field(
arith *szp; /* size of struct upto here */ arith *szp, /* size of struct upto here */
register struct field *fd; /* bitfield, containing width */ register struct field *fd, /* bitfield, containing width */
register struct type **fdtpp; /* type of selector */ register struct type **fdtpp, /* type of selector */
struct idf *idf; /* name of selector */ struct idf *idf, /* name of selector */
register struct type *stp; /* current struct descriptor */ register struct type *stp) /* current struct descriptor */
{ {
/* The address where this selector is put is returned. If the /* The address where this selector is put is returned. If the
selector with specified width does not fit in the word, or selector with specified width does not fit in the word, or
@ -438,18 +439,12 @@ add_field(szp, fd, fdtpp, idf, stp)
#endif /* NOBITFIELD */ #endif /* NOBITFIELD */
/* some utilities */ /* some utilities */
int int is_struct_or_union(register int fund)
is_struct_or_union(fund)
register int fund;
{ {
return fund == STRUCT || fund == UNION; return fund == STRUCT || fund == UNION;
} }
/* Greatest Common Divisor static int gcd(register int m, register int n)
*/
int
gcd(m, n)
register int m, n;
{ {
register int r; register int r;
@ -461,11 +456,8 @@ gcd(m, n)
return m; return m;
} }
/* Least Common Multiple
*/ static int lcm(register int m, register int n)
int
lcm(m, n)
register int m, n;
{ {
return m * (n / gcd(m, n)); return m * (n / gcd(m, n));
} }

View file

@ -2,7 +2,17 @@
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright". * See the copyright notice in the ACK home directory, in the file "Copyright".
*/ */
#ifndef STRUCT_H_
#define STRUCT_H_
/* $Id$ */ /* $Id$ */
#include "arith.h"
struct type;
struct idf;
struct field;
/* SELECTOR DESCRIPTOR */ /* SELECTOR DESCRIPTOR */
struct sdef { /* for selectors */ struct sdef { /* for selectors */
@ -27,4 +37,26 @@ struct tag { /* for struct-, union- and enum tags */
/* ALLOCDEF "tag" 10 */ /* ALLOCDEF "tag" 10 */
struct sdef *idf2sdef(); struct sdef *idf2sdef(register struct idf *idf, struct type *tp);
void add_sel(
register struct type *stp, /* type of the structure */
struct type *tp, /* type of the selector */
register struct idf *idf, /* idf of the selector */
struct sdef ***sdefpp, /* address of hook to selector definition */
arith *szp, /* pointer to struct size upto here */
struct field *fd);
void declare_struct(int fund, register struct idf *idf, struct type **tpp);
void apply_struct(int fund, register struct idf *idf, struct type **tpp);
int is_struct_or_union(register int fund);
#ifndef NOBITFIELD
arith
add_field(
arith *szp, /* size of struct upto here */
register struct field *fd, /* bitfield, containing width */
register struct type **fdtpp, /* type of selector */
struct idf *idf, /* name of selector */
register struct type *stp); /* current struct descriptor */
#endif
#endif

View file

@ -23,13 +23,16 @@
#include "expr.h" #include "expr.h"
#include "type.h" #include "type.h"
#include "sizes.h" #include "sizes.h"
#include "switch.h"
#include "eval.h"
#include "ch3.h"
#include "error.h"
extern char options[]; extern char options[];
int density = DENSITY; int density = DENSITY;
compact(nr, low, up) static int compact(int nr, arith low, arith up)
arith low, up;
{ {
/* Careful! up - low might not fit in an arith. And then, /* Careful! up - low might not fit in an arith. And then,
the test "up-low < 0" might also not work to detect this the test "up-low < 0" might also not work to detect this
@ -49,8 +52,7 @@ static struct switch_hdr *switch_stack = 0;
For simplicity, we suppose int_size == word_size. For simplicity, we suppose int_size == word_size.
*/ */
code_startswitch(expp) void code_startswitch(struct expr **expp)
struct expr **expp;
{ {
/* Check the expression, stack a new case header and /* Check the expression, stack a new case header and
fill in the necessary fields. fill in the necessary fields.
@ -85,7 +87,7 @@ code_startswitch(expp)
C_bra(l_table); /* goto start of switch_table */ C_bra(l_table); /* goto start of switch_table */
} }
code_endswitch() void code_endswitch(void)
{ {
register struct switch_hdr *sh = switch_stack; register struct switch_hdr *sh = switch_stack;
register label tablabel; register label tablabel;
@ -158,9 +160,7 @@ code_endswitch()
unstack_stmt(); unstack_stmt();
} }
void void code_case(struct expr *expr)
code_case(expr)
struct expr *expr;
{ {
register arith val; register arith val;
register struct case_entry *ce; register struct case_entry *ce;
@ -227,8 +227,7 @@ code_case(expr)
} }
} }
void void code_default(void)
code_default()
{ {
register struct switch_hdr *sh = switch_stack; register struct switch_hdr *sh = switch_stack;

View file

@ -2,7 +2,16 @@
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright". * See the copyright notice in the ACK home directory, in the file "Copyright".
*/ */
#ifndef SWITCH_H_
#define SWITCH_H_
/* $Id$ */ /* $Id$ */
#include "arith.h"
struct type;
struct expr;
/* S W I T C H - T A B L E - S T R U C T U R E */ /* S W I T C H - T A B L E - S T R U C T U R E */
struct switch_hdr { struct switch_hdr {
@ -27,3 +36,12 @@ struct case_entry {
}; };
/* ALLOCDEF "case_entry" 20 */ /* ALLOCDEF "case_entry" 20 */
void code_startswitch(struct expr **expp);
void code_endswitch(void);
void code_case(struct expr *expr);
void code_default(void);
#endif

View file

@ -0,0 +1,3 @@
/{[A-Z]/!d
s/.*{\(.*\),.*\(".*"\).*$/ case \1 :\
return \2;/

View file

@ -0,0 +1,16 @@
default:
if (tok <= 0) return "end of file";
if (tok < 040 || tok >= 0177) {
return "bad token";
}
/* fall through */
case '\n':
case '\f':
case '\v':
case '\r':
case '\t':
index = (index+2) & (SIZBUF-1);
buf[index] = tok;
return &buf[index];
}
}

View file

@ -0,0 +1,12 @@
/* Generated by make.tokcase */
/* $Id$ */
#include "Lpars.h"
char *symbol2str(int tok)
{
#define SIZBUF 8
/* allow for a few invocations in f.i. an argument list */
static char buf[SIZBUF];
static int index;
switch (tok) {

View file

@ -11,6 +11,7 @@
#include "LLlex.h" #include "LLlex.h"
#include "tokenname.h" #include "tokenname.h"
#include "Lpars.h" #include "Lpars.h"
#include "error.h"
/* To centralize the declaration of %tokens, their presence in this /* To centralize the declaration of %tokens, their presence in this
file is taken as their declaration. The Makefile will produce file is taken as their declaration. The Makefile will produce
@ -132,8 +133,7 @@ struct tokenname tkfunny[] = { /* internal keywords */
}; };
#endif /* ____ */ #endif /* ____ */
reserve(resv) void reserve(register struct tokenname resv[])
register struct tokenname resv[];
{ {
/* The names of the tokens described in resv are entered /* The names of the tokens described in resv are entered
as reserved words. as reserved words.

View file

@ -4,6 +4,8 @@
*/ */
/* $Id$ */ /* $Id$ */
/* TOKENNAME DEFINITION */ /* TOKENNAME DEFINITION */
#ifndef TOKENNAME_H_
#define TOKENNAME_H_
struct tokenname { /* Used for defining the name of a struct tokenname { /* Used for defining the name of a
token as identified by its symbol token as identified by its symbol
@ -11,3 +13,7 @@ struct tokenname { /* Used for defining the name of a
int tn_symbol; int tn_symbol;
char *tn_name; char *tn_name;
}; };
void reserve(register struct tokenname resv[]);
#endif /* TOKENNAME_H_ */

View file

@ -16,68 +16,59 @@
#include "sizes.h" #include "sizes.h"
#include "align.h" #include "align.h"
#include "decspecs.h" #include "decspecs.h"
#include "error.h"
extern struct type *function_of(), *array_of();
#ifndef NOBITFIELD
extern struct type *field_of();
#endif /* NOBITFIELD */
/* To be created dynamically in main() from defaults or from command /* To be created dynamically in main() from defaults or from command
line parameters. line parameters.
*/ */
struct type struct type *schar_type, *uchar_type, *short_type, *ushort_type, *word_type,
*schar_type, *uchar_type, *uword_type, *int_type, *uint_type, *long_type, *ulong_type,
*short_type, *ushort_type, *float_type, *double_type, *lngdbl_type, *void_type, *string_type,
*word_type, *uword_type, *funint_type, *error_type;
*int_type, *uint_type,
*long_type, *ulong_type,
*float_type, *double_type, *lngdbl_type,
*void_type,
*string_type, *funint_type, *error_type;
struct type *pa_type; /* Pointer-Arithmetic type */ struct type *pa_type; /* Pointer-Arithmetic type */
struct type * struct type *create_type(int fund)
create_type(fund)
int fund;
{ {
/* A brand new struct type is created, and its tp_fund set /* A brand new struct type is created, and its tp_fund set
to fund. to fund.
*/ */
register struct type *ntp = new_type(); register struct type *ntp = new_type();
ntp->tp_fund = fund; ntp->tp_fund = fund;
ntp->tp_size = (arith)-1; ntp->tp_size = (arith) -1;
return ntp; return ntp;
} }
struct type * struct type *promoted_type(struct type *tp)
promoted_type(tp)
struct type *tp;
{ {
if (tp->tp_fund == CHAR || tp->tp_fund == SHORT) { if (tp->tp_fund == CHAR || tp->tp_fund == SHORT)
{
if (tp->tp_unsigned && (int) tp->tp_size == (int) int_size) if (tp->tp_unsigned && (int) tp->tp_size == (int) int_size)
return uint_type; return uint_type;
else return int_type; else
} else if (tp->tp_fund == FLOAT) return int_type;
}
else if (tp->tp_fund == FLOAT)
return double_type; return double_type;
else return tp; else
return tp;
} }
struct type * struct type *construct_type(int fund, register struct type *tp, int qual,
construct_type(fund, tp, qual, count, pl) arith count, /* for fund == ARRAY only */
register struct type *tp; register struct proto *pl)
register struct proto *pl;
arith count; /* for fund == ARRAY only */
int qual;
{ {
/* fund must be a type constructor: FIELD, FUNCTION, POINTER or /* fund must be a type constructor: FIELD, FUNCTION, POINTER or
ARRAY. The pointer to the constructed type is returned. ARRAY. The pointer to the constructed type is returned.
*/ */
register struct type *dtp; register struct type *dtp;
switch (fund) { switch (fund)
{
#ifndef NOBITFIELD #ifndef NOBITFIELD
case FIELD: case FIELD:
dtp = field_of(tp, qual); dtp = field_of(tp, qual);
@ -85,11 +76,13 @@ construct_type(fund, tp, qual, count, pl)
#endif /* NOBITFIELD */ #endif /* NOBITFIELD */
case FUNCTION: case FUNCTION:
if (tp->tp_fund == FUNCTION) { if (tp->tp_fund == FUNCTION)
{
error("function cannot yield function"); error("function cannot yield function");
return error_type; return error_type;
} }
if (tp->tp_fund == ARRAY) { if (tp->tp_fund == ARRAY)
{
error("function cannot yield array"); error("function cannot yield array");
return error_type; return error_type;
} }
@ -100,7 +93,8 @@ construct_type(fund, tp, qual, count, pl)
dtp = pointer_to(tp, qual); dtp = pointer_to(tp, qual);
break; break;
case ARRAY: case ARRAY:
if (tp->tp_fund == VOID) { if (tp->tp_fund == VOID)
{
error("cannot construct array of void"); error("cannot construct array of void");
count = (arith) -1; count = (arith) -1;
} }
@ -113,14 +107,10 @@ construct_type(fund, tp, qual, count, pl)
return dtp; return dtp;
} }
struct type * struct type *function_of(register struct type *tp, struct proto *pl, int qual)
function_of(tp, pl, qual)
register struct type *tp;
struct proto *pl;
int qual;
{ {
#if 0 #if 0
/* See comment below */ /* See comment below */
register struct type *dtp = tp->tp_function; register struct type *dtp = tp->tp_function;
#else #else
register struct type *dtp; register struct type *dtp;
@ -128,30 +118,31 @@ function_of(tp, pl, qual)
/* look for a type with the right qualifier */ /* look for a type with the right qualifier */
#if 0 #if 0
/* the code doesn't work in the following case: /* the code doesn't work in the following case:
int func(); int func();
int func(int a, int b) { return q(a); } int func(int a, int b) { return q(a); }
because updating the type works inside the data-structures for that type because updating the type works inside the data-structures for that type
thus, a new type is created for very function. This may change in the thus, a new type is created for very function. This may change in the
future, when declarations with empty parameter lists become obsolete. future, when declarations with empty parameter lists become obsolete.
When it does, change type.str, decspecs.c, and this routine. Search for When it does, change type.str, decspecs.c, and this routine. Search for
the function_of pattern to find the places. the function_of pattern to find the places.
*/ */
while (dtp && (dtp->tp_typequal != qual || dtp->tp_proto != pl)) while (dtp && (dtp->tp_typequal != qual || dtp->tp_proto != pl))
dtp = dtp->next; dtp = dtp->next;
#else #else
dtp = 0; dtp = 0;
#endif #endif
if (!dtp) { if (!dtp)
{
dtp = create_type(FUNCTION); dtp = create_type(FUNCTION);
dtp->tp_up = tp; dtp->tp_up = tp;
dtp->tp_size = -1; /* function size is not known */ dtp->tp_size = -1; /* function size is not known */
dtp->tp_align = pointer_align; dtp->tp_align = pointer_align;
dtp->tp_typequal = qual; dtp->tp_typequal = qual;
dtp->tp_proto = pl; dtp->tp_proto = pl;
#if 0 #if 0
/* See comment above */ /* See comment above */
dtp->next = tp->tp_function; dtp->next = tp->tp_function;
tp->tp_function = dtp; tp->tp_function = dtp;
#endif #endif
@ -159,10 +150,7 @@ function_of(tp, pl, qual)
return dtp; return dtp;
} }
struct type * struct type *pointer_to(register struct type *tp, int qual)
pointer_to(tp, qual)
register struct type *tp;
int qual;
{ {
register struct type *dtp = tp->tp_pointer; register struct type *dtp = tp->tp_pointer;
@ -170,7 +158,8 @@ pointer_to(tp, qual)
while (dtp && dtp->tp_typequal != qual) while (dtp && dtp->tp_typequal != qual)
dtp = dtp->next; dtp = dtp->next;
if (!dtp) { if (!dtp)
{
dtp = create_type(POINTER); dtp = create_type(POINTER);
dtp->tp_unsigned = 1; dtp->tp_unsigned = 1;
dtp->tp_up = tp; dtp->tp_up = tp;
@ -183,11 +172,7 @@ pointer_to(tp, qual)
return dtp; return dtp;
} }
struct type * struct type * array_of(register struct type *tp, arith count, int qual)
array_of(tp, count, qual)
register struct type *tp;
arith count;
int qual;
{ {
register struct type *dtp = tp->tp_array; register struct type *dtp = tp->tp_array;
@ -195,7 +180,8 @@ array_of(tp, count, qual)
while (dtp && (dtp->tp_nel != count || dtp->tp_typequal != qual)) while (dtp && (dtp->tp_nel != count || dtp->tp_typequal != qual))
dtp = dtp->next; dtp = dtp->next;
if (!dtp) { if (!dtp)
{
dtp = create_type(ARRAY); dtp = create_type(ARRAY);
dtp->tp_up = tp; dtp->tp_up = tp;
dtp->tp_nel = count; dtp->tp_nel = count;
@ -203,19 +189,18 @@ array_of(tp, count, qual)
dtp->tp_typequal = qual; dtp->tp_typequal = qual;
dtp->next = tp->tp_array; dtp->next = tp->tp_array;
tp->tp_array = dtp; tp->tp_array = dtp;
if (tp->tp_size >= 0 && count >= 0) { if (tp->tp_size >= 0 && count >= 0)
{
dtp->tp_size = count * tp->tp_size; dtp->tp_size = count * tp->tp_size;
} }
else dtp->tp_size = -1; else
dtp->tp_size = -1;
} }
return dtp; return dtp;
} }
#ifndef NOBITFIELD #ifndef NOBITFIELD
struct type * struct type * field_of(register struct type *tp, int qual)
field_of(tp, qual)
register struct type *tp;
int qual;
{ {
register struct type *dtp = create_type(FIELD); register struct type *dtp = create_type(FIELD);
@ -227,53 +212,47 @@ field_of(tp, qual)
} }
#endif /* NOBITFIELD */ #endif /* NOBITFIELD */
arith arith size_of_type(struct type *tp, char nm[])
size_of_type(tp, nm)
struct type *tp;
char nm[];
{ {
arith sz = tp->tp_size; arith sz = tp->tp_size;
if (sz < 0) { if (sz < 0)
{
error("size of %s unknown", nm); error("size of %s unknown", nm);
sz = (arith)1; sz = (arith) 1;
} }
return sz; return sz;
} }
idf2type(idf, tpp) void idf2type(struct idf *idf, struct type **tpp)
struct idf *idf;
struct type **tpp;
{ {
/* Decoding a typedef-ed identifier or basic type: if the /* Decoding a typedef-ed identifier or basic type: if the
size is yet unknown we have to make copy of the type size is yet unknown we have to make copy of the type
descriptor to prevent garbage at the initialisation of descriptor to prevent garbage at the initialisation of
arrays with unknown size. arrays with unknown size.
*/ */
register struct type *tp = idf->id_def->df_type; register struct type *tp = idf->id_def->df_type;
if (*tpp) error("multiple types in declaration"); if (*tpp)
if ( tp->tp_size < (arith)0 && tp->tp_fund == ARRAY) { error("multiple types in declaration");
if (tp->tp_size < (arith) 0 && tp->tp_fund == ARRAY)
{
*tpp = new_type(); *tpp = new_type();
**tpp = *tp; **tpp = *tp;
/* this is really a structure assignment, AAGH!!! */ /* this is really a structure assignment, AAGH!!! */
} }
else { else
{
*tpp = tp; *tpp = tp;
} }
} }
arith arith align(arith pos, int al)
align(pos, al)
arith pos;
int al;
{ {
return ((pos + al - 1) / al) * al; return ((pos + al - 1) / al) * al;
} }
struct type * struct type * standard_type(int fund, int sgn, int algn, arith sz)
standard_type(fund, sgn, algn, sz)
int algn; arith sz;
{ {
register struct type *tp = create_type(fund); register struct type *tp = create_type(fund);
@ -284,25 +263,29 @@ standard_type(fund, sgn, algn, sz)
return tp; return tp;
} }
completed(tp) void completed(struct type *tp)
struct type *tp;
{ {
register struct type *atp = tp->tp_array; register struct type *atp = tp->tp_array;
register struct type *etp = tp; register struct type *etp = tp;
switch(etp->tp_fund) { switch (etp->tp_fund)
{
case STRUCT: case STRUCT:
case UNION: case UNION:
case ENUM: case ENUM:
while (etp = etp->next) { while (etp = etp->next)
if (! etp->tp_sdef) etp->tp_sdef = tp->tp_sdef; {
if (!etp->tp_sdef)
etp->tp_sdef = tp->tp_sdef;
etp->tp_size = tp->tp_size; etp->tp_size = tp->tp_size;
etp->tp_align = tp->tp_align; etp->tp_align = tp->tp_align;
} }
break; break;
} }
while (atp) { while (atp)
if (atp->tp_nel >= 0) { {
if (atp->tp_nel >= 0)
{
atp->tp_size = atp->tp_nel * tp->tp_size; atp->tp_size = atp->tp_nel * tp->tp_size;
} }
atp = atp->next; atp = atp->next;

View file

@ -4,8 +4,13 @@
*/ */
/* $Id$ */ /* $Id$ */
/* TYPE DESCRIPTOR */ /* TYPE DESCRIPTOR */
#ifndef TYPE_H_
#define TYPE_H_
#include "parameters.h" #include "parameters.h"
#include "arith.h"
struct type { struct type {
struct type *next; /* used for ARRAY and for qualifiers */ struct type *next; /* used for ARRAY and for qualifiers */
@ -59,13 +64,6 @@ struct type {
#define TQ_VOLATILE 0x01 #define TQ_VOLATILE 0x01
#define TQ_CONST 0x02 #define TQ_CONST 0x02
extern struct type
*create_type(), *standard_type(), *construct_type(), *pointer_to(),
*array_of(), *function_of(), *promoted_type();
#ifndef NOBITFIELD
extern struct type *field_of();
#endif /* NOBITFIELD */
extern struct type extern struct type
*schar_type, *uchar_type, *schar_type, *uchar_type,
@ -79,6 +77,24 @@ extern struct type
extern struct type *pa_type; /* type.c */ extern struct type *pa_type; /* type.c */
extern arith size_of_type(), align(); struct type *create_type(int fund);
struct type *promoted_type(struct type *tp);
struct type *construct_type(int fund, register struct type *tp, int qual,
arith count, /* for fund == ARRAY only */
register struct proto *pl);
struct type *function_of(register struct type *tp, struct proto *pl, int qual);
struct type *pointer_to(register struct type *tp, int qual);
struct type * array_of(register struct type *tp, arith count, int qual);
#ifndef NOBITFIELD
struct type * field_of(register struct type *tp, int qual);
#endif /* NOBITFIELD */
arith size_of_type(struct type *tp, char nm[]);
void idf2type(struct idf *idf, struct type **tpp);
arith align(arith pos, int al);
struct type * standard_type(int fund, int sgn, int algn, arith sz);
void completed(struct type *tp);
/* ALLOCDEF "type" 50 */ /* ALLOCDEF "type" 50 */
#endif

View file

@ -41,16 +41,14 @@ static int loc_id;
extern char options[]; extern char options[];
LocalInit() void LocalInit(void)
{ {
#ifdef USE_TMP #ifdef USE_TMP
C_insertpart(loc_id = C_getid()); C_insertpart(loc_id = C_getid());
#endif /* USE_TMP */ #endif /* USE_TMP */
} }
arith arith LocalSpace(arith sz, int al)
LocalSpace(sz, al)
arith sz;
{ {
register struct stack_level *stl = local_level; register struct stack_level *stl = local_level;
@ -61,9 +59,7 @@ LocalSpace(sz, al)
#define TABSIZ 32 #define TABSIZ 32
static struct localvar *regs[TABSIZ]; static struct localvar *regs[TABSIZ];
arith arith NewLocal(arith sz, int al, int regtype, int sc)
NewLocal(sz, al, regtype, sc)
arith sz;
{ {
register struct localvar *tmp = FreeTmps; register struct localvar *tmp = FreeTmps;
struct localvar *prev = 0; struct localvar *prev = 0;
@ -98,8 +94,7 @@ NewLocal(sz, al, regtype, sc)
return tmp->t_offset; return tmp->t_offset;
} }
FreeLocal(off) void FreeLocal(arith off)
arith off;
{ {
int index = (int) (off >> 2) & (TABSIZ - 1); int index = (int) (off >> 2) & (TABSIZ - 1);
register struct localvar *tmp = regs[index]; register struct localvar *tmp = regs[index];
@ -117,7 +112,7 @@ FreeLocal(off)
} }
} }
LocalFinish() void LocalFinish(void)
{ {
register struct localvar *tmp, *tmp1; register struct localvar *tmp, *tmp1;
register int i; register int i;
@ -163,9 +158,7 @@ LocalFinish()
#endif #endif
} }
void void RegisterAccount(arith offset, arith size, int regtype, int sc)
RegisterAccount(offset, size, regtype, sc)
arith offset, size;
{ {
register struct localvar *p; register struct localvar *p;
int index; int index;
@ -183,9 +176,7 @@ RegisterAccount(offset, size, regtype, sc)
regs[index] = p; regs[index] = p;
} }
static struct localvar * static struct localvar *find_reg(arith off)
find_reg(off)
arith off;
{ {
register struct localvar *p = regs[(int)(off >> 2) & (TABSIZ - 1)]; register struct localvar *p = regs[(int)(off >> 2) & (TABSIZ - 1)];
@ -193,8 +184,7 @@ find_reg(off)
return p; return p;
} }
LoadLocal(off, sz) void LoadLocal(arith off, arith sz)
arith off, sz;
{ {
register struct localvar *p = find_reg(off); register struct localvar *p = find_reg(off);
@ -213,8 +203,7 @@ LoadLocal(off, sz)
} }
} }
StoreLocal(off, sz) void StoreLocal(arith off, arith sz)
arith off, sz;
{ {
register struct localvar *p = find_reg(off); register struct localvar *p = find_reg(off);
@ -234,8 +223,7 @@ StoreLocal(off, sz)
} }
#ifndef LINT #ifndef LINT
AddrLocal(off) void AddrLocal(arith off)
arith off;
{ {
register struct localvar *p = find_reg(off); register struct localvar *p = find_reg(off);

View file

@ -1,3 +1,8 @@
#ifndef UTIL_H_
#define UTIL_H_
#include "arith.h"
struct localvar { struct localvar {
struct localvar *next; struct localvar *next;
arith t_offset; /* offset from LocalBase */ arith t_offset; /* offset from LocalBase */
@ -9,3 +14,18 @@ struct localvar {
}; };
/* ALLOCDEF "localvar" 10 */ /* ALLOCDEF "localvar" 10 */
void LocalInit(void);
arith LocalSpace(arith sz, int al);
arith NewLocal(arith sz, int al, int regtype, int sc);
void FreeLocal(arith off);
void LocalFinish(void);
void RegisterAccount(arith offset, arith size, int regtype, int sc);
void LoadLocal(arith off, arith sz);
void StoreLocal(arith off, arith sz);
#ifndef LINT
void AddrLocal(arith off);
#endif
#endif

View file

@ -0,0 +1,15 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-09
*
*/
#ifndef CH3BIN_H_
#define CH3BIN_H_
#include "arith.h"
void ch3bin(register arith *pval, int *pis_uns, int oper, register arith val, int is_uns);
#endif /* CH3BIN_H_ */

View file

@ -0,0 +1,15 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-09
*
*/
#ifndef CH3MON_H_
#define CH3MON_H_
#include "arith.h"
void ch3mon(int oper, register arith *pval, int *puns);
#endif /* CH3MON_H_ */

View file

@ -0,0 +1,27 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-09
*
*/
#ifndef DOMACRO_H_
#define DOMACRO_H_
struct idf;
void macro_def(register struct idf* id, char* text, int nformals, int length, int flags);
void do_undef(char* argstr);
/* Control line interpreter. The '#' has already
been read by the lexical analyzer by which this function is called.
The token appearing directly after the '#' is obtained by calling
the basic lexical analyzing function GetToken() and is interpreted
to perform the action belonging to that token.
An error message is produced when the token is not recognized.
Pragma's are handled by do_pragma(). They are passed on to the
compiler.
*/
void domacro(void);
char* GetIdentifier(int skiponerr);
#endif /* DOMACRO_H_ */

42
lang/cem/cpp.ansi/error.h Normal file
View file

@ -0,0 +1,42 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-09
*
*/
#ifndef ERROR_H_
#define ERROR_H_
#if __STDC__
/*VARARGS*/
void error(char *fmt, ...);
/*VARARGS*/
void warning(char *fmt, ...);
/*VARARGS*/
void strict(char *fmt, ...);
/*VARARGS*/
void crash(char *fmt, ...);
/*VARARGS*/
void fatal(char *fmt, ...);
#else
/*VARARGS*/
void error(va_alist);
va_dcl
/*VARARGS*/
void warning(va_alist);
va_dcl
/*VARARGS*/
void strict(va_alist);
va_dcl
/*VARARGS*/
void crash(va_alist);
va_dcl
/*VARARGS*/
void fatal(va_alist);
va_dcl
#endif
#endif /* ERROR_H_ */

14
lang/cem/cpp.ansi/expr.h Normal file
View file

@ -0,0 +1,14 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-09
*
*/
#ifndef EXPR_H_
#define EXPR_H_
/* The rank of the operator oper is returned. */
int rank_of(int oper);
#endif /* EXPR_H_ */

13
lang/cem/cpp.ansi/init.h Normal file
View file

@ -0,0 +1,13 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-09
*
*/
#ifndef INIT_H_
#define INIT_H_
void init_pp(void);
#endif /* INIT_H_ */

View file

@ -0,0 +1,13 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-09
*
*/
#ifndef OPTIONS_H_
#define OPTIONS_H_
void do_option(char *text);
#endif /* OPTIONS_H_ */

View file

@ -0,0 +1,14 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-09
*
*/
#ifndef PREPROCESS_H_
#define PREPROCESS_H_
void do_pragma(void);
void preprocess(char *fn);
#endif /* PREPROCESS_H_ */

18
lang/cem/cpp.ansi/skip.h Normal file
View file

@ -0,0 +1,18 @@
/* Copyright (c) 2019 ACK Project.
* See the copyright notice in the ACK home directory,
* in the file "Copyright".
*
* Created on: 2019-02-09
*
*/
#ifndef SKIP_H_
#define SKIP_H_
int SkipToNewLine(void);
/* Skips skips any white space and returns the first
non-space character.
*/
int skipspaces(register int ch, int skipnl);
#endif /* SKIP_H_ */

View file

@ -17,6 +17,7 @@
#include <em_arith.h> #include <em_arith.h>
#include <em_label.h> #include <em_label.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#include "LLlex.h" #include "LLlex.h"
@ -32,7 +33,7 @@
#include "type.h" #include "type.h"
#ifdef DEBUG #ifdef DEBUG
long sys_filesize(); size_t sys_filesize();
#endif #endif
t_idf* DefId; t_idf* DefId;

View file

@ -1,13 +1,13 @@
L_ACK_MODULES_ALLOC = { L_ACK_MODULES_ALLOC = {
$PWD/Malloc.c, $PWD/Malloc.c,
$PWD/Salloc.c, $PWD/Salloc.c,
$PWD/Srealloc.c, $PWD/Srealloc.c,
$PWD/Realloc.c, $PWD/Realloc.c,
$PWD/botch.c, $PWD/botch.c,
$PWD/clear.c, $PWD/clear.c,
$PWD/st_alloc.c, $PWD/st_alloc.c,
$PWD/std_alloc.c, $PWD/std_alloc.c,
$PWD/No_Mem.c, $PWD/No_Mem.c,
$PWD/alloc.h $PWD/alloc.h
}; };

View file

@ -17,9 +17,7 @@ extern char *malloc();
#endif #endif
#include "alloc.h" #include "alloc.h"
char * char *Malloc(unsigned int sz)
Malloc(sz)
unsigned int sz;
{ {
register char *res = malloc(sz); register char *res = malloc(sz);

View file

@ -1,14 +1,15 @@
/* $Id$ */ /* $Id$ */
/* /*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright". * See the copyright notice in the ACK home directory, in the file "Copyright".
*/ */
#include <system.h> #include <stdio.h>
#include <stdlib.h>
#include "alloc.h" #include "alloc.h"
void void No_Mem(void)
No_Mem()
{ {
sys_write(STDERR, "Out of memory\n", 14); fprintf(stderr,"Out of memory\n");
sys_stop(S_EXIT); exit(1);
} }

View file

@ -19,10 +19,7 @@ extern char *realloc();
#include "alloc.h" #include "alloc.h"
char * char *Realloc(char ptr[], unsigned int sz)
Realloc(ptr, sz)
char ptr[];
unsigned int sz;
{ {
register char *mptr; register char *mptr;

View file

@ -19,10 +19,7 @@ extern char *malloc();
#include "alloc.h" #include "alloc.h"
char * char *Salloc(register char *str, register unsigned int sz)
Salloc(str, sz)
register char *str;
register unsigned int sz;
{ {
/* Salloc() is not a primitive function: it just allocates a /* Salloc() is not a primitive function: it just allocates a
piece of storage and copies a given string into it. piece of storage and copies a given string into it.

View file

@ -12,10 +12,7 @@
#include "alloc.h" #include "alloc.h"
char * char *Srealloc(char str[], unsigned int sz)
Srealloc(str, sz)
char str[];
unsigned int sz;
{ {
return Realloc(str, sz); return Realloc(str, sz);
} }

View file

@ -1,107 +1,82 @@
.TH ALLOC 3 "$Revision$" .TH ALLOC 3 "$Revision$"
.ad .ad
.SH NAME .SH NAME
Malloc, Salloc, Realloc, Srealloc, st_alloc, st_free\ \-\ low level memory allocation routines Malloc, Salloc, Realloc, Srealloc, st_alloc, st_free\ \-\ low level memory allocation routines
.SH SYNOPSIS .SH SYNOPSIS
.B #include <alloc.h> .B #include <alloc.h>
.PP .PP
.B char *Malloc(size) .B char *Malloc(unsigned int size)
.br .PP
.B unsigned int size; .B char *Salloc(char *str, unsigned int size)
.PP .PP
.B char *Salloc(str, size) .B char *Realloc(char *buf, unsigned int size)
.br .PP
.B char *str; .B char *Srealloc(char *str, unsigned int size)
.B unsigned int size; .PP
.PP .B char *st_alloc(char **phead, unsigned int size, int count)
.B char *Realloc(ptr, size) .PP
.B char *buf; .B st_free(char *ptr, char **phead, unsigned int size)
.B unsigned int size; .PP
.PP .B void clear(char *ptr, unsigned int size)
.B char *Srealloc(str, size) .PP
.br .void No_Mem()
.B char *str; .PP
.br .SH DESCRIPTION
.B unsigned int size; This set of routines provides a checking memory allocation mechanism.
.PP .PP
.B char *st_alloc(phead, size, count) \fIMalloc\fR returns a pointer to a block of at least \fIsize\fR
.br bytes, beginning on a boundary suitable for any data type.
.B char **phead; .PP
.br \fISalloc\fR returns a pointer to a block of at least \fIsize\fR
.B unsigned int size; bytes, initialized with the null-terminated string \fIstr\fR.
.PP .PP
.B st_free(ptr, phead, size) \fIRealloc\fR changes the size of
.br the block at \fIbuf\fR to \fIsize\fR bytes, and returns a pointer to the
.B char *ptr; (possibly moved) block. If \fIbuf\fP is a null pointer, \fIRealloc\fP
.br behaves as \fIMalloc\fP.
.B char **phead; .PP
.br \fISrealloc\fR reallocates
.B unsigned int size; the string at \fIstr\fR to \fIsize\fR bytes.
.PP It actually does the same as \fIRealloc\fP, and exists only for
.B void clear(ptr, size) backwards compatibility.
.br .PP
.B char *ptr; All these routines use \fImalloc\fR and \fIrealloc\fR.
.br The routine \fIfree\fR can be used on pointers returned by these routines.
.B unsigned int size; .PP
.PP \fISt_alloc\fR and \fIst_free\fR provide a mechanism for maintaining free lists
.void No_Mem() of structures.
.PP \fISt_alloc\fR takes three parameters: \fIphead\fR is a pointer to a field
.SH DESCRIPTION containing the head of the free list, \fIsize\fR contains the size of the
This set of routines provides a checking memory allocation mechanism. structures, and \fIcount\fR indicates how many new structures must be allocated
.PP in case the free list is exhausted.
\fIMalloc\fR returns a pointer to a block of at least \fIsize\fR It returns a pointer to a zero-initialized structure.
bytes, beginning on a boundary suitable for any data type. \fISt_free\fR also takes three parameters: \fIptr\fR is a pointer to
.PP the structure to be freed, \fIphead\fR is again a pointer to a field
\fISalloc\fR returns a pointer to a block of at least \fIsize\fR containing the head of the free list, and \fIsize\fR again contains the size
bytes, initialized with the null-terminated string \fIstr\fR. of the structures.
.PP These last two routines are best used in a macro.
\fIRealloc\fR changes the size of .PP
the block at \fIbuf\fR to \fIsize\fR bytes, and returns a pointer to the \fIClear\fR clears \fIsize\fR bytes, starting at \fIptr\fR.
(possibly moved) block. If \fIbuf\fP is a null pointer, \fIRealloc\fP .SH FILES
behaves as \fIMalloc\fP. .nf
.PP ~em/modules/h/alloc.h
\fISrealloc\fR reallocates ~em/modules/lib/liballoc.a
the string at \fIstr\fR to \fIsize\fR bytes. .fi
It actually does the same as \fIRealloc\fP, and exists only for .SH "MODULES USED"
backwards compatibility. system(3)
.PP .SH "SEE ALSO"
All these routines use \fImalloc\fR and \fIrealloc\fR. malloc(3)
The routine \fIfree\fR can be used on pointers returned by these routines. .SH DIAGNOSTICS
.PP \fIMalloc\fR, \fISalloc\fR, \fIRealloc\fP, \fISrealloc\fR, and \fIst_alloc\fR
\fISt_alloc\fR and \fIst_free\fR provide a mechanism for maintaining free lists call a routine \fINo_Mem\fR if there is no memory available. This routine
of structures. is not supposed to return. A default one, that
\fISt_alloc\fR takes three parameters: \fIphead\fR is a pointer to a field gives an error message and stops execution, is provided.
containing the head of the free list, \fIsize\fR contains the size of the .SH BUGS
structures, and \fIcount\fR indicates how many new structures must be allocated The
in case the free list is exhausted. .I st_alloc
It returns a pointer to a zero-initialized structure. mechanism only works for structures that are large enough to contain one
\fISt_free\fR also takes three parameters: \fIptr\fR is a pointer to pointer.
the structure to be freed, \fIphead\fR is again a pointer to a field Also,
containing the head of the free list, and \fIsize\fR again contains the size .I st_free
of the structures. actually is a macro, and references its arguments more than once, so they
These last two routines are best used in a macro. better not have side-effects.
.PP
\fIClear\fR clears \fIsize\fR bytes, starting at \fIptr\fR.
.SH FILES
.nf
~em/modules/h/alloc.h
~em/modules/lib/liballoc.a
.fi
.SH "MODULES USED"
system(3)
.SH "SEE ALSO"
malloc(3)
.SH DIAGNOSTICS
\fIMalloc\fR, \fISalloc\fR, \fIRealloc\fP, \fISrealloc\fR, and \fIst_alloc\fR
call a routine \fINo_Mem\fR if there is no memory available. This routine
is not supposed to return. A default one, that
gives an error message and stops execution, is provided.
.SH BUGS
The
.I st_alloc
mechanism only works for structures that are large enough to contain one
pointer.
Also,
.I st_free
actually is a macro, and references its arguments more than once, so they
better not have side-effects.

View file

@ -9,10 +9,7 @@
#include "alloc.h" #include "alloc.h"
void void botch(register char *ptr, register unsigned int n)
botch(ptr, n)
register char *ptr;
register unsigned int n;
{ {
while (n >= sizeof (long)) { while (n >= sizeof (long)) {
/* high-speed botch loop */ /* high-speed botch loop */

Some files were not shown because too many files have changed in this diff Show more