assemble.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. #include <ctype.h>
  2. #include <system.h>
  3. #include <stdio.h>
  4. #if __STDC__
  5. #include <stdarg.h>
  6. extern error(char *, ...);
  7. #else
  8. #include <varargs.h>
  9. #endif
  10. #include "as.h"
  11. #include "const.h"
  12. /* This file contains the routine assemble(). Assemble() cuts an
  13. * assembly instruction in a label, a mnemonic and several operands.
  14. * For a mnemonic,label and operands it calls table writer defined
  15. * routines, process_mnemonic() * process_label() and process_operand(),
  16. * to give the table writer the oppurtunity to do something special.
  17. * At the end assemble() calls the routine belonging to the mnemonic
  18. * with the supplied operands.
  19. * If the table writer has other expectations of assemble() he should
  20. * write his own version.
  21. * Assemble parser the following instructions :
  22. * INSTR ::= [ STRING ':']? [ STRING [ OPERAND ( ',' OPERAND)*]? ]?
  23. * OPERAND ::= STRING [ '{' char* '}' |
  24. * '(' char* ')' |
  25. * '[' char* ']' ]?
  26. * note : nested brackets are not recognized.
  27. */
  28. /* The following global varaibles are defined in the EM_parser.
  29. */
  30. extern char *mnemonic[];
  31. extern int (*instruction[])(), n_mnems;
  32. /* The struct t_operand must be defined by the table writer in "as.h".
  33. * The constant MAX_OPERANDS is defined in "const.h"
  34. * To change MAX_OPERANDS effectively, the last statement in
  35. * execute_mnem() must be changed.
  36. */
  37. struct t_operand operand[ MAX_OPERANDS];
  38. char *skip_space(), *parse_label(), *parse_mnemonic(), *parse_operand(),
  39. *skip_string(), *match_ch(), *Salloc(), *skip_operand();
  40. int label();
  41. assemble( instr)
  42. char *instr;
  43. /* Break an assembly instruction down in a LABEL, MNEMONIC and OPERANDS.
  44. */
  45. {
  46. char *ptr, *copy, *mnem;
  47. int n_ops = 0;
  48. copy = ptr = Salloc( instr, strlen( instr)+1);
  49. ptr = skip_space( ptr);
  50. if ( label( ptr)) { /* Look for a label */
  51. ptr = parse_label( ptr);
  52. if ( *ptr == '\0') return;
  53. }
  54. ptr = parse_mnemonic( ptr, &mnem);
  55. while ( *ptr != '\0') { /* parse operans */
  56. if ( n_ops++ == MAX_OPERANDS)
  57. error( "to many operands\n");
  58. ptr = parse_operand( ptr, n_ops, instr);
  59. }
  60. execute_mnemonic( mnem); /* Execute the assembler instruction */
  61. free( copy);
  62. }
  63. int label( ptr)
  64. char *ptr;
  65. {
  66. ptr = skip_string( ptr);
  67. ptr = skip_space( ptr);
  68. return( *ptr == ':');
  69. }
  70. char *parse_label( ptr)
  71. char *ptr;
  72. {
  73. char *lab = ptr;
  74. ptr = skip_string( ptr);
  75. if ( *ptr == ':')
  76. *ptr++ = '\0';
  77. else {
  78. *ptr++ = '\0';
  79. ptr = skip_space( ptr);
  80. ptr++; /* skip ':' */
  81. }
  82. handle_label( lab);
  83. ptr = skip_space( ptr);
  84. return( ptr);
  85. }
  86. char *parse_mnemonic( ptr, mnem)
  87. char *ptr, **mnem;
  88. {
  89. *mnem = ptr;
  90. ptr = skip_string( ptr);
  91. if ( *ptr != '\0') {
  92. *ptr++ = '\0';
  93. ptr = skip_space( ptr);
  94. }
  95. return( ptr);
  96. }
  97. char *parse_operand( ptr, n_ops, instr)
  98. char *ptr, *instr;
  99. int n_ops;
  100. {
  101. char *op = ptr,
  102. *last;
  103. ptr = skip_operand( ptr, instr);
  104. for( last=ptr-1; isspace( *last); last--)
  105. ;
  106. if ( *ptr == ',') {
  107. ptr = skip_space( ptr + 1);
  108. }
  109. *(last+1) = '\0';
  110. process_operand( op, &operand[ n_ops-1]);
  111. return( ptr);
  112. }
  113. char *skip_operand( ptr, instr)
  114. char *ptr, *instr;
  115. {
  116. while ( *ptr != ',' && *ptr != '\0') {
  117. switch ( *ptr) {
  118. case '{' : ptr = match_ch( '}', ptr, instr);
  119. break;
  120. case '(' : ptr = match_ch( ')', ptr, instr);
  121. break;
  122. case '[' : ptr = match_ch( ']', ptr, instr);
  123. break;
  124. }
  125. ptr++;
  126. }
  127. return( ptr);
  128. }
  129. char *match_ch( c, str, instr)
  130. char c, *str, *instr;
  131. {
  132. char *ptr, *strindex();
  133. ptr = strindex( str, c);
  134. if ( ptr == 0) {
  135. error( "syntax error in %s : %c expected\n", instr, c);
  136. return( str);
  137. }
  138. else
  139. return( ptr);
  140. }
  141. char *skip_string( ptr)
  142. char *ptr;
  143. {
  144. while ( *ptr != '\0' && !isspace( *ptr) && *ptr != ':')
  145. ptr++;
  146. return( ptr);
  147. }
  148. char *skip_space( ptr)
  149. char *ptr;
  150. {
  151. while ( isspace( *ptr) )
  152. ptr++;
  153. return( ptr);
  154. }
  155. /*** Execution **************************************************************/
  156. execute_mnemonic( mnem)
  157. char *mnem;
  158. /* Find the function by "mnem" and execute it.
  159. */
  160. {
  161. int low, mid, high, rel;
  162. process_mnemonic( mnem);
  163. low = 0;
  164. high = n_mnems-1;
  165. while ( TRUE) {
  166. mid = ( low + high) / 2;
  167. rel = strcmp(mnem, mnemonic[ mid]);
  168. if ( rel == 0 )
  169. break;
  170. else if ( high == low) {
  171. error( "can't find %s", mnem);
  172. return;
  173. }
  174. else if ( rel < 0)
  175. high = mid;
  176. else
  177. /* watch it, mid is truncated */
  178. low = ( mid == low ? low + 1: mid);
  179. }
  180. ( *( instruction[ mid]))( &operand[0], &operand[1], &operand[2],
  181. &operand[3]);
  182. }
  183. /*** Error ****************************************************************/
  184. #if __STDC__
  185. /*VARARGS*/
  186. error(char *fmt, ...)
  187. {
  188. va_list args;
  189. extern int yylineno;
  190. extern int nerrors;
  191. va_start(args, fmt);
  192. fprint( STDERR, "ERROR in line %d : ", yylineno);
  193. doprnt( STDERR, fmt, args);
  194. fprint( STDERR, "\n");
  195. va_end(args);
  196. nerrors++;
  197. }
  198. #else
  199. /*VARARGS*/
  200. error(va_alist)
  201. va_dcl
  202. {
  203. char *fmt;
  204. va_list args;
  205. extern int yylineno;
  206. extern int nerrors;
  207. va_start(args);
  208. fmt = va_arg(args, char *);
  209. fprint( STDERR, "ERROR in line %d : ", yylineno);
  210. doprnt( STDERR, fmt, args);
  211. fprint( STDERR, "\n");
  212. va_end(args);
  213. nerrors++;
  214. }
  215. #endif