Files
Digital-Research-Source-Code/ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/declare.c
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

507 lines
11 KiB
C

#include "misc.h"
#include "defs.h"
#include "cvt.h"
#include "struct.h"
#include "tokens.h"
extern char *text_ptr;
extern char *out_string;
/*
* Routines to process DECLARE statements.
*/
/*
* Skip to closing right parenthesis
*/
find_right_paren()
{
TOKEN token;
int token_class;
int paren_count;
paren_count = 1;
do {
token_class = get_token(&token);
if (token_class == LEFT_PAREN)
paren_count++;
else
if (token_class == RIGHT_PAREN)
paren_count--;
} while (paren_count);
}
/*
* Copy an element from source to destination
*/
element_copy(src, dest)
DECL_MEMBER *src, *dest;
{
/* Don't copy name list */
dest->name_list = NULL;
/* Don't copy link */
dest->next_member = NULL;
dest->literal = src->literal;
dest->array_bound = src->array_bound;
dest->type = src->type;
dest->attributes = src->attributes;
dest->initialization = src->initialization;
dest->at_ptr = src->at_ptr;
dest->init_ptr = src->init_ptr;
if (src->struct_list)
element_copy(src->struct_list, dest->struct_list);
}
/*
* Generate a linked list of variables of the form:
* <id> [BASED <id>[.<id>]] or
* ( <id> [BASED <id>[.<id>]] [ ,<id> [BASED <id>[.<id>]] ] ... )
* Return token following variable list.
*/
get_var_list(list_ptr, sep_token)
DECL_ID **list_ptr;
TOKEN *sep_token;
{
DECL_ID *var_ptr, *last_var;
TOKEN *token;
int token_class;
BOOLEAN multi_list;
char *par_white_start, *par_white_end;
*list_ptr = NULL;
/* Get first token */
get_token_ptr(&token);
token_class = get_token(token);
/* Determine if <var> or list of ( <var> [,<var>] ... ) */
if (token_class == LEFT_PAREN) {
/* List of ( <var> [,<var>] ... ) */
multi_list = TRUE;
/* Use white space before '(' for first identifier */
par_white_start = token->white_space_start;
par_white_end = token->white_space_end;
/* Get first identifier */
token_class = get_token(token);
token->white_space_start = par_white_start;
token->white_space_end = par_white_end;
} else
/* <var> */
multi_list = FALSE;
/* Process identifier list */
last_var = NULL;
while (1) {
if (token_class != IDENTIFIER) {
parse_error("Identifier expected");
free_var_list(*list_ptr);
free((char *) token);
*list_ptr = NULL;
return ERROR;
}
/* Get a variable structure */
get_var_ptr(&var_ptr);
if (*list_ptr == NULL)
/* Point to first variable */
*list_ptr = var_ptr;
if (last_var)
last_var->next_var = var_ptr;
last_var = var_ptr;
/* Save variable name */
var_ptr->name = token;
/* Check for BASED */
token_class = get_token(sep_token);
if ((token_class == RESERVED) &&
(sep_token->token_type == BASED)) {
/* BASED <id>[ .<id> ] */
/* Get based name */
get_token_ptr(&token);
token_class = get_token(token);
if (token_class != IDENTIFIER) {
parse_error("Identifier expected");
free_var_list(*list_ptr);
free((char *) token);
*list_ptr = NULL;
return ERROR;
}
token_class = parse_simple_variable(token, sep_token);
#ifdef USE_DEFINES
/* Swap variable name with based name */
var_ptr->based_name = var_ptr->name;
var_ptr->name = token;
#else
var_ptr->based_name = token;
#endif
}
if (!multi_list)
return token_class;
if (token_class != COMMA)
break;
/* Get next variable */
get_token_ptr(&token);
token_class = get_token(token);
}
if (token_class == RIGHT_PAREN) {
/* Get next token */
token_class = get_token(sep_token);
return token_class;
} else {
parse_error("')' expected");
free_var_list(*list_ptr);
*list_ptr = NULL;
return ERROR;
}
}
/*
* Parse a structure declaration of the form:
* STRUCTURE ( <member> [ ,<member> ] ... )
* where:
* <member> ::= { <id> | ( <id> [ ,<id> ] ... ) } [ ( <numeric> ) ] <type>
*/
parse_structure(list_ptr)
DECL_MEMBER **list_ptr;
{
DECL_MEMBER *struct_ptr, *last_struct;
TOKEN token;
int token_class;
*list_ptr = NULL;
/* Get left paren */
token_class = get_token(&token);
if (token_class != LEFT_PAREN) {
parse_error("'(' expected");
return;
}
last_struct = NULL;
do {
/* Get a DECL_MEMBER structure */
get_element_ptr(&struct_ptr);
if (*list_ptr == NULL)
/* Point to first structure */
*list_ptr = struct_ptr;
if (last_struct)
last_struct->next_member = struct_ptr;
last_struct = struct_ptr;
/* Get variable list */
token_class = get_var_list(&struct_ptr->name_list, &token);
/* Get type and optional array designator */
get_token_ptr(&struct_ptr->type);
token_class = parse_type(struct_ptr, &token);
/* Get seperator */
token_class = get_token(&token);
} while (token_class == COMMA);
if (token_class != RIGHT_PAREN) {
parse_error("'(' expected");
free_decl_list(*list_ptr);
*list_ptr = NULL;
return;
}
}
/*
* Parse type and optional array designator.
* Passed initial token.
* Returns RESERVED if appropriate type found, else returns END_OF_LINE.
*/
parse_type(el_ptr, token)
DECL_MEMBER *el_ptr;
TOKEN *token;
{
TOKEN *temp_token;
int token_class;
token_class = token->token_class;
if (token_class == LEFT_PAREN) {
/* Array specifier */
/* Get numeric or '*' */
get_token_ptr(&temp_token);
token_class = get_token(temp_token);
if ((token_class == NUMERIC) ||
((token_class == OPERATOR) &&
(temp_token->token_type == TIMES))) {
if (token_class != NUMERIC)
/* array(*) specified - ignore '*' */
temp_token->token_name[0] = '\0';
/* Save array bound token */
el_ptr->array_bound = temp_token;
} else {
parse_error("Illegal array bound");
free((char *) temp_token);
return ERROR;
}
/* Get right paren */
token_class = get_token(token);
if (token_class != RIGHT_PAREN) {
parse_error("')' expected");
free((char *) temp_token);
return ERROR;
}
/* Get type */
token_class = get_token(token);
}
if ((token_class == RESERVED) && (token->token_type >= BYTE) &&
(token->token_type <= STRUCTURE)) {
/* Save type token */
token_copy(token, el_ptr->type);
if (token->token_type == STRUCTURE) {
/* Get structure list */
parse_structure(&el_ptr->struct_list);
}
return token_class;
} else {
parse_error("Illegal type");
return ERROR;
}
}
/*
* Parse a DECLARE element.
* Return token terminating DECLARE element.
*/
get_element(element, token)
DECL_MEMBER **element;
TOKEN *token;
{
DECL_MEMBER *el_ptr;
TOKEN temp_token, eof_token;
int token_class;
char *tmp_text_ptr;
char *tmp_out_string;
char *get_mem();
get_element_ptr(element);
/* Point to element */
el_ptr = *element;
/* Get name list */
token_class = get_var_list(&el_ptr->name_list, token);
/* Malloc space for type */
get_token_ptr(&el_ptr->type);
if (token_class == RESERVED)
switch (token->token_type) {
case LABEL :
/* LABEL declaration */
token_copy(token, el_ptr->type);
/* Check for PUBLIC or EXTERNAL */
token_class = get_token(token);
if ((token_class == RESERVED) &&
((token->token_type == PUBLIC) ||
(token->token_type == EXTERNAL)))
/* Indeed, who cares? */
token_class = get_token(token);
return token_class;
case LITERALLY :
token_copy(token, el_ptr->type);
/* Check for 'string' */
if (get_token(token) != STRING) {
parse_error("String expected");
free_decl_list(el_ptr);
return ERROR;
}
el_ptr->literal = get_mem(MAX_LITERAL_SIZE);
#ifdef PARSE_LITERALS
/* Parse literal string if only one token in string */
tmp_text_ptr = text_ptr;
text_ptr = token->token_name;
/* Parse token in string */
if (get_token(&temp_token) == END_OF_FILE)
el_ptr->literal[0] = '\0';
else
if (get_token(&eof_token) == END_OF_FILE) {
/* Single token literal */
(void) strcpy(el_ptr->literal, temp_token.token_name);
/* Save parsed token */
get_token_ptr(&el_ptr->literal_token);
token_copy(&temp_token, el_ptr->literal_token);
} else
(void) strcpy(el_ptr->literal, token->token_name);
text_ptr = tmp_text_ptr;
#else
/* Put string in literal */
(void) strcpy(el_ptr->literal, token->token_name);
#endif
/* Return following token */
token_class = get_token(token);
return token_class;
}
if (parse_type(el_ptr, token) != RESERVED) {
/* Error occurred */
free_decl_list(el_ptr);
return END_OF_LINE;
}
/* Process attribute information (if any) */
/* Check for EXTERNAL [ DATA ] */
token_class = get_token(token);
if (token_class != RESERVED)
return token_class;
if (token->token_type == EXTERNAL) {
el_ptr->attributes = EXTERNAL;
/* Check for DATA attribute */
token_class = get_token(token);
if (token_class == RESERVED) {
if (token->token_type == DATA) {
/*
* Ignore attribute
* el_ptr->initialization = DATA;
*/
token_class = get_token(token);
} else {
parse_error("Illegal attribute");
free_decl_list(el_ptr);
return ERROR;
}
}
return token_class;
} else
/* Check for PUBLIC */
if (token->token_type == PUBLIC) {
el_ptr->attributes = PUBLIC;
token_class = get_token(token);
}
if (token_class != RESERVED)
return token_class;
/* Check for AT ( <expr> ) */
if (token->token_type == AT) {
/* Check for '(' */
token_class = get_token(token);
if (token_class != LEFT_PAREN) {
parse_error("'(' expected");
free_decl_list(el_ptr);
return ERROR;
}
/* Generate a string for the AT expression */
el_ptr->at_ptr = get_mem(MAX_AT_EXPR_SIZE);
el_ptr->at_ptr[0] = '\0';
tmp_out_string = out_string;
out_string = el_ptr->at_ptr;
/* Parse the expression into at_ptr */
token_class = parse_expression(token);
if (token_class != RIGHT_PAREN) {
parse_error("')' expected");
free_decl_list(el_ptr);
return ERROR;
}
out_string = tmp_out_string;
token_class = get_token(token);
}
if (token_class != RESERVED)
return token_class;
/* Check for INITIAL or DATA ( <expr> ) */
if ((token->token_type == INITIAL) ||
(token->token_type == DATA)) {
el_ptr->initialization = token->token_type;
/* Check for '(' */
token_class = get_token(token);
if (token_class != LEFT_PAREN) {
parse_error("'(' expected");
free_decl_list(el_ptr);
return ERROR;
}
el_ptr->init_ptr = text_ptr;
/* Skip to ')' */
find_right_paren();
token_class = get_token(token);
}
return token_class;
}
/*
* Parse a DECLARE list.
* Passed a pointer to a DECL, returns with DECL filled.
*/
get_decl_list(decl)
DECL *decl;
{
DECL_MEMBER *el_ptr, *decl_ptr;
TOKEN token;
int token_class;
decl->decl_list = NULL;
decl->next_decl = NULL;
decl_ptr = NULL;
do {
/* Get a declaration element */
token_class = get_element(&el_ptr, &token);
if (decl->decl_list == NULL)
decl->decl_list = el_ptr;
/* Link previous element */
if (decl_ptr)
decl_ptr->next_member = el_ptr;
decl_ptr = el_ptr;
} while (token_class == COMMA);
}
/*
* Parse a DECLARE statement.
*/
parse_declare(first_token)
TOKEN *first_token;
{
DECL decl;
decl.decl_token = first_token;
get_decl_list(&decl);
out_decl(&decl);
add_to_context(decl.decl_list);
}