1 /* This file contains the parser for the 'EM_table'.
2 * Every row in the table is converted to a C-function.
3 * The parser is a fairly simple program, for each row it prints a function-
4 * header and the following actions are printed as C-statements. A CALL is just
5 * copied, and an ASSEM_INSTR will be handed to the routine assemble().
6 * Assemble() will turn the assembly-string into a sequence of C-function calls.
7 * How this should be done is expressed in the 'as_table'.
9 * There are however some complicating factors:
10 * - A row in the 'EM_table' may contain CONDITION's.
11 * The parser supports this by outptutting some "if" and "else"'s.
13 * - The user is allowed to use some abbreviation in the 'EM_table', (s)he
14 * can use the DEF_C_INSTR's ( e.g. C_loe..).
15 * One such DEF_C_INSTR must be expanded in 3 or more C-functions.
16 * The solution is to copy the DEF_C_INSTR to a temporary file. Then
17 * this file will be processed as many times as needed to generate all
20 * - The assembler-instructions must be processed in blocks not one at a
21 * time, so buffering is needed.
23 * - When generating object-code, the user can make use of the dist()
24 * function. This function should return the number of bytes between
25 * the current instruction and a labelled one, both forward and backward
26 * references must be handled.
27 * This requires the saving of the generated function, and
28 * backpatching in a second phase.
39 extern int first_action, last_action, token;
42 int no_conversions = FALSE, library, segment = UNKNOWN;
48 %token C_INSTR, DEF_C_INSTR, CONDITION, ARROW,
49 CALL, ASSEM_INSTR, DEFAULT, ERROR;
51 %start def_row, def_row;
52 %start c_table, c_table;
53 %lexical lex_analyzer ;
59 row : C_INSTR { set_outfile( yytext); header( yytext);
62 [ special | simple] { out( "}\n\n");}
64 | DEF_C_INSTR { init_defaults( yytext);}
65 [ Dspecial | Dsimple] { handle_defaults();}
69 { out( "if( 0 ) ;\n"); }
71 [ CONDITION { out( "else "); question( &yytext[0]);}
72 simple { out( "}\n");}
75 DEFAULT { out( "else {\n");}
76 simple { out( "}\n");}
79 simple : ARROW { save_output();}
80 actionlist { back_patch();}
84 actionlist : { first_action = TRUE;}
85 [ action { first_action = FALSE;}
91 action : CALL { print_call( &yytext[0]);}
93 | as_block { last_action = ( token == '.');
98 as_block : { init_as_block();}
99 ASSEM_INSTR { save_as( &yytext[0]);}
104 %if ( next_token() == ASSEM_INSTR)
106 ASSEM_INSTR { save_as( &yytext[0]);}
112 /* Grammar rules for a default-instruction, just copy to a temporary file. */
114 Dspecial: CONDITION { out( " %s ", yytext);}
117 [ CONDITION { out( " %s ", yytext);}
121 DEFAULT { out( " %s ", yytext);}
125 Dsimple : ARROW { out( "%s", yytext);}
132 [ ';' { out( ";\n");}
139 Daction : CALL { out( "%s", yytext);}
141 | ASSEM_INSTR { out( "\"%s\"", yytext);}
145 def_row : { set_segment(segment);}
146 [ special | simple] { out( "}\n\n");}
151 /* This is a grammar to handle the -c flag ( only one entry has changed).
152 * Skip all entries in the table until the one that has changed, then
153 * use the grammar rules for the normal case above.
159 c_row : %if ( to_change && strcmp( yytext, to_change) == 0)
160 C_INSTR { set_outfile( yytext); header( yytext);
161 set_segment(segment);
163 [ special | simple] { out( "}\n\n"); to_change = 0; }
166 [ c_special | c_simple]
168 | %if ( to_change && strcmp( yytext, to_change) == 0)
169 DEF_C_INSTR { init_defaults( yytext);}
170 [ Dspecial | Dsimple] { handle_defaults(); to_change = 0; }
173 [ c_special | c_simple]
176 c_special : CONDITION
193 [ c_action [ ';' c_action]* ]? '.'
206 int saved = 0, token;
210 LLmessage( inserted_token)
214 if ( inserted_token == 0) {
215 fprint( STDERR, "EM_table : syntax error in line %d, >>",
217 print_token( LLsymb);
218 fprint( STDERR, "<< will be deleted!!\n");
220 else if ( inserted_token < 0) {
221 fprint(STDERR,"EM_table : syntax error in line %d, garbage at end of table\n",
225 fprint( STDERR, "EM_table : syntax error in line %d, >>",
227 print_token( inserted_token);
228 fprint( STDERR, "<< will be inserted!!\n");
238 case C_INSTR : fprint( STDERR, "C_INSTR %s", yytext);
240 case ASSEM_INSTR : fprint( STDERR, "STRING %s", yytext);
242 case CALL : fprint( STDERR, "CALL %s", yytext);
244 case ARROW : fprint( STDERR, "==> ");
246 case CONDITION: fprint( STDERR, "CONDITION %s", yytext);
248 case DEFAULT : fprint( STDERR, "default ");
250 case ERROR : fprint( STDERR, "unmatched %s", yytext);
252 default : fprint( STDERR, " %c", token);
258 /* The lexical analyzer.
259 * It uses mylex() to get the tokens.
260 * It supports the buffering of one token.
261 * If the curent token is a C_INSTR it will set the global variable
262 * 'C_instr_info' to point to the correct information ( arguments, header,
277 if ( token == C_INSTR)
278 set_C_instr_info( yytext);
295 /******************************************************************************/
297 /* Handle arguments :
298 * -l : Library, generate one function per file.
299 * -c <name> : Change, only update the <name> file.
311 if ( strcmp( argv[1], "-l") == 0)
313 else if( strcmp( argv[1], "-c") == 0) {
318 fprint( STDERR, "No rule for %s\n", to_change);