PL/M to C converter Part 03/03
Bob Ankeney
bob at reed.UUCP
Wed Apr 10 03:02:47 AEST 1991
#!/bin/sh
# this is part 3 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file parse.c continued
#
CurArch=3
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
exit 1; fi
( read Scheck
if test "$Scheck" != $CurArch
then echo "Please unpack part $Scheck next!"
exit 1;
else exit 0; fi
) < s2_seq_.tmp || exit 1
sed 's/^X//' << 'SHAR_EOF' >> parse.c
X out_string = temp_out_string;
X
X /* Check for '=' */
X if ((token_class != OPERATOR) ||
X (token.token_type != EQUAL)) {
X parse_error("Missing '='");
X pop_context();
X return;
X }
X /* Send <ident> '=' <expr> */
X out_str(var_string);
X out_token(&token);
X token_class = parse_expression(&token);
X if ((token_class != RESERVED) ||
X (token.token_type != TO)) {
X parse_error("Missing TO");
X pop_context();
X return;
X }
X
X /* Send <ident> <= <limit> */
X out_str("; ");
X out_str(var_string);
X out_str(" <=");
X token_class = parse_expression(&token);
X out_str("; ");
X
X /* Parse increment */
X if ((token_class == RESERVED) &&
X (token.token_type == BY)) {
X
X /* Send <ident> += <step> */
X out_str(var_string);
X out_str(" +=");
X token_class = parse_expression(&token);
X } else {
X /* Send <ident>++ */
X out_str(var_string);
X out_str("++");
X }
X
X out_str(") {"); /* } for dumb vi */
X out_white_space(&token);
X
X if (token_class != END_OF_LINE) {
X parse_error("BY or ';' expected");
X pop_context();
X return;
X }
X
X parse_to_end();
X break;
X
X case RESERVED :
X switch (token.token_type) {
X
X case CASE :
X /* DO CASE <expr>; */
X out_str("switch (");
X if (parse_expression(&token) != END_OF_LINE) {
X parse_error("';' expected");
X pop_context();
X return;
X }
X out_white_space(&token);
X out_str(") {"); /* } for dumb vi */
X
X case_line = 0;
X while (1) {
X /* Place case statement in out_string */
X temp_out_string1 = out_string;
X case_output[0] = '\0';
X out_string = case_output;
X
X (void) sprintf(case_statement, "case %d :",
X case_line++);
X token_class = parse_new_statement();
X if (token_class == END_OF_FILE) {
X parse_error("Premature end-of-file");
X exit(1);
X }
X if (token_class == END) {
X out_string = temp_out_string1;
X out_str(case_output);
X break;
X }
X out_string = temp_out_string1;
X out_white_space(first_token);
X out_str(case_statement);
X out_str(case_output);
X out_white_space(first_token);
X out_str("break;\n");
X }
X break;
X
X case WHILE :
X /* DO WHILE <expr>; */
X out_str("while (");
X if (parse_expression(&token) != END_OF_LINE) {
X parse_error("';' expected");
X pop_context();
X return;
X }
X out_white_space(&token);
X out_str(") {"); /* } for dumb vi */
X
X parse_to_end();
X break;
X
X default:
X parse_error("Illegal DO clause");
X pop_context();
X return;
X }
X break;
X }
X
X /* End of context */
X pop_context();
X}
X
X/*
X * END statement
X * Handles END [ <identifier> ] ;
X */
Xparse_end(first_token)
XTOKEN *first_token;
X{
X TOKEN token;
X int token_class;
X
X out_white_space(first_token); /* { for dumb vi */
X out_char('}');
X
X /* Check for END <procedure name>; */
X token_class = get_token(&token);
X if (token_class == IDENTIFIER) {
X /* END foo; where foo is a procedure */
X out_white_space(&token);
X out_str("/* ");
X out_token_name(&token);
X out_str(" */");
X token_class = get_token(&token);
X }
X
X if (token_class == END_OF_LINE)
X out_white_space(&token);
X else
X parse_error("';' expected");
X}
X
X/*
X * IF statement
X */
Xparse_if(first_token)
XTOKEN *first_token;
X{
X TOKEN token;
X
X out_white_space(first_token);
X out_str("if (");
X
X if ((parse_expression(&token) != RESERVED) ||
X (token.token_type != THEN))
X parse_error("Missing THEN in IF statement");
X else {
X out_pre_line(&token);
X out_char(')');
X out_white_space(&token);
X }
X}
X
X/*
X * THEN statement
X */
Xparse_then()
X{
X parse_error("Illegal use of THEN");
X}
X
X/*
X * ELSE statement
X */
Xparse_else(first_token)
XTOKEN *first_token;
X{
X out_white_space(first_token);
X out_str("else");
X}
X
X/*
X * GOTO statement
X */
Xparse_goto(first_token)
XTOKEN *first_token;
X{
X TOKEN token;
X
X out_white_space(first_token);
X out_str("goto");
X
X if (get_token(&token) != IDENTIFIER)
X parse_error("Illegal GOTO label");
X else {
X out_token(&token);
X check_eol();
X }
X}
X
X/*
X * GO TO statement
X */
Xparse_go(first_token)
XTOKEN *first_token;
X{
X TOKEN token;
X
X if ((get_token(&token) != RESERVED) || (token.token_type != TO))
X parse_error("Illegal GO TO");
X else
X parse_goto(first_token);
X}
X
X/*
X * CALL statement
X * Handles CALL <procedure name> [ ( <parameter list> ) ] ;
X */
Xparse_call(first_token)
XTOKEN *first_token;
X{
X TOKEN token;
X int token_class;
X DECL_MEMBER *id_type;
X DECL_ID *id_id;
X char *new_func, *tmp_out_string;
X char func_name[MAX_TOKEN_LENGTH];
X
X /* Get procedure name */
X token_class = get_token(&token);
X if (token_class != IDENTIFIER) {
X parse_error("Illegal procedure name");
X return;
X }
X
X out_white_space(first_token);
X
X /* Check for function conversion */
X if (check_cvt_id(&token, &cvt_functions[0], &new_func)) {
X out_str(new_func);
X token_class = get_token(&token);
X } else
X
X if (find_symbol(&token, &id_type, &id_id) &&
X (id_type->type->token_type != PROCEDURE)) {
X
X /* Skip white space */
X token.white_space_start = token.white_space_end;
X
X /* Check for call to pointer */
X func_name[0] = '\0';
X tmp_out_string = out_string;
X out_string = func_name;
X token_class = parse_variable(&token, &id_type, &id_id);
X out_string = tmp_out_string;
X
X if ((id_type->type->token_type == POINTER) ||
X#ifdef OFFSET
X (id_type->type->token_type == OFFSET) ||
X#endif
X (id_type->type->token_type == WORD)) {
X /* Yes - use pointer reference */
X out_str("(*");
X out_str(func_name);
X out_char(')');
X } else {
X parse_error("Illegal procedure reference");
X return;
X }
X } else {
X out_token_name(&token);
X token_class = get_token(&token);
X }
X
X /* Get parameter list (if any) */
X if (token_class == LEFT_PAREN) {
X out_token(&token);
X
X do {
X token_class = parse_expression(&token);
X out_token(&token);
X } while (token_class == COMMA);
X
X if (token_class == RIGHT_PAREN)
X /* Get end of line */
X check_eol();
X else
X parse_error("Illegal parameter list seperator");
X } else
X
X if (token_class == END_OF_LINE) {
X /* No parameter list */
X out_str("()");
X out_token(&token);
X } else
X parse_error("';' expected");
X}
X
X/*
X * RETURN statement
X * Handles RETURN [ <expression> ] ;
X */
Xparse_return(first_token)
XTOKEN *first_token;
X{
X TOKEN token;
X int token_class;
X
X out_white_space(first_token);
X out_str("return");
X
X token_class = parse_expression(&token);
X if (token_class != END_OF_LINE)
X parse_error("';' expected");
X else
X out_token(&token);
X}
X
X/*
X * Parse statement starting with an identifier.
X * Possibilities include:
X * Assignment
X * Procedure statement
X */
Xparse_identifier(first_token)
XTOKEN *first_token;
X{
X TOKEN token, next_token;
X TOKEN param_token, attrib_token, type_token;
X int token_class, next_token_class;
X DECL *decl_list, *extra_decl_list;
X PARAM_LIST *param_list, *param_ptr;
X DECL_MEMBER *decl_ptr;
X DECL_ID *decl_id;
X BOOLEAN extern_proc, got_type, interrupt_proc;
X char *tmp_text_ptr;
X
X /* Check for label or procedure */
X tmp_text_ptr = text_ptr;
X token_class = get_token(&token);
X
X if (token_class == LABEL) {
X /* Determine if label or procedure definition */
X next_token_class = get_token(&next_token);
X if ((next_token_class == RESERVED) &&
X (next_token.token_type == PROCEDURE)) {
X/*
X * Procedure - Check for parameter list
X */
X param_list = NULL;
X token_class = get_token(¶m_token);
X if (token_class == LEFT_PAREN) {
X /* Yes - get parameter list */
X get_param_list(¶m_list);
X
X /* Get token after parameter list */
X token_class = get_token(&attrib_token);
X } else
X /* No param list - save as attribute */
X token_copy(¶m_token, &attrib_token);
X
X out_white_space(first_token);
X extern_proc = FALSE;
X interrupt_proc = FALSE;
X
X got_type = (token_class == RESERVED) &&
X (attrib_token.token_type >= BYTE) &&
X (attrib_token.token_type <= SELECTOR);
X if (got_type) {
X/*
X * Process [ <type> ]
X */
X token_copy(&attrib_token, &type_token);
X token_class = get_token(&attrib_token);
X }
X
X while (token_class == RESERVED) {
X if (attrib_token.token_type == INTERRUPT) {
X/*
X * Process [ <interrupt> ]
X */
X interrupt_proc = TRUE;
X token_class = get_token(&attrib_token);
X if (token_class == NUMERIC)
X /* Interrupt number */
X token_class = get_token(&attrib_token);
X } else
X
X/*
X * Process [ EXTERNAL | { [ PUBLIC ] [ REENTRANT ] } ]
X */
X if (attrib_token.token_type == EXTERNAL) {
X out_str("extern");
X out_must_white(&attrib_token);
X extern_proc = TRUE;
X
X token_class = get_token(&attrib_token);
X } else
X
X if ((attrib_token.token_type == PUBLIC) ||
X (attrib_token.token_type == REENTRANT)) {
X do {
X if (attrib_token.token_type == PUBLIC) {
X /* Ignore for now */
X token_class = get_token(&attrib_token);
X } else
X
X if (attrib_token.token_type == REENTRANT) {
X /* Ignore for now */
X token_class = get_token(&attrib_token);
X } else
X break;
X } while (token_class == RESERVED);
X } else
X break;
X }
X
X if (token_class != END_OF_LINE) {
X parse_error("';' expected");
X return;
X }
X
X if (interrupt_proc && !extern_proc)
X parse_warning("INTERRUPT procedure declared");
X
X /* Create declaration for procedure */
X get_element_ptr(&decl_ptr);
X get_var_ptr(&decl_ptr->name_list);
X /* Type = PROCEDURE */
X get_token_ptr(&decl_ptr->type);
X token_copy(&next_token, decl_ptr->type);
X /* Name = procedure name */
X get_token_ptr(&decl_ptr->name_list->name);
X token_copy(first_token, decl_ptr->name_list->name);
X /* Flag if parameter list */
X if (param_list)
X decl_ptr->initialization = DATA;
X /* Add it to context */
X add_to_context(decl_ptr);
X
X if (got_type) {
X /* Output procedure type */
X out_token_name(&type_token);
X out_must_white(&type_token);
X }
X
X /* Output procedure name */
X out_token_name(first_token);
X
X if (extern_proc) {
X out_str("()");
X
X if (param_list)
X /* Parse parameter declarations */
X parse_param_list(param_list, &decl_list,
X &extra_decl_list);
X
X out_char(';');
X /* Eat closing 'END [<proc name>];' */
X token_class = get_token(&token);
X if ((token_class != RESERVED) ||
X (token.token_type != END)) {
X parse_error("END expected");
X return;
X }
X
X out_white_space(&token);
X token_class = get_token(&token);
X if (token_class == IDENTIFIER) {
X token_class = get_token(&token);
X }
X
X if (token_class != END_OF_LINE) {
X parse_error("';' expected");
X }
X
X return;
X } else
X
X if (param_list) {
X out_token(¶m_token);
X /* Output parameter list */
X param_ptr = param_list;
X while (param_ptr) {
X out_token(¶m_ptr->param);
X param_ptr = param_ptr->next_param;
X if (param_ptr)
X out_char(',');
X }
X out_char(')');
X
X /* Parse parameter declarations */
X parse_param_list(param_list, &decl_list,
X &extra_decl_list);
X
X /* Output declarations */
X if (decl_list) {
X out_decl(decl_list);
X /* Add declarations to context */
X add_decl_to_context(decl_list);
X }
X
X out_str("\n{"); /* } for dumb vi */
X
X if (extra_decl_list) {
X out_decl(extra_decl_list);
X /* Add declarations to context */
X add_decl_to_context(extra_decl_list);
X }
X
X /* Discard declarations */
X free_decl(decl_list);
X free_decl(extra_decl_list);
X } else
X /* No parameter list */
X out_str("()\n{"); /* } for dumb vi */
X
X /* Create new context */
X new_context(PROCEDURE, first_token);
X /* Parse statements to END */
X parse_to_end();
X /* Pop procedure context */
X pop_context();
X } else {
X/*
X * Label - add label name
X */
X out_token(first_token);
X /* Add colon */
X out_token(&token);
X
X /* Is this a defined label or a module? */
X if (find_symbol(first_token, &decl_ptr, &decl_id)) {
X if (decl_ptr->type->token_class == LABEL) {
X /* Label - new context */
X new_context(MODULE, first_token);
X parse_statement(&next_token);
X pop_context();
X } else {
X parse_error("Illegal label name");
X return;
X }
X } else
X parse_statement(&next_token);
X }
X return;
X }
X
X /* Assignment statement */
X text_ptr = tmp_text_ptr;
X token_copy(first_token, &token);
X token_class = parse_variable(&token, &decl_ptr, &decl_id);
X
X /* Check for multiple assignments */
X while (token_class == COMMA) {
X /* Print ' =' instead of ',' */
X out_str(" =");
X out_white_space(&token);
X /* Get identifier part of next assignment variable */
X token_class = get_token(&token);
X if (token_class != IDENTIFIER) {
X parse_error("Illegal assignment");
X return;
X }
X
X /* Parse remainder of variable (if any) */
X token_class = parse_variable(&token, &decl_ptr, &decl_id);
X }
X
X if (token_class == OPERATOR) {
X if (token.token_type != EQUAL) {
X parse_error("Illegal use of identifier");
X return;
X }
X
X out_token(&token);
X
X /* Check for POINTER assignment */
X if (decl_ptr->type->token_type == POINTER) {
X /* Yes - cast it */
X out_str(" (");
X out_str(TYPE_POINTER);
X out_str(" *) ");
X }
X
X if (parse_expression(&token) != END_OF_LINE)
X parse_error("';' expected");
X else
X out_token(&token);
X return;
X } else
X
X if (token_class != LABEL) {
X parse_error("Illegal use of identifier");
X return;
X }
X
X}
X
X/*
X * Statement started with ':'
X */
Xparse_label()
X{
X parse_error("Illegal label");
X}
X
X/*
X * End of line (Null statement)
X */
Xparse_eol(first_token)
XTOKEN *first_token;
X{
X out_white_space(first_token);
X out_char(';');
X}
X
X/*
X * ENABLE or DISABLE statement
X */
Xparse_int_ctl(first_token)
XTOKEN *first_token;
X{
X TOKEN token;
X int token_class;
X
X out_token(first_token);
X out_str("()");
X
X token_class = get_token(&token);
X if (token_class != END_OF_LINE) {
X parse_error("';' expected");
X return;
X }
X out_token(&token);
X}
X
X/*
X * OUTPUT, OUTWORD or OUTHWORD statement of form:
X * OUTPUT(port) = expr;
X */
Xparse_outport()
X{
X TOKEN token;
X int token_class;
X
X if (get_token(&token) != LEFT_PAREN) {
X parse_error("'(' expected");
X return;
X }
X out_token(&token);
X
X /* Get port number */
X if (parse_expression(&token) != RIGHT_PAREN) {
X parse_error("'(' expected");
X return;
X }
X out_char(',');
X
X token_class = get_token(&token);
X if ((token_class != OPERATOR) || (token.token_type != EQUAL)) {
X parse_error("'=' expected");
X return;
X }
X
X /* Get expression */
X if (parse_expression(&token) != END_OF_LINE) {
X parse_error("'(' expected");
X return;
X }
X out_char(')');
X out_token(&token);
X}
X
X/*
X * OUTPUT statement
X */
Xparse_output(first_token)
XTOKEN *first_token;
X{
X out_white_space(first_token);
X out_str(FUNC_OUTPUT);
X parse_outport();
X}
X
X/*
X * OUTWORD statement
X */
Xparse_outword(first_token)
XTOKEN *first_token;
X{
X out_white_space(first_token);
X out_str(FUNC_OUTWORD);
X parse_outport();
X}
X
X/*
X * OUTHWORD statement
X */
Xparse_outhword(first_token)
XTOKEN *first_token;
X{
X out_white_space(first_token);
X out_str(FUNC_OUTHWORD);
X parse_outport();
X}
X
X
SHAR_EOF
chmod 0660 parse.c || echo "restore of parse.c fails"
sed 's/^X//' << 'SHAR_EOF' > struct.h &&
X/*
X * Format of a token returned by get_token().
X */
Xtypedef struct TOKEN {
X /* Class of token (see below) */
X int token_class;
X /* Type of token (see below) */
X int token_type;
X /* Converted token name (when applicable) */
X char token_name[MAX_TOKEN_LENGTH];
X /* Pointer to start of token in text_buffer */
X char *token_start;
X /* Number of characters token_start points to */
X int token_length;
X /* Pointer to start of white space in text_buffer */
X char *white_space_start;
X /* Pointer to char after end of white space in text_buffer */
X char *white_space_end;
X#ifdef LINKED_TOKENS
X /* Pointer for use in linked list */
X struct TOKEN *next_token;
X#endif
X} TOKEN;
X
X/*
X * Format of a procedure parameter list
X */
Xtypedef struct PARAM_LIST {
X /* Parameter name */
X TOKEN param;
X /* Pointer for use in linked list */
X struct PARAM_LIST *next_param;
X} PARAM_LIST;
X
X/*
X * Format of a variable in a DECLARE statement.
X */
Xtypedef struct DECL_ID {
X /* Variable name */
X TOKEN *name;
X /* BASED identifier token */
X TOKEN *based_name;
X /* If declared AT in another module */
X BOOLEAN is_ext_at;
X /* Pointer for use in linked list */
X struct DECL_ID *next_var;
X} DECL_ID;
X
X/*
X * Format of an element in a DECLARE statement.
X */
Xtypedef struct DECL_MEMBER {
X /* Linked list of identifiers of designated type */
X DECL_ID *name_list;
X /* LITERALLY string */
X char *literal;
X#ifdef PARSE_LITERALS
X /* Parsed LITERAL token */
X TOKEN *literal_token;
X#endif
X /* Array bound token */
X TOKEN *array_bound;
X /* Type of variable (INTEGER, WORD, LABEL, LITERALLY, etc.) */
X TOKEN *type;
X /* Attributes (NONE, EXTERNAL or PUBLIC) */
X int attributes;
X /* Initialization attribute (NONE, INITIAL or DATA) */
X /* If PROCEDURE, DATA if has parameters */
X int initialization;
X /* Pointer to linked list of structure elements */
X struct DECL_MEMBER *struct_list;
X /* Pointer to parsed AT expression */
X char *at_ptr;
X /* Pointer in text_buffer to start of INITIAL/DATA values */
X char *init_ptr;
X /* Pointer for use in linked list */
X struct DECL_MEMBER *next_member;
X} DECL_MEMBER;
X
X/*
X * Format of a DECLARE statement.
X */
Xtypedef struct DECL {
X /* DECLARE token */
X TOKEN *decl_token;
X /* Linked list of DECL_MEMBERs */
X DECL_MEMBER *decl_list;
X /* Pointer for use in linked list */
X struct DECL *next_decl;
X} DECL;
X
X/*
X * Format of a context element
X */
Xtypedef struct CONTEXT {
X /* Type of context (MODULE, PROCEDURE or DO) */
X int context_type;
X /* Name of module or procedure */
X TOKEN *context_name;
X /* Pointer to linked list of declaration members */
X DECL_MEMBER *decl_head;
X /* Pointer for use in linked list */
X struct CONTEXT *next_context;
X} CONTEXT;
X
X
X/*
X * Format of a PL/M identifier equivalent
X */
Xtypedef struct {
X char *id_name, *new_id;
X} CVT_ID;
X
X
X/*
X * Format of a PL/M reserved word
X */
Xtypedef struct {
X char *name;
X int token;
X} RESERVED_WORD;
X
X/*
X * Format of a PL/M reserved operator
X */
Xtypedef struct {
X char *operator;
X char *cvt_operator;
X int name;
X} RESERVED_OPERATOR;
X
SHAR_EOF
chmod 0660 struct.h || echo "restore of struct.h fails"
sed 's/^X//' << 'SHAR_EOF' > test.c.out &&
X
X
Xextern farp();
X
X
Xslug()
X{
X void *ptr;
X short i;
X short **iptr = (short **) &ptr;
X float j;
X float k;
X float l;
X WORD mqaFOO;
X DWORD fooBAR;
X
X ptr = (void *) &i;
X (**iptr) = 72;
X iptfil();
X setinterrput(0, farp);
X signal(abs(i), (short) (i));
X j = (float) ((short) (i));
X
X} /* slug */
X
X
SHAR_EOF
chmod 0660 test.c.out || echo "restore of test.c.out fails"
sed 's/^X//' << 'SHAR_EOF' > test.plm &&
XFOO: DO;
X
XFARP: PROCEDURE EXTERNAL;
XEND;
X
XSLUG :PROCEDURE;
X DECLARE PTR POINTER;
X DECLARE I INTEGER;
X DECLARE IPTR BASED PTR INTEGER;
X DECLARE J REAL;
X declare k real;
X declare l REAL;
X declare mqaFOO WORD;
X declare FOObar DWORD;
X
X PTR = @I;
X IPTR = 72;
X CALL IPTFIL;
X CALL SET$INTERRPUT(0, FARP);
X CALL SET$INTERRUPT(IABS(I), FIX(I));
X J = FLOAT(FIX(I));
X
XEND SLUG;
X END FOO;
X
SHAR_EOF
chmod 0660 test.plm || echo "restore of test.plm fails"
sed 's/^X//' << 'SHAR_EOF' > tkn_defs.h &&
X/*
X * Reserved word list
X */
XRESERVED_WORD reserved_words[] = {
X
X /* Statements */
X "DECLARE", DECLARE,
X "DO", DO,
X "END", END,
X "IF", IF,
X "THEN", THEN,
X "ELSE", ELSE,
X "GOTO", GOTO,
X "GO", GO,
X "CALL", CALL,
X "RETURN", RETURN,
X "DISABLE", DISABLE,
X "ENABLE", ENABLE,
X "OUTPUT", OUTPUT,
X "OUTWORD", OUTWORD,
X "OUTHWORD", OUTHWORD,
X
X /* Operators */
X "AND", AND,
X "OR", OR,
X "XOR", XOR,
X "NOT", NOT,
X "MOD", MOD,
X "PLUS", PLUS,
X "MINUS", MINUS,
X
X /* DO options */
X "CASE", CASE,
X "WHILE", WHILE,
X "TO", TO,
X "BY", BY,
X
X /* DECLARE types */
X "BYTE", BYTE,
X "WORD", WORD,
X "DWORD", DWORD,
X "INTEGER", INTEGER,
X "REAL", REAL,
X "SELECTOR", SELECTOR,
X "ADDRESS", ADDRESS,
X "STRUCTURE", STRUCTURE,
X "LABEL", LABEL,
X "POINTER", POINTER,
X "BASED", BASED,
X "LITERALLY", LITERALLY,
X
X /* DECLARE options */
X "DATA", DATA,
X "EXTERNAL", EXTERNAL,
X "INITIAL", INITIAL,
X "PUBLIC", PUBLIC,
X "AT", AT,
X
X /* Misc reserved words */
X "PROCEDURE", PROCEDURE,
X "REENTRANT", REENTRANT,
X "INTERRUPT", INTERRUPT,
X
X /* End of list */
X "", END_OF_FILE
X};
X
X
X/*
X * Operator list
X */
XRESERVED_OPERATOR reserved_operators[] = {
X "+", "+", PLUS,
X "-", "-", MINUS,
X "*", "*", TIMES,
X "/", "/", DIVIDE,
X "<>", "!=", NOT_EQUAL,
X "<=", "<=", LESS_EQUAL,
X ">=", ">=", GREATER_EQUAL,
X "<", "<", LESS,
X ">", ">", GREATER,
X "=", "=", EQUAL,
X ":=", "=", EQUATE,
X "@", "&", AT_OP,
X "", "", END_OF_FILE
X};
X
X/*
X * Control directives list
X */
XRESERVED_WORD control_directives[] = {
X#ifdef USE_ALL_CONTROLS
X "CODE", C_CODE,
X "CO", C_CODE,
X "NOCODE", C_NOCODE,
X "NOCO", C_NOCODE,
X "COND", C_COND,
X "NOCOND", C_NOCOND,
X "DEBUG", C_DEBUG,
X "DB", C_DEBUG,
X "NODEBUG", C_NODEBUG,
X "NODB", C_NODEBUG,
X "EJECT", C_EJECT,
X "EJ", C_EJECT,
X#endif
X "IF", C_IF,
X "ELSEIF", C_ELSEIF,
X "ELSE", C_ELSE,
X "ENDIF", C_ENDIF,
X "INCLUDE", C_INCLUDE,
X "IC", C_INCLUDE,
X#ifdef USE_ALL_CONTROLS
X "INTERFACE", C_INTERFACE,
X "ITF", C_INTERFACE,
X "LEFTMARGIN", C_LEFTMARGIN,
X "LM", C_LEFTMARGIN,
X "LIST", C_LIST,
X "LI", C_LIST,
X "NOLIST", C_NOLIST,
X "NOLI", C_NOLIST,
X "OBJECT", C_OBJECT,
X "OJ", C_OBJECT,
X "NOOBJECT", C_NOOBJECT,
X "NOOJ", C_NOOBJECT,
X "OPTIMIZE", C_OPTIMIZE,
X "OT", C_OPTIMIZE,
X "OVERFLOW", C_OVERFLOW,
X "OV", C_OVERFLOW,
X "NOOVERFLOW", C_NOOVERFLOW,
X "NOOV", C_NOOVERFLOW,
X "PAGELENGTH", C_PAGELENGTH,
X "PL", C_PAGELENGTH,
X "PAGEWIDTH", C_PAGEWIDTH,
X "PW", C_PAGEWIDTH,
X "PAGING", C_PAGING,
X "PI", C_PAGING,
X "NOPAGING", C_NOPAGING,
X "NOPI", C_NOPAGING,
X "PRINT", C_PRINT,
X "PR", C_PRINT,
X "NOPRINT", C_NOPRINT,
X "NOPR", C_NOPRINT,
X "RAM", C_RAM,
X "ROM", C_ROM,
X "SAVE", C_SAVE,
X "SA", C_SAVE,
X "RESTORE", C_RESTORE,
X "RS", C_RESTORE,
X#endif
X "SET", C_SET,
X "RESET", C_RESET,
X#ifdef USE_ALL_CONTROLS
X "SMALL", C_SMALL,
X "SM", C_SMALL,
X "COMPACT", C_COMPACT,
X "CP", C_COMPACT,
X "MEDIUM", C_MEDIUM,
X "MD", C_MEDIUM,
X "LARGE", C_LARGE,
X "LA", C_LARGE,
X "SUBTITLE", C_SUBTITLE,
X "ST", C_SUBTITLE,
X "SYMBOLS", C_SYMBOLS,
X "SB", C_SYMBOLS,
X "NOSYMBOLS", C_NOSYMBOLS,
X "NOSB", C_NOSYMBOLS,
X "TITLE", C_TITLE,
X "TT", C_TITLE,
X "TYPE", C_TYPE,
X "TY", C_TYPE,
X "NOTYPE", C_NOTYPE,
X "NOTY", C_NOTYPE,
X "XREF", C_XREF,
X "XR", C_XREF,
X "NOXREF", C_NOXREF,
X "NOXR", C_NOXREF,
X "INTVECTOR", C_INTVECTOR,
X "IV", C_INTVECTOR,
X "NOINTVECTOR", C_NOINTVECTOR,
X "NOIV", C_NOINTVECTOR,
X "MOD86", C_MOD86,
X "MOD186", C_MOD186,
X "WORD16", C_WORD16,
X "W16", C_WORD16,
X "WORD32", C_WORD32,
X "W32", C_WORD32,
X#endif
X /* End of list */
X "", END_OF_FILE
X};
X
SHAR_EOF
chmod 0660 tkn_defs.h || echo "restore of tkn_defs.h fails"
sed 's/^X//' << 'SHAR_EOF' > tkn_ext.h &&
X
X/*
X * Reserved word list
X */
Xextern RESERVED_WORD reserved_words[];
X
X/*
X * Operator list
X */
Xextern RESERVED_OPERATOR reserved_operators[];
X
X/*
X * Control directives list
X */
Xextern RESERVED_WORD control_directives[];
SHAR_EOF
chmod 0660 tkn_ext.h || echo "restore of tkn_ext.h fails"
sed 's/^X//' << 'SHAR_EOF' > token.c &&
X#include <stdio.h>
X#include <string.h>
X#include "misc.h"
X#include "defs.h"
X#include "cvt.h"
X#include "struct.h"
X#include "tokens.h"
X#include "tkn_ext.h"
X
XBOOLEAN parsing_literal;
XTOKEN literal_token, eof_token;
Xchar *lit_text_ptr;
X
Xextern char *text_buffer, *text_ptr;
Xextern int line_count;
Xextern char *line_ptr;
Xextern char current_file_name[];
X
X/*
X * get_token() - Fetch a token from the buffer and return type,
X * pointer and associated white space.
X */
Xget_token(token)
XTOKEN *token;
X{
X RESERVED_WORD *word_ptr;
X RESERVED_OPERATOR *op_ptr;
X char token_ch, last_token;
X char *token_name_ptr;
X char *op_name;
X BOOLEAN got_fraction;
X BOOLEAN cvt_case;
X char id[MAX_TOKEN_LENGTH], *id_ptr;
X DECL_MEMBER *decl_ptr;
X DECL_ID *decl_id;
X int token_class;
X char *cvt_ptr;
X TOKEN *token_ptr;
X
X /* Point to start of white space (if any) */
X token->white_space_start = text_ptr;
X token->white_space_end = text_ptr;
X
X /* Get first character */
X token_ch = *text_ptr++;
X
X /* Check for white space */
X while ((token_ch == SPACE) || (token_ch == TAB) || (token_ch == CR) ||
X (token_ch == LF) || (token_ch == '$') ||
X ((token_ch == '/') && (*text_ptr == '*'))) {
X
X if (token_ch == '$') {
X /* Check for a control directive */
X if ((text_ptr - 1 == text_buffer) ||
X (*(text_ptr - 2) == '\n')) {
X out_pre_white(token);
X parse_control();
X
X /* Reset start of white space */
X token->white_space_start = text_ptr;
X token->white_space_end = text_ptr;
X } else {
X parse_error("Illegal character");
X return ERROR;
X }
X } else {
X
X *(token->white_space_end++) = token_ch;
X
X if (token_ch == LF) {
X /* Increment input line count */
X line_count++;
X /* Point to start of line */
X line_ptr = text_ptr;
X } else
X
X if (token_ch == '/') {
X /* Comment - search to end */
X /* Add '*' of comment */
X token_ch = *(token->white_space_end++) = *text_ptr++;
X
X do {
X last_token = token_ch;
X token_ch = *(token->white_space_end++) = *text_ptr++;
X if (token_ch == LF) {
X /* Increment input line count */
X line_count++;
X /* Point to start of line */
X line_ptr = text_ptr;
X }
X } while ((token_ch != '/') || (last_token != '*'));
X }
X }
X
X token_ch = *text_ptr++;
X }
X
X
X /* Point to start of current token */
X token->token_start = text_ptr - 1;
X /* Point to start of converted token */
X token_name_ptr = token->token_name;
X
X if (is_a_char(token_ch)) {
X /* Process identifier */
X#ifdef CONVERT_CASE
X /* Convert identifiers starting with an */
X /* upper-case character to opposite case. */
X cvt_case = is_a_uc_char(token_ch);
X#else
X cvt_case = FALSE;
X#endif
X while (TRUE) {
X if (is_a_char(token_ch)) {
X if (cvt_case) {
X if (is_a_uc_char(token_ch))
X /* Convert to lower-case character */
X *token_name_ptr++ = token_ch + ' ';
X else
X
X /* Convert to upper-case character */
X *token_name_ptr++ = token_ch - ' ';
X } else
X *token_name_ptr++ = token_ch;
X } else
X
X if (is_a_digit(token_ch))
X *token_name_ptr++ = token_ch;
X else
X
X if (token_ch == '_')
X *token_name_ptr++ = token_ch;
X else
X
X if (token_ch == '$')
X#ifdef CONVERT_DOLLAR
X *token_name_ptr++ = CONVERT_DOLLAR;
X#else
X ;
X#endif
X else
X break;
X
X token_ch = *text_ptr++;
X }
X
X
X /* Mark end of token */
X text_ptr--;
X token->token_length = text_ptr - token->token_start;
X *token_name_ptr = '\0';
X
X /* Get a copy of identifier */
X (void) strcpy(id, token->token_name);
X /* If lower-case, convert to upper case for comparison */
X if (is_a_lc_char(*id)) {
X for (id_ptr = id; *id_ptr; id_ptr++)
X if (is_a_lc_char(*id_ptr))
X *id_ptr -= ' ';
X }
X
X /* Check for reserved word */
X for (word_ptr = &reserved_words[0]; word_ptr->token != END_OF_FILE;
X word_ptr++)
X {
X if (!strcmp(word_ptr->name, id)) {
X
X token->token_type = word_ptr->token;
X
X /* Check for reserved operator */
X switch (token->token_type) {
X
X case AND :
X op_name = AND_OP;
X break;
X
X case OR :
X op_name = OR_OP;
X break;
X
X case NOT :
X op_name = NOT_OP;
X break;
X
X case XOR :
X op_name = "^";
X break;
X
X case MOD :
X op_name = "%";
X break;
X
X case PLUS :
X parse_error("Cannot convert PLUS operator");
X token->token_class = token->token_type = ERROR;
X return ERROR;
X
X case MINUS :
X parse_error("Cannot convert MINUS operator");
X token->token_class = token->token_type = ERROR;
X return ERROR;
X
X default :
X /* Must not be an operator! */
X token->token_class = RESERVED;
X return RESERVED;
X }
X
X /* Switch to appropriate operator */
X (void) strcpy(token->token_name, op_name);
X token->token_class = OPERATOR;
X return OPERATOR;
X }
X }
X
X /* Not a reserved word - must be an identifier */
X token->token_class = token->token_type = IDENTIFIER;
X
X /* Check for a literal */
X if (!parsing_literal && find_symbol(token, &decl_ptr, &decl_id) &&
X (decl_ptr->type->token_type == LITERALLY)) {
X#ifdef CONVERT_CASE
X /* Convert case of literal */
X for (cvt_ptr = token->token_name; *cvt_ptr;
X cvt_ptr++) {
X if (is_a_uc_char(*cvt_ptr))
X *cvt_ptr += 32;
X else
X if (is_a_lc_char(*cvt_ptr))
X *cvt_ptr -= 32;
X }
X#endif
X#ifdef PARSE_LITERALS
X /* Yes - Has literal been parsed? */
X if (decl_ptr->literal_token) {
X /* Yes - return parsed literal token */
X /* with token_name set to literal name */
X token_ptr = decl_ptr->literal_token;
X token->token_class = token_ptr->token_class;
X token->token_type = token_ptr->token_type;
X return token->token_class;
X }
X#endif
X /* Is literal a single token? */
X lit_text_ptr = text_ptr;
X text_ptr = decl_ptr->literal;
X token_class = get_token(&literal_token);
X if (get_token(&eof_token) == END_OF_FILE) {
X /* Yes - return single token with */
X /* token_name set to literal name */
X token->token_class = token_class;
X token->token_type = literal_token.token_type;
X text_ptr = lit_text_ptr;
X parsing_literal = FALSE;
X return token->token_class;
X }
X
X /* No - parse complex literal and replace */
X /* Use of literal declaration */
X parsing_literal = TRUE;
X text_ptr = lit_text_ptr;
X parse_warning("Literal expanded");
X text_ptr = decl_ptr->literal;
X return get_token(token);
X }
X
X return IDENTIFIER;
X } else
X
X if (is_a_digit(token_ch)) {
X /* Process number */
X /* Flag not a floating point number */
X got_fraction = FALSE;
X
X while (TRUE) {
X if (is_a_digit(token_ch))
X *token_name_ptr++ = token_ch;
X else
X
X if (token_ch == '.') {
X got_fraction = TRUE;
X *token_name_ptr++ = token_ch;
X } else
X
X if ((token_ch == 'E') && got_fraction) {
X /* Process exponent */
X *token_name_ptr++ = token_ch;
X /* Signed exponent? */
X if ((*text_ptr != '+') && (*text_ptr != '-')) {
X /* No - default to + exponent */
X *token_name_ptr++ = '+';
X } else {
X /* Yes - add sign */
X token_ch = *text_ptr++;
X *token_name_ptr++ = token_ch;
X }
X } else
X
X /* Assume it's a hex char or constant designator */
X if (is_a_char(token_ch))
X *token_name_ptr++ = token_ch;
X else
X
X if (token_ch != '$')
X break;
X
X token_ch = *text_ptr++;
X }
X
X /* Point to last character in constant */
X token_name_ptr--;
X token_ch = *token_name_ptr;
X
X if (got_fraction) {
X /* Floating point - add suffix */
X *++token_name_ptr = 'F';
X /* Mark end of token */
X *++token_name_ptr = '\0';
X } else
X
X if (token_ch == 'B') {
X parse_error("Binary constant");
X token->token_class = token->token_type = ERROR;
X return ERROR;
X } else
X
X if ((token_ch == 'O') || (token_ch == 'Q')) {
X /* Octal constant */
X /* Mark end of token */
X *token_name_ptr++ = '\0';
X /* Move constant up 1 character */
X while (token_name_ptr != token->token_name) {
X *token_name_ptr = *(token_name_ptr - 1);
X token_name_ptr--;
X }
X
X /* Make a C octal constant */
X *token_name_ptr = '0';
X } else
X
X if (token_ch == 'H') {
X /* Hex constant */
X /* Mark end of token */
X *token_name_ptr++ = '\0';
X token_name_ptr++;
X /* Move constant up 2 characters */
X while (token_name_ptr != (token->token_name + 1)) {
X *token_name_ptr = *(token_name_ptr - 2);
X token_name_ptr--;
X }
X
X /* Make a C hex constant */
X *token_name_ptr-- = 'x';
X *token_name_ptr = '0';
X } else
X
X if (token_ch == 'D')
X /* Decimal constant - ignore 'D' */
X *token_name_ptr = '\0';
X else
X /* Regular constant */
X *++token_name_ptr = '\0';
X
X /* Mark end of token */
X text_ptr--;
X token->token_length = text_ptr - token->token_start;
X
X token->token_class = token->token_type = NUMERIC;
X return NUMERIC;
X } else {
X
X /* Check for operator */
X for (op_ptr = &reserved_operators[0]; op_ptr->name != END_OF_FILE;
X op_ptr++) {
X token->token_length = strlen(op_ptr->operator);
X if (!strncmp(text_ptr - 1, op_ptr->operator,
X token->token_length)) {
X /* Found operator */
X /* Save converted type */
X (void) strcpy(token->token_name, op_ptr->cvt_operator);
X token->token_type = op_ptr->name;
X /* Point past operator */
X text_ptr += token->token_length - 1;
X
X token->token_class = OPERATOR;
X return OPERATOR;
X }
X }
X
X /* Assume single character token */
X *token_name_ptr++ = token_ch;
X *token_name_ptr = '\0';
X /* Mark end of token so far */
X token->token_length = 1;
X
X
X switch (token_ch) {
X
X case ';' :
X token->token_class = token->token_type = END_OF_LINE;
X return END_OF_LINE;
X
X case ':' :
X token->token_class = token->token_type = LABEL;
X return LABEL;
X
X case ',' :
X token->token_class = token->token_type = COMMA;
X return COMMA;
X
X case '.' :
X token->token_class = token->token_type = PERIOD;
X return PERIOD;
X
X case '(' :
X token->token_class = token->token_type = LEFT_PAREN;
X return LEFT_PAREN;
X
X case ')' :
X token->token_class = token->token_type = RIGHT_PAREN;
X return RIGHT_PAREN;
X
X case '\'' :
X /* String constant */
X token_name_ptr--;
X while (1) {
X if (*text_ptr == '\'') {
X if ((*(text_ptr + 1) == '\''))
X text_ptr++;
X else
X break;
X }
X *token_name_ptr++ = *text_ptr++;
X }
X
X text_ptr++;
X *token_name_ptr++ = '\0';
X token->token_length = strlen(token->token_name);
X
X token->token_class = token->token_type = STRING;
X return STRING;
X
X case 0:
X if (parsing_literal) {
X /* Done parsing literal - */
X /* Switch back to text_ptr */
X parsing_literal = FALSE;
X text_ptr = lit_text_ptr;
X return get_token(token);
X }
X token->token_class = token->token_type = END_OF_FILE;
X return END_OF_FILE;
X
X default:
X parse_error("Illegal character");
X /* Eat the evidence */
X token->token_name[0] = '\0';
X token->token_class = token->token_type = ERROR;
X return ERROR;
X }
X }
X}
X
X/*
X * Copy source token to destination token
X */
Xtoken_copy(src, dest)
XTOKEN *src, *dest;
X{
X dest->token_class = src->token_class;
X dest->token_type = src->token_type;
X (void) strcpy(dest->token_name, src->token_name);
X dest->token_start = src->token_start;
X dest->token_length = src->token_length;
X dest->white_space_start = src->white_space_start;
X dest->white_space_end = src->white_space_end;
X}
X
SHAR_EOF
chmod 0660 token.c || echo "restore of token.c fails"
sed 's/^X//' << 'SHAR_EOF' > tokens.h &&
X/**************************
X * Token classes
X *************************/
X#define END_OF_FILE 0
X#define RESERVED 1
X#define IDENTIFIER 2
X#define NUMERIC 3
X#define OPERATOR 4
X#define STRING 5
X#define LABEL 6
X#define END_OF_LINE 7
X#define COMMA 8
X#define PERIOD 9
X#define LEFT_PAREN 10
X#define RIGHT_PAREN 11
X#define SUBSCRIPT 12
X#define MODULE 13
X#define ERROR 19
X
X
X/**************************
X * Token types
X *************************/
X/*
X * Operators
X */
X#define PLUS 20 /* + */
X#define MINUS 21 /* - */
X#define TIMES 22 /* * */
X#define DIVIDE 23 /* / */
X#define NOT_EQUAL 24 /* <> */
X#define LESS_EQUAL 25 /* <= */
X#define GREATER_EQUAL 26 /* >= */
X#define LESS 27 /* < */
X#define GREATER 28 /* > */
X#define EQUAL 29 /* = */
X#define EQUATE 30 /* := */
X#define COLON 31 /* : */
X#define AT_OP 32 /* @ */
X
X/*
X * Reserved word values
X */
X /* Statements */
X#define DECLARE 40
X#define DO 41
X#define END 42
X#define IF 43
X#define THEN 44
X#define ELSE 45
X#define GOTO 46
X#define GO 47
X#define CALL 48
X#define RETURN 49
X#define DISABLE 50
X#define ENABLE 51
X#define OUTPUT 52
X#define OUTWORD 53
X#define OUTHWORD 54
X
X /* Operators */
X#define AND 60
X#define OR 61
X#define XOR 62
X#define NOT 63
X#define MOD 64
X
X /* DO options */
X#define CASE 70
X#define WHILE 71
X#define TO 72
X#define BY 73
X
X /* DECLARE types */
X#define BYTE 80
X#define WORD 81
X#define DWORD 82
X#define INTEGER 83
X#define REAL 84
X#define ADDRESS 85
X#define SELECTOR 86
X#define POINTER 87
X#define STRUCTURE 88
X
X /* DECLARE options */
X#define BASED 90
X#define LITERALLY 91
X#define DATA 92
X#define EXTERNAL 93
X#define INITIAL 94
X#define PUBLIC 95
X#define AT 96
X
X /* Misc reserved words */
X#define PROCEDURE 101
X#define REENTRANT 102
X#define INTERRUPT 103
X
X /* Control Directives */
X#define C_CODE 200
X#define C_NOCODE 201
X#define C_COND 202
X#define C_NOCOND 203
X#define C_DEBUG 204
X#define C_NODEBUG 205
X#define C_EJECT 206
X#define C_IF 207
X#define C_ELSEIF 208
X#define C_ELSE 209
X#define C_ENDIF 210
X#define C_INCLUDE 211
X#define C_INTERFACE 212
X#define C_LEFTMARGIN 213
X#define C_LIST 214
X#define C_NOLIST 215
X#define C_OBJECT 216
X#define C_NOOBJECT 217
X#define C_OPTIMIZE 218
X#define C_OVERFLOW 219
X#define C_NOOVERFLOW 220
X#define C_PAGELENGTH 221
X#define C_PAGEWIDTH 222
X#define C_PAGING 223
X#define C_NOPAGING 224
X#define C_PRINT 225
X#define C_NOPRINT 226
X#define C_RAM 227
X#define C_ROM 228
X#define C_SAVE 229
X#define C_RESTORE 230
X#define C_SET 231
X#define C_RESET 232
X#define C_SMALL 233
X#define C_COMPACT 234
X#define C_MEDIUM 235
X#define C_LARGE 236
X#define C_SUBTITLE 237
X#define C_SYMBOLS 238
X#define C_NOSYMBOLS 239
X#define C_TITLE 240
X#define C_TYPE 241
X#define C_NOTYPE 242
X#define C_XREF 243
X#define C_NOXREF 244
X#define C_INTVECTOR 245
X#define C_NOINTVECTOR 246
X#define C_MOD86 247
X#define C_MOD186 248
X#define C_WORD16 249
X#define C_WORD32 250
X
SHAR_EOF
chmod 0660 tokens.h || echo "restore of tokens.h fails"
sed 's/^X//' << 'SHAR_EOF' > typedefs.c &&
Xtypedef unsigned char BYTE;
Xtypedef unsigned short WORD;
Xtypedef unsigned int DWORD;
Xtypedef short INTEGER;
Xtypedef float REAL;
X
SHAR_EOF
chmod 0660 typedefs.c || echo "restore of typedefs.c fails"
sed 's/^X//' << 'SHAR_EOF' > version.c &&
Xchar version[] = "Version 1.02 (Alpha)";
SHAR_EOF
chmod 0644 version.c || echo "restore of version.c fails"
rm -f s2_seq_.tmp
echo "You have unpacked the last part"
exit 0
More information about the Alt.sources
mailing list