commit
d41ba12679
|
@ -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;
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
|
@ -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();
|
||||||
|
|
20
lang/cem/cemcom.ansi/blocks.h
Normal file
20
lang/cem/cemcom.ansi/blocks.h
Normal 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_ */
|
|
@ -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:
|
||||||
|
|
29
lang/cem/cemcom.ansi/ch3.h
Normal file
29
lang/cem/cemcom.ansi/ch3.h
Normal 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_ */
|
|
@ -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
|
||||||
|
|
21
lang/cem/cemcom.ansi/ch3bin.h
Normal file
21
lang/cem/cemcom.ansi/ch3bin.h
Normal 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_ */
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
22
lang/cem/cemcom.ansi/ch3mon.h
Normal file
22
lang/cem/cemcom.ansi/ch3mon.h
Normal 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_ */
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
15
lang/cem/cemcom.ansi/conversion.h
Normal file
15
lang/cem/cemcom.ansi/conversion.h
Normal 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_ */
|
|
@ -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;
|
||||||
|
|
17
lang/cem/cemcom.ansi/cstoper.h
Normal file
17
lang/cem/cemcom.ansi/cstoper.h
Normal 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_ */
|
|
@ -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;
|
||||||
|
|
19
lang/cem/cemcom.ansi/dataflow.h
Normal file
19
lang/cem/cemcom.ansi/dataflow.h
Normal 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
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
28
lang/cem/cemcom.ansi/declarator.h
Normal file
28
lang/cem/cemcom.ansi/declarator.h
Normal 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_ */
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
16
lang/cem/cemcom.ansi/domacro.h
Normal file
16
lang/cem/cemcom.ansi/domacro.h
Normal 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_ */
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
94
lang/cem/cemcom.ansi/error.h
Normal file
94
lang/cem/cemcom.ansi/error.h
Normal 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_ */
|
|
@ -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
|
|
@ -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);
|
||||||
|
|
37
lang/cem/cemcom.ansi/eval.h
Normal file
37
lang/cem/cemcom.ansi/eval.h
Normal 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_ */
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
@ -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; }
|
||||||
|
;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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_ */
|
|
@ -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
|
||||||
|
|
15
lang/cem/cemcom.ansi/fltcstoper.h
Normal file
15
lang/cem/cemcom.ansi/fltcstoper.h
Normal 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_ */
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
1
lang/cem/cemcom.ansi/next.str
Normal file
1
lang/cem/cemcom.ansi/next.str
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "parameters.h"
|
|
@ -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.
|
||||||
|
|
13
lang/cem/cemcom.ansi/options.h
Normal file
13
lang/cem/cemcom.ansi/options.h
Normal 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_ */
|
|
@ -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
|
||||||
|
|
13
lang/cem/cemcom.ansi/pragma.h
Normal file
13
lang/cem/cemcom.ansi/pragma.h
Normal 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_ */
|
|
@ -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 */
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
13
lang/cem/cemcom.ansi/skip.h
Normal file
13
lang/cem/cemcom.ansi/skip.h
Normal 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_ */
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
20
lang/cem/cemcom.ansi/stab.h
Normal file
20
lang/cem/cemcom.ansi/stab.h
Normal 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_ */
|
|
@ -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));
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
3
lang/cem/cemcom.ansi/tokcase.sed
Normal file
3
lang/cem/cemcom.ansi/tokcase.sed
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
/{[A-Z]/!d
|
||||||
|
s/.*{\(.*\),.*\(".*"\).*$/ case \1 :\
|
||||||
|
return \2;/
|
16
lang/cem/cemcom.ansi/tokcasee.in
Normal file
16
lang/cem/cemcom.ansi/tokcasee.in
Normal 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];
|
||||||
|
}
|
||||||
|
}
|
12
lang/cem/cemcom.ansi/tokcaseh.in
Normal file
12
lang/cem/cemcom.ansi/tokcaseh.in
Normal 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) {
|
|
@ -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.
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
15
lang/cem/cpp.ansi/ch3bin.h
Normal file
15
lang/cem/cpp.ansi/ch3bin.h
Normal 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_ */
|
15
lang/cem/cpp.ansi/ch3mon.h
Normal file
15
lang/cem/cpp.ansi/ch3mon.h
Normal 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_ */
|
27
lang/cem/cpp.ansi/domacro.h
Normal file
27
lang/cem/cpp.ansi/domacro.h
Normal 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
42
lang/cem/cpp.ansi/error.h
Normal 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
14
lang/cem/cpp.ansi/expr.h
Normal 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
13
lang/cem/cpp.ansi/init.h
Normal 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_ */
|
13
lang/cem/cpp.ansi/options.h
Normal file
13
lang/cem/cpp.ansi/options.h
Normal 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_ */
|
14
lang/cem/cpp.ansi/preprocess.h
Normal file
14
lang/cem/cpp.ansi/preprocess.h
Normal 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
18
lang/cem/cpp.ansi/skip.h
Normal 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_ */
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
|
||||||
|
|
|
@ -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
Loading…
Reference in a new issue