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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -8,11 +8,15 @@
#include "parameters.h"
#ifndef LINT
#include "conversion.h"
#include <em.h>
#include "interface.h"
#include "arith.h"
#include "type.h"
#include "sizes.h"
#include "Lpars.h"
#include "error.h"
#define T_SIGNED 1
#define T_UNSIGNED 2
@ -27,10 +31,9 @@
C??
*/
static int convtype();
static int convtype(register struct type *);
conversion(from_type, to_type)
register struct type *from_type, *to_type;
void conversion(register struct type *from_type, register struct type *to_type)
{
register arith from_size = from_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:
signed, unsigned or floating
*/
static int
convtype(tp)
register struct type *tp;
static int convtype(register struct type *tp)
{
switch (tp->tp_fund) {
case CHAR:

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -8,12 +8,17 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "domacro.h"
#include "parameters.h"
#include "idf.h"
#include "interface.h"
#include "arith.h"
#include "LLlex.h"
#include "Lpars.h"
#include "input.h"
#include "pragma.h"
#include "skip.h"
#include "error.h"
#ifdef DBSYMTAB
#include <stb.h>
@ -23,7 +28,9 @@ int IncludeLevel = 0;
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
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;
}
domacro()
void domacro(void)
{
int tok;
struct token tk;
@ -70,7 +77,7 @@ domacro()
SkipToNewLine();
}
do_line(l) unsigned int l;
static void do_line(unsigned int l)
{
struct token tk;
int t = GetToken(&tk);

View file

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

View file

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

View file

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

View file

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

View file

@ -14,6 +14,8 @@
#include <em_reg.h>
#include <alloc.h>
#include <flt_arith.h>
#include "interface.h"
#include "eval.h"
#include "idf.h"
#include "arith.h"
#include "type.h"
@ -22,13 +24,21 @@
#include "def.h"
#include "expr.h"
#include "sizes.h"
#include "field.h"
#include "Lpars.h"
#include "level.h"
#include "conversion.h"
#include "stack.h"
#include "struct.h"
#include "align.h"
#include "mes.h"
#include "atw.h"
#include "ch3.h"
#include "util.h"
#include "blocks.h"
#include "dataflow.h"
#include "specials.h"
#include "error.h"
#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)
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
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)
*/
void
EVAL(expr, val, code, true_label, false_label)
register struct expr *expr;
int val, code;
label true_label, false_label;
void EVAL(register struct expr *expr, int val, int code, label true_label, label false_label)
{
int vol = (code != TRUE && recurqual(expr->ex_type, TQ_VOLATILE));
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(relop, lbl)
int relop;
label lbl;
static void compare(int relop, label lbl)
{
switch (relop) {
case '<':
@ -688,8 +696,7 @@ compare(relop, lbl)
}
/* truthvalue() serves as an auxiliary function of EVAL */
truthvalue(relop)
int relop;
static void truthvalue(int relop)
{
switch (relop) {
case '<':
@ -717,12 +724,10 @@ truthvalue(relop)
/* assop() generates the opcode of an assignment operators op= */
assop(type, oper)
register struct type *type;
int oper;
void assop(register struct type *type, int oper)
{
register arith size;
register uns = type->tp_unsigned;
register int uns = type->tp_unsigned;
if ((int)(size = type->tp_size) < (int)word_size)
size = word_size;
@ -822,8 +827,7 @@ assop(type, oper)
}
}
ptr_add(size)
arith size;
static void ptr_add(arith size)
{
if (size != pointer_size) {
C_loc(size);
@ -840,10 +844,7 @@ ptr_add(size)
- into a local static variable
- absolute addressing
*/
void
store_val(vl, tp)
register struct value *vl;
register struct type *tp;
void store_val(register struct value *vl, register struct type *tp)
{
register int inword = 0;
register int indword = 0;
@ -911,11 +912,10 @@ store_val(vl, tp)
- global variable
- static variable
- local variable
rlval generate rlval or lval
*/
void
load_val(expr, rlval)
register struct expr *expr; /* expression containing the value */
int rlval; /* generate either LVAL or RVAL */
void load_val(register struct expr *expr, int rlval)
{
register struct type *tp = expr->ex_type;
int rvalue = (rlval == RVAL && expr->ex_lvalue != 0);
@ -1012,8 +1012,7 @@ load_val(expr, rlval)
}
}
load_cst(val, siz)
arith val, siz;
void load_cst(arith val, arith siz)
{
if ((int)siz <= (int)word_size)
C_loc(val);
@ -1030,8 +1029,7 @@ load_cst(val, siz)
}
}
operands(expr, gencode)
register struct expr *expr;
static void operands(register struct expr *expr, int gencode)
{
EVAL(expr->OP_LEFT, RVAL, gencode, NO_LABEL, NO_LABEL);
EVAL(expr->OP_RIGHT, RVAL, gencode, NO_LABEL, NO_LABEL);

View file

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

View file

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

View file

@ -4,6 +4,13 @@
*/
/* $Id$ */
/* 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
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 */
int rank_of(int oper);
void dot2expr(struct expr **expp);
void idf2expr(register struct expr *expr);
void string2expr(register struct expr **expp, char *str, int len);
void int2expr(struct expr *expr);
void float2expr(register struct expr *expr);
struct expr* intexpr(arith ivalue, int fund);
void fill_int_expr(register struct expr *ex,arith ivalue, int fund);
struct expr *new_oper(struct type *tp, register struct expr *e1, int oper,
register struct expr *e2);
void chk_cst_expr(struct expr **expp);
void init_expression(register struct expr ***eppp, struct expr *expr);
int is_ld_cst(register struct expr *expr);
int is_cp_cst(struct expr *expr);
int is_fp_cst(struct expr *expr);
int is_zero_cst(register struct expr *expr);
void free_expression(register struct expr *expr);
#endif

View file

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

View file

@ -23,8 +23,11 @@
#include "align.h"
#include "Lpars.h"
#include "field.h"
#include "util.h"
#include "conversion.h"
#include "eval.h"
arith NewLocal(); /* util.c */
extern arith full_mask[]; /* cstoper.c */
/* 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;
and in which bitfields are stored!
*/
eval_field(expr, code)
struct expr *expr;
int code;
void eval_field(
struct expr *expr,
int code)
{
int op = expr->OP_OPER;
register struct expr *leftop = expr->OP_LEFT;
@ -126,12 +129,12 @@ eval_field(expr, code)
}
}
store_field(fd, uns, code, leftop, tmpvar)
register struct field *fd;
int uns;
int code;
register struct expr *leftop;
arith tmpvar;
void store_field(
register struct field *fd,
int uns,
int code,
register struct expr *leftop,
arith tmpvar)
{
C_loc(fd->fd_mask);
C_and(word_size);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

@ -4,6 +4,8 @@
*/
/* $Id$ */
/* 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" */
@ -26,3 +28,10 @@ extern label datlab_count;
not be there, and if it is there, it may be from a
declaration or another application.
*/
struct idf;
void enter_label(register struct idf *idf, int defining);
void unstack_label(register struct idf *idf);
#endif /* LABEL_H_ */

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

@ -3,10 +3,10 @@
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $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)
do

View file

@ -2,6 +2,9 @@
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#ifndef STMT_H_
#define STMT_H_
/* $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 */
@ -12,3 +15,5 @@ struct stmt_block {
};
/* ALLOCDEF "stmt_block" 5 */
#endif

View file

@ -19,16 +19,23 @@
#include "Lpars.h"
#include "align.h"
#include "level.h"
#include "ch3.h"
#include "sizes.h"
#include "error.h"
/* 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.
*/
static field_busy = 0;
static int field_busy = 0;
extern char options[];
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
obscure. Some highly regarded compilers are found out to accept,
@ -51,13 +58,13 @@ int lcm();
as well).
*/
add_sel(stp, tp, idf, sdefpp, szp, fd) /* this is horrible */
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 add_sel( /* this is horrible */
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)
{
/* The selector idf with type tp is added to two chains: the
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)
register struct idf *idf;
struct type *stp; /* the type of the struct */
static void check_selector(register struct idf *idf, struct type *stp)
{
/* 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;
@ -163,9 +169,7 @@ check_selector(idf, stp)
}
}
declare_struct(fund, idf, tpp)
register struct idf *idf;
struct type **tpp;
void declare_struct(int fund, register struct idf *idf, struct type **tpp)
{
/* A struct, union or enum (depending on fund) with tag (!)
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)
register struct idf *idf;
struct type **tpp;
void apply_struct(int fund,
register struct idf *idf,
struct type **tpp)
{
/* The occurrence of a struct, union or enum (depending on
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);
}
struct sdef *
idf2sdef(idf, tp)
register struct idf *idf;
struct type *tp;
struct sdef *idf2sdef(
register struct idf *idf,
struct type *tp)
{
/* The identifier idf is identified as a selector
in the struct tp.
@ -296,9 +299,7 @@ idf2sdef(idf, tp)
}
#if 0
int
uniq_selector(idf_sdef)
register struct sdef *idf_sdef;
int uniq_selector(register struct sdef *idf_sdef)
{
/* Returns true if idf_sdef (which is guaranteed to exist)
is unique for this level, i.e there is no other selector
@ -324,12 +325,12 @@ uniq_selector(idf_sdef)
#ifndef NOBITFIELD
arith
add_field(szp, fd, fdtpp, idf, stp)
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 */
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 */
{
/* The address where this selector is put is returned. If the
selector with specified width does not fit in the word, or
@ -438,18 +439,12 @@ add_field(szp, fd, fdtpp, idf, stp)
#endif /* NOBITFIELD */
/* some utilities */
int
is_struct_or_union(fund)
register int fund;
int is_struct_or_union(register int fund)
{
return fund == STRUCT || fund == UNION;
}
/* Greatest Common Divisor
*/
int
gcd(m, n)
register int m, n;
static int gcd(register int m, register int n)
{
register int r;
@ -461,11 +456,8 @@ gcd(m, n)
return m;
}
/* Least Common Multiple
*/
int
lcm(m, n)
register int m, n;
static int lcm(register int m, register int n)
{
return m * (n / gcd(m, n));
}

View file

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

View file

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

View file

@ -2,7 +2,16 @@
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#ifndef SWITCH_H_
#define SWITCH_H_
/* $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 */
struct switch_hdr {
@ -27,3 +36,12 @@ struct case_entry {
};
/* ALLOCDEF "case_entry" 20 */
void code_startswitch(struct expr **expp);
void code_endswitch(void);
void code_case(struct expr *expr);
void code_default(void);
#endif

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -4,8 +4,13 @@
*/
/* $Id$ */
/* TYPE DESCRIPTOR */
#ifndef TYPE_H_
#define TYPE_H_
#include "parameters.h"
#include "arith.h"
struct type {
struct type *next; /* used for ARRAY and for qualifiers */
@ -59,13 +64,6 @@ struct type {
#define TQ_VOLATILE 0x01
#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
*schar_type, *uchar_type,
@ -79,6 +77,24 @@ extern struct type
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 */
#endif

View file

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

View file

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

View file

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

View file

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

View file

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

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

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

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

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

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

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

View file

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

View file

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

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

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

View file

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

View file

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

View file

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

View file

@ -1,14 +1,15 @@
/* $Id$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* 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"
void
No_Mem()
void No_Mem(void)
{
sys_write(STDERR, "Out of memory\n", 14);
sys_stop(S_EXIT);
fprintf(stderr,"Out of memory\n");
exit(1);
}

View file

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

View file

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

View file

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

View file

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

View file

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

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