123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- #include <ctype.h>
- #include <system.h>
- #include <stdio.h>
- #if __STDC__
- #include <stdarg.h>
- extern error(char *, ...);
- #else
- #include <varargs.h>
- #endif
- #include "as.h"
- #include "const.h"
- /* This file contains the routine assemble(). Assemble() cuts an
- * assembly instruction in a label, a mnemonic and several operands.
- * For a mnemonic,label and operands it calls table writer defined
- * routines, process_mnemonic() * process_label() and process_operand(),
- * to give the table writer the oppurtunity to do something special.
- * At the end assemble() calls the routine belonging to the mnemonic
- * with the supplied operands.
- * If the table writer has other expectations of assemble() he should
- * write his own version.
- * Assemble parser the following instructions :
- * INSTR ::= [ STRING ':']? [ STRING [ OPERAND ( ',' OPERAND)*]? ]?
- * OPERAND ::= STRING [ '{' char* '}' |
- * '(' char* ')' |
- * '[' char* ']' ]?
- * note : nested brackets are not recognized.
- */
- /* The following global varaibles are defined in the EM_parser.
- */
- extern char *mnemonic[];
- extern int (*instruction[])(), n_mnems;
- /* The struct t_operand must be defined by the table writer in "as.h".
- * The constant MAX_OPERANDS is defined in "const.h"
- * To change MAX_OPERANDS effectively, the last statement in
- * execute_mnem() must be changed.
- */
- struct t_operand operand[ MAX_OPERANDS];
- char *skip_space(), *parse_label(), *parse_mnemonic(), *parse_operand(),
- *skip_string(), *match_ch(), *Salloc(), *skip_operand();
- int label();
- assemble( instr)
- char *instr;
- /* Break an assembly instruction down in a LABEL, MNEMONIC and OPERANDS.
- */
- {
- char *ptr, *copy, *mnem;
- int n_ops = 0;
- copy = ptr = Salloc( instr, strlen( instr)+1);
- ptr = skip_space( ptr);
- if ( label( ptr)) { /* Look for a label */
- ptr = parse_label( ptr);
- if ( *ptr == '\0') return;
- }
- ptr = parse_mnemonic( ptr, &mnem);
- while ( *ptr != '\0') { /* parse operans */
- if ( n_ops++ == MAX_OPERANDS)
- error( "to many operands\n");
- ptr = parse_operand( ptr, n_ops, instr);
- }
- execute_mnemonic( mnem); /* Execute the assembler instruction */
- free( copy);
- }
- int label( ptr)
- char *ptr;
- {
- ptr = skip_string( ptr);
- ptr = skip_space( ptr);
- return( *ptr == ':');
- }
- char *parse_label( ptr)
- char *ptr;
- {
- char *lab = ptr;
- ptr = skip_string( ptr);
- if ( *ptr == ':')
- *ptr++ = '\0';
- else {
- *ptr++ = '\0';
- ptr = skip_space( ptr);
- ptr++; /* skip ':' */
- }
- handle_label( lab);
- ptr = skip_space( ptr);
- return( ptr);
- }
- char *parse_mnemonic( ptr, mnem)
- char *ptr, **mnem;
- {
- *mnem = ptr;
- ptr = skip_string( ptr);
- if ( *ptr != '\0') {
- *ptr++ = '\0';
- ptr = skip_space( ptr);
- }
- return( ptr);
- }
- char *parse_operand( ptr, n_ops, instr)
- char *ptr, *instr;
- int n_ops;
- {
- char *op = ptr,
- *last;
- ptr = skip_operand( ptr, instr);
- for( last=ptr-1; isspace( *last); last--)
- ;
- if ( *ptr == ',') {
- ptr = skip_space( ptr + 1);
- }
- *(last+1) = '\0';
-
- process_operand( op, &operand[ n_ops-1]);
- return( ptr);
- }
- char *skip_operand( ptr, instr)
- char *ptr, *instr;
- {
- while ( *ptr != ',' && *ptr != '\0') {
- switch ( *ptr) {
- case '{' : ptr = match_ch( '}', ptr, instr);
- break;
- case '(' : ptr = match_ch( ')', ptr, instr);
- break;
- case '[' : ptr = match_ch( ']', ptr, instr);
- break;
- }
- ptr++;
- }
- return( ptr);
- }
- char *match_ch( c, str, instr)
- char c, *str, *instr;
- {
- char *ptr, *strindex();
- ptr = strindex( str, c);
- if ( ptr == 0) {
- error( "syntax error in %s : %c expected\n", instr, c);
- return( str);
- }
- else
- return( ptr);
- }
- char *skip_string( ptr)
- char *ptr;
- {
- while ( *ptr != '\0' && !isspace( *ptr) && *ptr != ':')
- ptr++;
- return( ptr);
- }
- char *skip_space( ptr)
- char *ptr;
- {
- while ( isspace( *ptr) )
- ptr++;
- return( ptr);
- }
- /*** Execution **************************************************************/
- execute_mnemonic( mnem)
- char *mnem;
- /* Find the function by "mnem" and execute it.
- */
- {
- int low, mid, high, rel;
- process_mnemonic( mnem);
- low = 0;
- high = n_mnems-1;
- while ( TRUE) {
- mid = ( low + high) / 2;
- rel = strcmp(mnem, mnemonic[ mid]);
- if ( rel == 0 )
- break;
- else if ( high == low) {
- error( "can't find %s", mnem);
- return;
- }
- else if ( rel < 0)
- high = mid;
- else
- /* watch it, mid is truncated */
- low = ( mid == low ? low + 1: mid);
- }
- ( *( instruction[ mid]))( &operand[0], &operand[1], &operand[2],
- &operand[3]);
- }
- /*** Error ****************************************************************/
- #if __STDC__
- /*VARARGS*/
- error(char *fmt, ...)
- {
- va_list args;
- extern int yylineno;
- extern int nerrors;
- va_start(args, fmt);
- fprint( STDERR, "ERROR in line %d : ", yylineno);
- doprnt( STDERR, fmt, args);
- fprint( STDERR, "\n");
- va_end(args);
- nerrors++;
- }
- #else
- /*VARARGS*/
- error(va_alist)
- va_dcl
- {
- char *fmt;
- va_list args;
- extern int yylineno;
- extern int nerrors;
- va_start(args);
- fmt = va_arg(args, char *);
- fprint( STDERR, "ERROR in line %d : ", yylineno);
- doprnt( STDERR, fmt, args);
- fprint( STDERR, "\n");
- va_end(args);
- nerrors++;
- }
- #endif
|