314 lines
6.9 KiB
C
314 lines
6.9 KiB
C
/* D E F I N I T I O N M E C H A N I S M */
|
|
|
|
#include "parameters.h"
|
|
#include "debug.h"
|
|
|
|
#include <alloc.h>
|
|
#include <assert.h>
|
|
#include <em_arith.h>
|
|
#include <em_label.h>
|
|
|
|
#include "LLlex.h"
|
|
#include "def.h"
|
|
#include "idf.h"
|
|
#include "main.h"
|
|
#include "misc.h"
|
|
#include "node.h"
|
|
#include "scope.h"
|
|
#include "code.h"
|
|
#include "type.h"
|
|
#include "lookup.h"
|
|
#include "error.h"
|
|
|
|
struct def *MkDef(register struct idf *id, register struct scope *scope,
|
|
long kind)
|
|
{
|
|
/* Create a new definition structure in scope "scope", with
|
|
* id "id" and kind "kind".
|
|
*/
|
|
register struct def *df = new_def();
|
|
|
|
df->df_idf = id;
|
|
df->df_scope = scope;
|
|
df->df_kind = kind;
|
|
df->df_type = error_type;
|
|
df->df_next = id->id_def;
|
|
id->id_def = df;
|
|
|
|
/* enter the definition in the list of definitions in this scope
|
|
*/
|
|
df->df_nextinscope = scope->sc_def;
|
|
scope->sc_def = df;
|
|
return df;
|
|
}
|
|
|
|
struct def *define(register struct idf *id, register struct scope *scope,
|
|
long kind)
|
|
{
|
|
/* Declare an identifier in a scope, but first check if it
|
|
already has been defined.
|
|
If so, then check for the cases in which this is legal,
|
|
and otherwise give an error message.
|
|
*/
|
|
register struct def *df;
|
|
|
|
if ( (df = lookup(id, scope, 0L)) )
|
|
{
|
|
if (df->df_kind == D_INUSE)
|
|
{
|
|
if (kind != D_INUSE)
|
|
{
|
|
error("\"%s\" already used in this block", id->id_text);
|
|
}
|
|
return MkDef(id, scope, kind);
|
|
}
|
|
if (df->df_kind == D_ERROR)
|
|
{
|
|
/* used in forward references */
|
|
df->df_kind = kind;
|
|
return df;
|
|
}
|
|
/* other cases fit in an int (assume at least 2 bytes) */
|
|
switch ((int) df->df_kind)
|
|
{
|
|
|
|
case D_LABEL:
|
|
/* generate error message somewhere else */
|
|
return NULLDEF;
|
|
|
|
case D_PARAMETER:
|
|
if (kind == D_VARIABLE)
|
|
/* program parameter declared as variable */
|
|
return df;
|
|
break;
|
|
|
|
case D_FORWTYPE:
|
|
if (kind == D_FORWTYPE)
|
|
return df;
|
|
if (kind == D_TYPE)
|
|
{
|
|
/* forward reference resolved */
|
|
df->df_kind = D_FTYPE;
|
|
return df;
|
|
}
|
|
else
|
|
error("identifier \"%s\" must be a type", id->id_text);
|
|
return NULLDEF;
|
|
|
|
case D_FWPROCEDURE:
|
|
if (kind == D_PROCEDURE)
|
|
return df;
|
|
error("procedure identification \"%s\" expected", id->id_text);
|
|
return NULLDEF;
|
|
|
|
case D_FWFUNCTION:
|
|
if (kind == D_FUNCTION)
|
|
return df;
|
|
error("function identification \"%s\" expected", id->id_text);
|
|
return NULLDEF;
|
|
|
|
}
|
|
if (kind != D_ERROR)
|
|
/* avoid spurious error messages */
|
|
error("identifier \"%s\" already declared", id->id_text);
|
|
|
|
return NULLDEF;
|
|
}
|
|
|
|
return MkDef(id, scope, kind);
|
|
}
|
|
|
|
void DoDirective(struct idf *directive, struct node *nd, struct type *tp,
|
|
struct scopelist *scl, int function)
|
|
{
|
|
long kind; /* kind of directive */
|
|
int inp; /* internal or external name */
|
|
int ext = 0; /* directive = EXTERN */
|
|
struct def *df = lookup(directive, PervasiveScope, D_INUSE);
|
|
|
|
if (!df)
|
|
{
|
|
if (!is_anon_idf(directive))
|
|
node_error(nd, "\"%s\" unknown directive", directive->id_text);
|
|
return;
|
|
}
|
|
|
|
if (df->df_kind == D_FORWARD)
|
|
{
|
|
kind = function ? D_FWFUNCTION : D_FWPROCEDURE;
|
|
inp = (proclevel > 1);
|
|
}
|
|
else if (df->df_kind == D_EXTERN)
|
|
{
|
|
kind = function ? D_FUNCTION : D_PROCEDURE;
|
|
inp = 0;
|
|
ext = 1;
|
|
}
|
|
else
|
|
{
|
|
node_error(nd, "\"%s\" unknown directive", directive->id_text);
|
|
return;
|
|
}
|
|
|
|
if ( (df = define(nd->nd_IDF, CurrentScope, kind)) )
|
|
{
|
|
if (df->df_kind != kind)
|
|
{
|
|
/* identifier already forward declared */
|
|
node_error(nd, "\"%s\" already forward declared",
|
|
nd->nd_IDF->id_text);
|
|
return;
|
|
}
|
|
|
|
df->df_type = tp;
|
|
df->prc_vis = scl;
|
|
df->prc_name = gen_proc_name(nd->nd_IDF, inp);
|
|
if (ext)
|
|
{
|
|
if (!(df->df_flags & D_EXTERNAL) && proclevel > 1)
|
|
tp->prc_nbpar -= pointer_size;
|
|
/* was added for static link which is not needed now.
|
|
But make sure this is done only once (look at the
|
|
D_EXTERNAL flag).
|
|
*/
|
|
df->df_flags |= D_EXTERNAL;
|
|
}
|
|
df->df_flags |= D_SET;
|
|
}
|
|
}
|
|
|
|
struct def *DeclProc(register struct node *nd, struct type *tp,
|
|
register struct scopelist *scl)
|
|
{
|
|
register struct def *df;
|
|
|
|
if ( (df = define(nd->nd_IDF, CurrentScope, D_PROCEDURE)) )
|
|
{
|
|
df->df_flags |= D_SET;
|
|
if (df->df_kind == D_FWPROCEDURE)
|
|
{
|
|
df->df_kind = D_PROCEDURE; /* identification */
|
|
|
|
/* Simulate a call to open_scope(), which has already
|
|
* been performed in the forward declaration.
|
|
*/
|
|
CurrVis = df->prc_vis;
|
|
|
|
if (tp->prc_params)
|
|
node_error(nd, "\"%s\" already declared", nd->nd_IDF->id_text);
|
|
}
|
|
else
|
|
{ /* normal declaration */
|
|
df->df_type = tp;
|
|
df->prc_name = gen_proc_name(nd->nd_IDF, (proclevel > 1));
|
|
/* simulate open_scope() */
|
|
CurrVis = df->prc_vis = scl;
|
|
}
|
|
routine_label(df);
|
|
}
|
|
else
|
|
CurrVis = scl; /* simulate open_scope() */
|
|
|
|
return df;
|
|
}
|
|
|
|
struct def *
|
|
DeclFunc(register struct node *nd, struct type *tp,
|
|
register struct scopelist *scl)
|
|
{
|
|
register struct def *df;
|
|
|
|
if ( (df = define(nd->nd_IDF, CurrentScope, D_FUNCTION)) )
|
|
{
|
|
df->df_flags &= ~D_SET;
|
|
if (df->df_kind == D_FUNCTION)
|
|
{ /* declaration */
|
|
if (!tp)
|
|
{
|
|
node_error(nd, "\"%s\" illegal function declaration",
|
|
nd->nd_IDF->id_text);
|
|
tp = construct_type(T_FUNCTION, error_type);
|
|
}
|
|
/* simulate open_scope() */
|
|
CurrVis = df->prc_vis = scl;
|
|
df->df_type = tp;
|
|
df->prc_name = gen_proc_name(nd->nd_IDF, (proclevel > 1));
|
|
}
|
|
else
|
|
{ /* identification */
|
|
assert(df->df_kind == D_FWFUNCTION);
|
|
|
|
df->df_kind = D_FUNCTION;
|
|
CurrVis = df->prc_vis;
|
|
|
|
if (tp)
|
|
node_error(nd, "\"%s\" already declared", nd->nd_IDF->id_text);
|
|
|
|
}
|
|
routine_label(df);
|
|
}
|
|
else
|
|
CurrVis = scl; /* simulate open_scope() */
|
|
|
|
return df;
|
|
}
|
|
|
|
void EndFunc(register struct def *df)
|
|
{
|
|
/* assignment to functionname is illegal outside the functionblock */
|
|
df->prc_res = 0;
|
|
|
|
/* Give the error about assignment as soon as possible. The
|
|
* |= assignment inhibits a warning in the main procedure.
|
|
*/
|
|
if (!(df->df_flags & D_SET))
|
|
{
|
|
error("function \"%s\" not assigned", df->df_idf->id_text);
|
|
df->df_flags |= D_SET;
|
|
}
|
|
}
|
|
|
|
void EndBlock(register struct def *block_df)
|
|
{
|
|
register struct def *tmp_def = CurrentScope->sc_def;
|
|
register struct def *df;
|
|
|
|
while (tmp_def)
|
|
{
|
|
df = tmp_def;
|
|
/* The length of a usd_def chain is at most 1.
|
|
* The while is just defensive programming.
|
|
*/
|
|
while (df->df_kind & D_INUSE)
|
|
df = df->usd_def;
|
|
|
|
if (!is_anon_idf(df->df_idf) && (df->df_scope == CurrentScope))
|
|
{
|
|
if (!(df->df_kind & (D_ENUM | D_LABEL | D_ERROR)))
|
|
{
|
|
if (!(df->df_flags & D_USED))
|
|
{
|
|
if (!(df->df_flags & D_SET))
|
|
{
|
|
warning("\"%s\" neither set nor used in \"%s\"",
|
|
df->df_idf->id_text, block_df->df_idf->id_text);
|
|
}
|
|
else
|
|
{
|
|
warning("\"%s\" unused in \"%s\"", df->df_idf->id_text,
|
|
block_df->df_idf->id_text);
|
|
}
|
|
}
|
|
else if (!(df->df_flags & D_SET))
|
|
{
|
|
if (!(df->df_flags & D_LOOPVAR))
|
|
warning("\"%s\" not set in \"%s\"", df->df_idf->id_text,
|
|
block_df->df_idf->id_text);
|
|
}
|
|
}
|
|
|
|
}
|
|
tmp_def = tmp_def->df_nextinscope;
|
|
}
|
|
}
|