Files
retrobsd/src/cmd/smallc/sym.c
2014-04-09 14:27:18 +01:00

346 lines
9.5 KiB
C

/*
* File sym.c: 2.1 (83/03/20,16:02:19)
*/
#include <stdio.h>
#include "defs.h"
#include "data.h"
#define LOCALOFFSET 16 /* for MIPS32 */
/**
* declare a static variable
* @param type
* @param storage
* @return
*/
declare_global(int type, int storage) {
int k, j, count;
char sname[NAMESIZE];
for (;;) {
for (;;) {
if (endst ())
return;
k = 1;
if (match ("*"))
j = POINTER;
else
j = VARIABLE;
if (!symname (sname))
illname ();
if (findglb (sname))
multidef (sname);
count = 1;
if (match ("[")) {
k = needsub ();
count = k;
//if (k || storage == EXTERN)
j = ARRAY;
//else
// j = POINTER;
}
j = initials(sname, type, j, k);
add_global (sname, j, type, (k == 0 ? -1 : k), storage, count);
break;
}
if (!match (","))
return;
}
}
/**
* declare local variables
* works just like "declglb", but modifies machine stack and adds
* symbol table entry with appropriate stack offset to find it again
* @param typ
* @param stclass
*/
declare_local (typ, stclass)
int typ, stclass;
{
int k, j, count;
char sname[NAMESIZE];
for (;;) {
for (;;) {
if (endst ())
return;
if (match ("*"))
j = POINTER;
else
j = VARIABLE;
if (!symname (sname))
illname ();
if (findloc (sname))
multidef (sname);
count = 1;
if (match ("[")) {
k = needsub ();
count = k;
if (k) {
j = ARRAY;
if (typ & CINT)
k = k * INTSIZE;
} else {
j = POINTER;
k = INTSIZE;
}
} else
if ((typ & CCHAR) && (j != POINTER))
k = 1;
else
k = INTSIZE;
if (stclass != LSTATIC) {
k = galign(k);
stkp = gen_modify_stack (stkp - k);
add_local (sname, j, typ, stkp + LOCALOFFSET, AUTO, count);
} else
add_local( sname, j, typ, k, LSTATIC, count);
break;
}
if (!match (","))
return;
}
}
/**
* initialize global objects
* @param symbol_name
* @param size char 1 or integer 2
* @param identity
* @param dim
* @return 1 if variable is initialized
*/
int initials(char *symbol_name, int size, int identity, int dim) {
int dim_unknown = 0;
litptr = 0;
if(dim == 0) { // allow for xx[] = {..}; declaration
dim_unknown = 1;
}
if (!(size & CCHAR) && !(size & CINT)) {
error("unsupported storage size");
}
if(match("=")) {
// an array
if(match("{")) {
while((dim > 0) || (dim_unknown)) {
if (init(symbol_name, size, identity, &dim) && dim_unknown) {
dim_unknown++;
}
if(match(",") == 0) {
break;
}
}
needbrack("}");
if(--dim_unknown == 0)
identity = POINTER;
// single constant
} else {
init(symbol_name, size, identity, &dim);
}
}
return identity;
}
/**
* evaluate one initializer, add data to table
* @param size
* @param ident
* @param dim
* @return
*/
init(char *symbol_name, int size, int ident, int *dim) {
int value, number_of_chars;
if(ident == POINTER) {
error("cannot assign to pointer");
}
if(quoted_string(&value)) {
if((ident == VARIABLE) || (size != 1))
error("found string: must assign to char pointer or array");
number_of_chars = litptr - value;
*dim = *dim - number_of_chars;
while (number_of_chars > 0) {
add_data(symbol_name, CCHAR, litq[value++]);
number_of_chars = number_of_chars - 1;
}
} else if (number(&value)) {
add_data(symbol_name, CINT, value);
*dim = *dim - 1;
} else if(quoted_char(&value)) {
add_data(symbol_name, CCHAR, value);
*dim = *dim - 1;
} else {
return 0;
}
return 1;
}
/**
* get required array size. [xx]
* @return array size
*/
needsub () {
int num[1];
if (match ("]"))
return (0);
if (!number (num)) {
error ("must be constant");
num[0] = 1;
}
if (num[0] < 0) {
error ("negative size illegal");
num[0] = (-num[0]);
}
needbrack ("]");
return (num[0]);
}
/**
* search global table for given symbol name
* @param sname
* @return table index
*/
int findglb (char *sname) {
int idx;
idx = 1;
while (idx < global_table_index) {
if (astreq (sname, symbol_table[idx].name, NAMEMAX))
return (idx);
idx++;
}
return (0);
}
/**
* search local table for given symbol name
* @param sname
* @return table index
*/
int findloc (char *sname) {
int idx;
idx = local_table_index;
while (idx >= NUMBER_OF_GLOBALS) {
idx--;
if (astreq (sname, symbol_table[idx].name, NAMEMAX))
return (idx);
}
return (0);
}
/**
* add new symbol to global table
* @param sname
* @param identity
* @param type
* @param value
* @param storage
* @return new index
*/
int add_global (char *sname, int identity, int type, int offset, int storage, int count)
{
symbol_t *symbol;
char *buffer_ptr;
current_symbol_table_idx = findglb (sname);
if (current_symbol_table_idx != 0) {
return (current_symbol_table_idx);
}
if (global_table_index >= NUMBER_OF_GLOBALS) {
error ("global symbol table overflow");
return (0);
}
current_symbol_table_idx = global_table_index;
symbol = &symbol_table[current_symbol_table_idx];
buffer_ptr = symbol->name;
while (alphanumeric(*buffer_ptr++ = *sname++));
symbol->identity = identity;
symbol->type = type;
symbol->storage = storage;
symbol->count = count;
symbol->offset = offset;
global_table_index++;
return (current_symbol_table_idx);
}
/**
* add new symbol to local table
* @param sname
* @param identity
* @param type
* @param value
* @param storage_class
* @return
*/
int add_local (char *sname, int identity, int type, int offset, int storage_class, int count) {
int k;
symbol_t *symbol;
char *buffer_ptr;
//printf("local - symbol: %s offset: %d count: %d\n", sname, offset, count);
if (current_symbol_table_idx = findloc (sname)) {
return (current_symbol_table_idx);
}
if (local_table_index >= NUMBER_OF_GLOBALS + NUMBER_OF_LOCALS) {
error ("local symbol table overflow");
return (0);
}
current_symbol_table_idx = local_table_index;
symbol = &symbol_table[current_symbol_table_idx];
buffer_ptr = symbol->name;
while (alphanumeric(*buffer_ptr++ = *sname++));
symbol->identity = identity;
symbol->type = type;
symbol->storage = storage_class;
symbol->count = count;
if (storage_class == LSTATIC) {
data_segment_gdata();
print_label(k = getlabel());
output_label_terminator();
gen_def_storage();
output_number(offset);
newline();
code_segment_gtext();
offset = k;
}
symbol->offset = offset;
local_table_index++;
return (current_symbol_table_idx);
}
/*
* test if next input string is legal symbol name
*
*/
symname(char *sname) {
int k;
blanks();
if (!alpha (ch ()))
return (0);
k = 0;
while (alphanumeric(ch ()))
sname[k++] = gch ();
sname[k] = 0;
return (1);
}
illname() {
error ("illegal symbol name");
}
/**
* print error message
* @param symbol_name
* @return
*/
multidef (char *symbol_name) {
error ("already defined");
gen_comment ();
output_string (symbol_name);
newline ();
}