home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
me34src.zip
/
me3
/
mc
/
defun.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-14
|
14KB
|
583 lines
/*
Groups: keywords, targets
Keywords: Mutt keywords, External Tokens, global vars, local vars,
prototypes, constants, programs
targets: named labels, structures
Precedence: High to low, same line means ==
Keyword group:
Mutt Keywords
External Tokens
Local Vars, Prototypes
Global Vars, Constants, programs
Name Spaces:
Share: Overwritable
Mutt Keywords No
External Tokens Yes: if asked to, complain if overwriten
Global Vars No
Constants No
Programs No
?Structures
Share: Can't collide with Mutt Keywords
Local Vars No
Prototypes No
Share:
Named labels No
Scope:
Global:
Mutt Keywords
External Tokens
Global Vars
Constants
Programs
?Structures
Local to a defun:
Local Vars
Prototypes
Named labels
Prototype:
Local scope: name and type...
Global scope: program name, type list
*/
#include <stdio.h>
#include <os.h>
#include <dtable.h>
#include "mc.h"
#include "opcode.h"
#include "mm.h"
extern address pcaddr();
extern char *sheap_add(), *spoof(), *keyword_type_name(), *typename();
extern char ebuf[], token[];
extern unsigned int class; /* in mc.c */
extern int moders;
extern MuttCmd muttcmds[], modifiers[];
extern KeyWord *global_look_up(), *global_look_for(), *global_check();
address get_pgm();
/* ******************************************************************** */
/* **************************** Variables ***************************** */
/* ******************************************************************** */
static int
num_vars = 0, local_start = 0, any_local_vars = FALSE,
local_objects = 0,
global_objects = 0,
global_vars = 0, /* number of global variables */
size_of_global_vars = 0,
size_of_local_vars = 0;
static declare_and_init_dTable(var_table, Var);
#define VID_TO_VAR(n) (&var_table.table[n])
Var *vid_to_Var(n) { return VID_TO_VAR(n); }
/* ************ Var Names ************************ */
static char *global_vname_heap = NULL, *local_vname_heap = NULL;
char *add_var_name(name, forever) char *name;
{
char *ptr;
ptr = sheap_add(
(forever ? &global_vname_heap : &local_vname_heap),
name);
if (!ptr) bail("Out of memory! Can't expand var name heap.");
return ptr;
}
char *save_string(string) char *string; { return add_var_name(string, TRUE); }
void var_init()
{
}
/* Create a Var and pass back its id.
* Input:
* name : Pointer to name of var
* type :
* var_size : Size of the var. 0 if part of a protoype. Context
* dependent.
* is_proto : TRUE if this is a function protype
* Returns:
* Var id.
* Notes:
* This always works.
*/
create_var(name,type,var_size,scope) char *name; unsigned int type;
{
int n, is_object, is_proto, vid;
Var *the_var;
is_proto = (scope == PROTOTYPE);
if (scope == GLOBAL)
{
KeyWord *kw;
if (kw = global_check(name))
{
if (kw->type == KWGlobalVar) return kw->token;
/* else go ahead and add it */
}
}
else /* Local => local var or prototype */
if (find_local_var(name) != -1)
moan(spoof(ebuf,"\"%s\" already in use (as a local variable or arg).",
name));
is_object = is_object_type(type);
if (!xpand_dTable(&var_table, 1, 200,100))
bail("Out of memory! Can't expand Var table.");
vid = num_vars++;
the_var = VID_TO_VAR(vid);
the_var->name = add_var_name(name, is_proto || scope == GLOBAL);
the_var->type = type;
the_var->sub_type = 0;
the_var->offset = 0;
the_var->scope = scope;
the_var->blobs = 0;
the_var->dims = 0;
if (scope == LOCAL)
{
if (is_object) the_var->offset = local_objects++;
else
{
the_var->offset = size_of_local_vars;
size_of_local_vars += var_size;
}
}
else
if (scope == GLOBAL)
{
global_vars++;
if (is_object) the_var->offset = global_objects++;
else
{
the_var->offset = size_of_global_vars;
size_of_global_vars += var_size;
}
add_keyword(the_var->name, KWGlobalVar, vid, 3);
}
return vid; /* pass back the var */
}
add_array(name,type,size,scope,dims,dim)
char *name; unsigned int type; int dim[];
{
int j,n;
Var *var;
n = create_var(name,ARRAY,size,scope);
var = VID_TO_VAR(n);
var->sub_type = type;
var->dims = dims;
for (j = 0; j < dims; j++) var->dim[j] = dim[j];
return n;
}
#define VNAME(n) (VID_TO_VAR(n)->name)
char *vname(n) { return VNAME(n); }
vscope(n) { return (int)VID_TO_VAR(n)->scope; }
voffset(n) { return VID_TO_VAR(n)->offset; }
find_local_var(name) char *name;
{
int i;
if (any_local_vars)
for (i = local_start; i < num_vars; i++)
if (0 == strcmp(name, VNAME(i))) return i;
return -1;
}
getvar(name) char *name;
{
int n;
KeyWord *kw;
if (-1 != (n = find_local_var(name))) return n;
if (kw = global_look_for(name, KWGlobalVar)) return kw->token;
return -1;
}
unsigned int vtype(n) { return (unsigned int)VID_TO_VAR(n)->type; }
unsigned int vctype(n) unsigned int n; { return mmtype(vtype(n)); }
num_global_vars() { return global_vars; } /* number of global vars */
/* space needed to hold global vars */
gvspace() { return size_of_global_vars; }
num_global_objects() { return global_objects; }
/* Return the id of the next globabl object variable with id >= n, -1 if
* none.
*/
get_global_object(n)
{
for (; n < num_vars; n++)
if (vscope(n) == GLOBAL && is_object_type(vtype(n))) return n;
return -1;
}
/* Return the id of the next globabl variable with id >= n, -1 if none.
*/
get_global_var(n)
{
for (; n < num_vars; n++)
if (vscope(n) == GLOBAL) return n;
return -1;
}
static int compare2vars(a,b) Var *a, *b;
{ return strcmp(a->name,b->name); }
void sort_global_vars()
{
ssort(var_table.table, num_vars, sizeof(Var), compare2vars);
}
void print_global_vars(lstfile) FILE *lstfile;
{
int j;
sort_global_vars();
if (num_global_vars() == 0) fputs("\nNo global variables.\n",lstfile);
else
{
fputs("\n Global Variables\nName Offset Type\n",
lstfile);
for (j = 0; -1 != (j = get_global_var(j)); j++) /* global vars */
{
if (vtype(j) == ARRAY)
fprintf(lstfile,"%-27s %5d array of %s\n",
vname(j),voffset(j),typename(VID_TO_VAR(j)->sub_type));
else
fprintf(lstfile,"%-27s %5d %s\n",
vname(j),voffset(j),typename(vtype(j)));
}
}
}
/* ******************************************************************** */
/* **************************** Prototypes **************************** */
/* ******************************************************************** */
addproto(name) char *name; /* !!! */
{
return 0;
}
void add_to_proto(name,nth_arg,type,dims,dim) /* !!!moreproto */
char *name; unsigned int type; int dim[];
{
int j;
Var *var;
j = create_var(name,type,0,PROTOTYPE);
var = VID_TO_VAR(j);
var->offset = nth_arg;
if (dims)
{
var->sub_type = type;
var->type = ARRAY;
}
var->dims = dims;
for (j = 0; j < dims; j++) var->dim[j] = dim[j];
}
/* ******************************************************************** */
/* *************************** Named Labels *************************** */
/* ******************************************************************** */
/* Notes:
* Named labels (label foo) are only legal inside a defun and share
* scope with the defun.
*/
typedef struct { char *name; int label; } NamedLabel;
static declare_and_init_dTable(named_label_table,NamedLabel);
static int named_labels = 0, named_label_base = 0;
gen_named_label(name) char *name;
{
if (get_named_label(name) != -1)
{
moan(spoof(ebuf,"Label \"%s\" already in use.",name));
return 0;
}
if (!xpand_dTable(&named_label_table, 1, 10,10))
bail("Out of memory! Can't expand named label table.");
named_label_table.table[named_labels].name = add_var_name(name, FALSE);
return (named_label_table.table[named_labels++].label = genlabel());
}
get_named_label(name) char *name; /* return label */
{
int j;
NamedLabel *label = named_label_table.table;
for (j = named_labels; j--; label++)
if (0 == strcmp(name, label->name)) return label->label;
return -1;
}
void reset_named_labels(base, nlabels)
{
int j;
NamedLabel *label;
for (j = named_label_base; j < named_labels; j++)
{
label = &named_label_table.table[j];
if (getlabel(label->label) == NIL)
moan(spoof(ebuf,"Label \"%s\" unresolved.", label->name));
}
named_label_base = base;
named_labels = nlabels;
sizeof_dTable(&named_label_table) = named_labels;
}
/* ******************************************************************** */
/* *************************** Defun Frames *************************** */
/* ******************************************************************** */
typedef struct
{
int
num_vars, local_objects, size_of_local_vars, local_start,
named_labels, named_label_base;
} DefunFrame;
#define DFpush 0
#define DFarg 1
static int df_level = 0;
void push_dframe(dframe, op) DefunFrame *dframe;
{
if (op == DFarg)
{
/* dframe->num_vars = num_vars; /* */
return;
}
df_level++;
dframe->num_vars = num_vars;
dframe->local_start = local_start;
dframe->local_objects = local_objects;
dframe->size_of_local_vars = size_of_local_vars;
dframe->named_labels = named_labels;
dframe->named_label_base = named_label_base;
local_start = num_vars;
local_objects = 0;
size_of_local_vars = 0;
any_local_vars = TRUE;
}
void pop_dframe(dframe) DefunFrame *dframe;
{
/* num_vars = dframe->num_vars; /* */
num_vars = local_start; /* */
local_objects = dframe->local_objects;
size_of_local_vars = dframe->size_of_local_vars;
local_start = dframe->local_start;
sizeof_dTable(&var_table) = num_vars;
reset_named_labels(dframe->named_label_base, dframe->named_labels);
if (--df_level == 0)
{
sheap_reset(local_vname_heap);
any_local_vars = FALSE;
}
}
/* ******************************************************************** */
/* ****************************** Defun ******************************* */
/* ******************************************************************** */
extern int ntharg; /* in vcomp.c */
/* Define a function
* Syntax:
* (defun pgm-name [(arg list)] [modifiers] pgm [another fcn])
* pgm-name: TOKEN or STRING: name of the function being defined
* arg-list: a list of the function parameters. Used to to a give
* name to (arg n).
* (type name ...)
* (array type name [dims] ...)
* (pointer type name ...)
* (name ...) Unknown type: same as (arg n)
* modifiers: stuff like HIDDEN, etc.
* pgm: the actual function code.
* If another pgm-name follows the end of pgm, another function is
* defined.
*/
void defun()
{
DefunFrame vf;
int t, pgm, dim[MAXDIM];
unsigned int type;
KeyWord *kw;
do
{
/* Get the name of the function */
get_token();
if (class != TOKEN && class != STRING)
bitch("Function names are tokens or strings.");
pgm = add_pgm(token);
/*strcpy(temp,token); /* save pgm name */
/* Parse arg-list */
push_dframe(&vf, DFpush);
ntharg = 0; addproto("pgm-name");
while (TRUE)
{
lookahead();
if (class != DELIMITER || *token != START_EXP) break;
get_token(); /* suck up "(" */
lookahead(); t = -2;
if (class == TOKEN) /* (type arg-name) or (arg-name) */
{
t = -1; /* at least its a token */
if (kw = global_look_for(token,KWMutt))
{
t = kw->token;
get_token(); /* suck up type */
}
}
switch (t)
{
default: moan(spoof(ebuf,"\"%s\" is not an arg type.",token));
/* FALL THROUGH */
case -1: type = UNKNOWN; goto defvar; /* unknown token => untyped var */
case 62: /* bool */
type = BOOLEAN;
defvar:
do
{
get_token(); /* suck up arg-name */
if (class != TOKEN)
bitch(spoof(ebuf,"\"%s\" is not an arg name.",token));
add_to_proto(token,ntharg++,type,0,dim);
lookahead();
} while (class == TOKEN);
break;
case 61: case 75: case 31: /* byte, small-int, int all are NUMBER */
type = NUMBER; goto defvar;
case 60: type = STRING; goto defvar; /* string */
case 27: type = LIST; goto defvar; /* list */
case 73: array(LOCAL,TRUE); break; /* array */
case 72: /* (pointer bool | byte | small-int | int | defun name ...) */
get_token(); /* suck up the pointer type */
t = -1;
if (class == TOKEN &&
(kw = global_look_for(token,KWMutt))) t = kw->token;
switch (t)
{
default:
moan(spoof(ebuf,"\"%s\" is not a pointer type.",token));
type = UNKNOWN; goto defvar;
case 62: type = POINTER | BOOLEAN; goto defvar; /* bool */
case 75: type = POINTER | INT8; goto defvar; /* byte */
case 61: type = POINTER | INT16; goto defvar; /* small-int */
case 31: type = POINTER | INT32; goto defvar; /* int */
case 2: type = FCNPTR; goto defvar; /* defun */
}
}
get_token();
if (class != DELIMITER || *token != END_EXP) bitch("Bad arg list.");
}
/* suck up function modifiers */
while (lookahead(), class == TOKEN)
{
get_token();
if ((t = lookup_pgm_modifier(token)) != -1) modpgm(pgm,t);
else moan(spoof(ebuf,"\"%s\" is an invalid pgm modifer.",token));
}
push_dframe(&vf, DFarg); /* */
/* Compile the code */
if (class != DELIMITER || *token != START_PGM)
bitch("Pgms must start with a {");
class = VAROK;
compile(); genop(DONE);
pop_dframe(&vf);
/* Clean up and get ready for another defun */
lookahead();
} while (class == TOKEN || class == STRING);
}
/* Compile an Anonymous Defun: {{ code }}
* !!!??? (anon-defun ...)
* or (defun ANON
*/
void anon_defun()
{
address addr;
int label;
unsigned int lastclass;
DefunFrame vf;
push_dframe(&vf, DFpush);
gojmp(JMP, label = genlabel());
addr = pcaddr();
lastclass = VAROK;
while (TRUE)
{
lookahead();
if (class == DELIMITER)
if (*token == END_IPGM) break;
class = lastclass;
compile();
lastclass = class;
}
get_token(); /* suck up }} */
pop_dframe(&vf);
genop(DONE);
stufflabel(label);
genfa(addr, "Anon defun");
class = FCNPTR;
}