home *** CD-ROM | disk | FTP | other *** search
/ Total Destruction / Total_Destruction.iso / addons / Lccwin32.exe / Lccwin32 / lccpub / src / Asm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-11  |  179.4 KB  |  5,652 lines

  1. #include "c.h"
  2. #include "asm.h"
  3. #include "i386.h"
  4. #include "i386-opc.h"
  5. #include "cv.h"
  6. extern void * _stdcall GlobalAlloc(unsigned int,unsigned int);
  7. extern void _stdcall GlobalFree(void *);
  8. #define BUFFER_SIZE (32 * 1024)
  9. typedef char operator_rankT;
  10. extern int OptimizeFlag;
  11. /* Prototypes */
  12. static char * xmalloc (long n );
  13. static void StringAppend (char * * charPP ,char * fromP ,unsigned long length );
  14. static void subsegs_begin (void);
  15. static void subseg_change (register segT seg ,register int subseg );
  16. static void subseg_new (register segT seg ,register subsegT subseg );
  17. static void symbol_begin (void);
  18. static symbolS * symbol_new (char * name ,unsigned char type ,valueT value ,struct frag * frag );
  19. static void colon (register char * sym_name );
  20. static void symbol_table_insert (symbolS * symbolP );
  21. static void SetFlags(symbolS *coffS);
  22. static symbolS * symbol_find_or_make (char * name );
  23. static void frag_grow (unsigned int nchars );
  24. static void frag_new (int old_frags_var_max_size );
  25. static char * frag_more (int nchars );
  26. static char * frag_var (relax_stateT type ,int max_chars ,int var ,relax_substateT subtype ,symbolS * symbol ,long int offset ,char * opcode );
  27. static void frag_wane (fragS * fragP );
  28. static void frag_align (int alignment ,int fill_character );
  29. static segT operand (register expressionS * expressionP );
  30. static void clean_up_expression (register expressionS * expressionP );
  31. static segT expr_part (symbolS * * symbol_1_PP ,symbolS * symbol_2_P );
  32. static segT AsmExpression (register operator_rankT rank ,register expressionS * resultP );
  33. static char get_symbol_end (void);
  34. static char * input_file_give_next_buffer (char * where );
  35. static void InitAsmInput (void);
  36. static char * SetObjFileName (char * filename );
  37. static char * input_scrub_next_buffer (char * * bufp );
  38. static void bump_line_counters (void);
  39. static void as_where (void);
  40. static void as_perror (char * gripe ,char * filename );
  41. static void _obstack_begin (struct obstack * h ,int size ,int alignment ,void *(*chunkfun )(int),void (* freefun )(void *));
  42. static void _obstack_newchunk (struct obstack * h ,int length );
  43. static void read_begin (void);
  44. static char * hash_insert (struct HASH_LIST * where ,char * name ,char * data );
  45. static char * hash_find (struct HASH_LIST * w ,char * n );
  46. static struct HASH_LIST * hash_new (void);
  47. static char * hash_jam (struct HASH_LIST * where ,char * n ,char * data );
  48. static void s_align (void);
  49. static void s_byte(void);
  50. static void s_short(void);
  51. static void s_int(void);
  52. static void s_comm (void);
  53. static void s_data (void);
  54. static void s_file (void);
  55. static void s_globl (void);
  56. static void s_lcomm (void);
  57. static void s_line (void);
  58. static void s_lsym (void);
  59. static void s_space (void);
  60. static void s_text (void);
  61. static void s_section(void);
  62. static void s_type (void);
  63. static void s_size (void);
  64. static void demand_empty_rest_of_line (void);
  65. static void ignore_rest_of_line (void);
  66. static void stab (int what );
  67. static void pseudo_set (symbolS * symbolP );
  68. static void cons (int nbytes );
  69. static void stringer (int append_zero );
  70. static int next_char_of_string (void);
  71. static segT get_segmented_expression (register expressionS * expP );
  72. static segT get_known_segmented_expression (expressionS * expP );
  73. static long int get_absolute_expression (void);
  74. static char get_absolute_expression_and_terminator (long int * val_pointer );
  75. static char * demand_copy_C_string (int * len_pointer );
  76. static char * demand_copy_string (int * lenP );
  77. static int is_it_end_of_statement (void);
  78. static void equals (char * sym_name );
  79. static void InitializeAsmTables (void);
  80. static int i386_operand (char *,char * );
  81. static int md_estimate_size_before_relax (register fragS * fragP ,register int segment_type );
  82. static void md_convert_frag (register fragS * fragP );
  83. static void md_number_to_chars (char con [ ] ,long int value ,int nbytes );
  84. static char * output_invalid (char c );
  85. #ifndef ASM_LIB
  86. static
  87. #else
  88. extern
  89. #endif
  90. reg_entry * parse_register (char * reg_string );
  91. static void WriteCoffHeader (void);
  92. static long WriteTextSection (long siz ,long nfixups );
  93. static long WriteDataSection (long siz ,long nfixups ,int addr );
  94. static long WriteBssSection (long siz );
  95. static int ArrangeDataSection (int ordinal );
  96. static int ArrangeOrdinalNumbers (char * name );
  97. static int SortFun (const void * f1 ,const void * f2 );
  98. static int WriteRelocations (int which);
  99. static STRING * NewString (char * s ,int len );
  100. static int AddStringToStringTable (char * str );
  101. static long WriteStringTable (void);
  102. static int SortSymbols (const void * f1 ,const void * f2 );
  103. static int WriteLineNumbers (int PosCodeSection );
  104. static int WriteOneSymbol (char * p );
  105. static int WriteFunctionRecords (symbolS * coffS );
  106. static int SymbolToChars (symbolS * coffS );
  107. static int WriteDataSymbols (int count );
  108. static int WriteSpecialSymbols (int result );
  109. static int WriteAllCoffSymbols (int startCount );
  110. static int WriteFileName (char * name );
  111. static COFF_RELOC * AddCoffRelocation (symbolS * coffS ,int where ,int pcrel );
  112. static void newFixup(fragS * frag ,int where ,short int size ,symbolS * add_symbol ,symbolS * sub_symbol ,long int offset ,int pcrel );
  113. static void relax_segment (struct frag * segment_frag_root ,segT segment_type );
  114. static relax_addressT relax_align (register relax_addressT address ,register long int alignment );
  115. static long int fixup_segment (fixS * fixP ,int this_segment_type );
  116. static int FixRelocations(register fixS * fixP);
  117. #ifdef ASM_LIB
  118. extern int is_dnrange (struct frag *f1,struct frag *f2);
  119. #else
  120. static int is_dnrange (struct frag * f1 ,struct frag * f2 );
  121. #endif
  122. int main (int argc ,char * * argv );
  123. void WriteError(void);
  124. void InternalError(int err);
  125. static void MakeBssSymbol(symbolS *symbolP,int siz,int localflag);
  126.  
  127. #define HASHSIZE 1024
  128. fixS *   text_fix_root;  /* Chains fixSs. */
  129. fixS *   data_fix_root;  /* Chains fixSs. */
  130. fixS **  seg_fix_rootP;  /* -> one of above. */
  131.  
  132. /* --------------------------------------------------Sections stuff */
  133. static int IsSpecialSection = 0;
  134. static int NumberOfSpecialSections,NumberOfDebugSections;
  135. NewSection *SectionList,*CurrentSpecialSection;
  136.  
  137. static void Asm386Instruction(char *line);
  138. static struct obstack frags;    /* All, and only, frags live here. */
  139. static    char    * InputPointer; /* -> char we are parsing now. */
  140. static STRING_TABLE *StringTable;
  141. int    need_pass_2;    /* TRUE if we need a second pass. */
  142. /* used by is_... macros. our ctype[] */
  143. static char lex_type[256] = {
  144.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */
  145.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */
  146.     0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
  147.     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0123456789:;<=>? */
  148.                                                     /* @ is part of name */
  149.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */
  150.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, /* PQRSTUVWXYZ[\]^_ */
  151.     0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* `abcdefghijklmno */
  152.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, /* pqrstuvwxyz{|}~. */
  153.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  154.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  155.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  156.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  157.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  158.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  159.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  160. };
  161. static char *buffer_limit;  /* -> 1 + last char in buffer. */
  162. static char *old_buffer = 0;    /* JF a hack */
  163. static char *old_input;
  164. static char *old_limit;
  165. static pseudo_typeS potable[] =
  166. {
  167.     {"align", s_align},
  168.     {"byte", s_byte},
  169.     {"comm", s_comm},
  170.     {"data", s_data},
  171.     {"file", s_file},
  172.     {"globl", s_globl},
  173.     {"int", s_int},
  174.     {"lcomm", s_lcomm},
  175.     {"line", s_line},
  176.     {"long", s_int},
  177.     {"lsym", s_lsym},
  178.     {"short", s_short},
  179.     {"space", s_space},
  180.     {"text", s_text},
  181.     {"type", s_type},
  182.     {"size", s_size},
  183.     {"extern", s_globl},
  184.     {"bss", s_data},
  185.     {"section",s_section},
  186.     {"word", s_short},
  187.     {NULL}              /* end sentinel */
  188. };
  189.  
  190. /*
  191. Interface to relax_segment.
  192. There are 2 relax states for 386 jump insns: one for conditional & one
  193. for unconditional jumps.  This is because the these two types of jumps
  194. add different sizes to frags when we're figuring out what sort of jump
  195. to choose to reach a given label.  */
  196. /* types */
  197. #define COND_JUMP 1     /* conditional jump */
  198. #define UNCOND_JUMP 2   /* unconditional jump */
  199. /* sizes */
  200. #define BYTE 0
  201. #define WORD 1
  202. #define DWORD 2
  203. #define UNKNOWN_SIZE 3
  204. #define ENCODE_RELAX_STATE(type,size) ((type<<2) | (size))
  205. #define SIZE_FROM_RELAX_STATE(s) \
  206.   ( (((s) & 0x3) == BYTE ? 1 : (((s) & 0x3) == WORD ? 2 : 4)) )
  207. static relax_typeS md_relax_table[] = {
  208. /*
  209.   The fields are:
  210.    1) most positive reach of this state,
  211.    2) most negative reach of this state,
  212.    3) how many bytes this mode will add to the size of the current frag
  213.    4) which index into the table to try if we can't fit into this one.
  214. */
  215.     {1, 1, 0, 0},
  216.     {1, 1, 0, 0},
  217.     {1, 1, 0, 0},
  218.     {1, 1, 0, 0},
  219.     /* For now we don't use word displacement jumps:  they may be
  220.     untrustworthy. */
  221.     {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE(COND_JUMP, DWORD)},
  222.     /* word conditionals add 3 bytes to frag: 2 opcode prefix; 1 displacement
  223.     bytes */
  224.     {32767 + 2, -32768 + 2, 3, ENCODE_RELAX_STATE(COND_JUMP, DWORD)},
  225.     /* dword conditionals adds 4 bytes to frag: 1 opcode prefix; 3
  226.     displacement bytes */
  227.     {0, 0, 4, 0},
  228.     {1, 1, 0, 0},
  229.     {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE(UNCOND_JUMP, DWORD)},
  230.     /* word jmp adds 2 bytes to frag: 1 opcode prefix; 1 displacement bytes */
  231.     {32767 + 2, -32768 + 2, 2, ENCODE_RELAX_STATE(UNCOND_JUMP, DWORD)},
  232.     /* dword jmp adds 3 bytes to frag: 0 opcode prefix; 3 displacement bytes */
  233.     {0, 0, 3, 0},
  234.     {1, 1, 0, 0},
  235. };
  236. static frchainS *frchain_root, *frchain_now,
  237.             *data0_frchainP;
  238. static fragS *    frag_now;    /* -> current frag we are building. */
  239.                 /* This frag is incomplete. */
  240.                 /* It is, however, included in frchain_now. */
  241.                 /* Frag_now->fr_fix is bogus. Use: */
  242. /* Virtual frag_now->fr_fix==obstack_next_free(&frags)-frag_now->fr_literal.*/
  243. static fragS zero_address_frag = {
  244.     0,                  /* fr_address */
  245.     NULL,               /* fr_next */
  246.     0,                  /* fr_fix */
  247.     0,                  /* fr_var */
  248.     0,                  /* fr_symbol */
  249.     0,                  /* fr_offset */
  250.     NULL,               /* fr_opcode */
  251.     rs_fill,            /* fr_type */
  252.     0,                  /* fr_subtype */
  253.     0                   /* fr_literal [0] */
  254. };
  255. static fragS bss_address_frag = {
  256.     0,                  /* fr_address. Gets filled in to make up SymbolValue-s. */
  257.     NULL,               /* fr_next */
  258.     0,                  /* fr_fix */
  259.     0,                  /* fr_var */
  260.     0,                  /* fr_symbol */
  261.     0,                  /* fr_offset */
  262.     NULL,               /* fr_opcode */
  263.     rs_fill,            /* fr_type */
  264.     0,                  /* fr_subtype */
  265.     0                   /* fr_literal [0] */
  266. };
  267. static subsegT            now_subseg;
  268.                 /* What subseg we are accreting now? */
  269.  
  270.  
  271. static segT            now_seg;
  272.                 /* Segment our instructions emit to. */
  273.                 /* Only OK values are SEG_TEXT or SEG_DATA. */
  274. static struct hash_control *sy_hash;    /* symbol-name => struct symbol
  275.                         pointer */
  276. static unsigned int local_bss_counter;
  277. static symbolS *symbol_rootP;
  278. static symbolS *symbol_lastP;
  279. static symbolS abs_symbol;
  280. static struct obstack notes;
  281. /* tables for lexical analysis */
  282. static char opcode_chars[256];
  283. #ifndef ASM_LIB
  284. static
  285. #endif
  286. char register_chars[256];
  287. static char operand_chars[256];
  288. static char space_chars[256];
  289. static char identifier_chars[256];
  290. static char digit_chars[256];
  291. #ifndef ASM_LIB
  292. static
  293. #endif
  294. char RegisterNames[MAX_REG_NAMES * 6];
  295.  
  296. static char *SourceFileName = "";
  297. char *OutputFileName;
  298.  
  299. /*
  300. Errors
  301. ------
  302. 1000    Symbol is already defined
  303. 1001    Symbol %s already defined.
  304. 1002    Inserting symnol into symbol table failed
  305. 1003    Can't extend frag
  306. 1004    "integer overflow in constant"
  307. 1005    "No floating point constants supported"
  308. 1006    "Source line too long.
  309. 1007    error constructing pseudo-op table
  310. 1008    bad .type construct
  311. 1009    "Internal Error:  Can't hash %s: %s", prev_name, hash_err
  312. 1010    Unknown pseudo-op:
  313. 1011    Spurious digit
  314. 1012    Synchronization problem at character ...
  315. 1013    Alignment too large
  316. 2014    Alignment negative
  317. 2015    Expected comma after symbol-name
  318. 2016    Bad expression
  319. 1017    Unknown expression: symbols %s and %s are in different frags
  320. 1018    invalid character %s in opcode"
  321. 1019    expecting prefix; got nothing"
  322. 1020    no such opcode prefix ('%s')", token_start)
  323. 1021    same prefix used twice; you don't really want this!
  324. 1022    too many opcode prefixes
  325. 1023    expecting opcode; got nothing
  326. 1024    no such 386 instruction: `%s'", token_start
  327. 1025    expecting string instruction after rep/repne
  328. 1026    invalid character %s before %s operand",
  329. 1027    unbalenced parenthesis in %s operand.",
  330. 1028    invalid character %s in %s operand",
  331. 1029    spurious operands; (%d operands/instruction max)
  332. 1030    expecting operand after ','; got nothing
  333. 1031    expecting operand before ','; got nothing
  334. 1032    operands given don't match any known 386 instruction
  335. 1033    no opcode suffix given; can't determine immediate size
  336. 1034    no opcode suffix given; can't determine immediate size
  337. 1035    no opcode suffix given and no register operands; can't size instruction
  338. 1036    %d prefixes given and 'w' opcode suffix gives too many prefixes",
  339. 1037    you can't 'pop cs' on the 386."
  340. 1038    %d prefixes given and %s segment override gives too many prefixes",
  341. 1039    "loop/jecx only takes byte displacement
  342. 1040    can't handle non absolute segment in long call/jmp"
  343. 1041    bad register name
  344. 1042    bad memory operand after segment override"
  345. 1043    only 1 or 2 immediate operands are allowed"
  346. 1044    missing or invalid immediate expression '%s'
  347. 1045    Unimplemented segment type %d in parse_operand"
  348. 1046    more than 1 memory reference in instruction"
  349. 1047    can't find base register name
  350. 1048    bad base register name
  351. 1049    expecting ',' or ')' after base register
  352. 1050    bad index register name
  353. 1051    can't find a scale factor after ','
  354. 1052    can't find a scale factor after ','
  355. 1053    expecting scale factor of 1, 2, 4, 8;
  356. 1054    expecting index register or scale factor after ','
  357. 2055    Ignoring junk '%s' after expression", InputPointer);
  358. 1056    missing or invalid displacement
  359. 1057    register size mismatch in (base,index,scale) expression
  360. 1058    base/index register must be 32 bit register"
  361. 1059    may not be used as an index register
  362. 1060    invalid char %s begining %s operand '%s'
  363. 3061    Missing ')' assumed"
  364. 3062    Unary operator %c ignored because bad operand follows", c);
  365. 1063    Expression too complex
  366. 1064    .COMMon length (%d.) <0!
  367. 1065    not used
  368. 1066    Missing operand value
  369. 1067    Expression too complex:
  370. 1068    Relocation error.
  371. 1069    Division by 0
  372. 2070    Partial line at end of file ignored
  373. 1071    Length of .comm \"%s\" is already %d
  374. 1072    Expected comma after name
  375. 1073    BSS length (%d.) <0! Ignored.
  376. 1074    Ignoring attempt to re-define symbol
  377. 1075    Expected comma after name
  378. 1076    Repeat < 0,in .space
  379. 2077    Rest of line ignored.
  380. 1078    need a comma after symbol's name
  381. 1079    want a comma after the n_type expression
  382. 1080    want a comma after the n_other expression
  383. 1081    I want a comma after the n_desc expression
  384. 1082    Missing expression
  385. 1083    %s number illegal
  386. 1084    No expression
  387. 1085    expression too complex
  388. 1086    Unknown expression
  389. 1087    Substracting expression too complicated
  390. 1088    number illegal
  391. 1089    missing expression
  392. 1090    Value x%x truncated to x%x
  393. 1091    Expected "-ed string
  394. 1092    Bad escaped character in string
  395. 1093    Expected address expression: absolute 0 assumed
  396. 1094    Symbols are undefined
  397. 1095    Symbol is undefined
  398. 1096    Bad Absolute Expression
  399. 2097    This string may not contain zeros
  400. 1098    Missing string
  401. 1099    Illegal segment %d.
  402. 1100    Negative of non-absolute symbol
  403. 1101    Can't emit reloc
  404. 1102    Fixup of %d too large for field width
  405. 1103    Bad case in cleanup_expression
  406. 1104    Bad case in function expr
  407. 1105    Bad case in function stab
  408. 1106    not used
  409. 1107    Bad case in cons
  410. 1108    Bad case in md_convert_frag
  411. 1109    Bad case in WriteCoffFile
  412. 1110    Bad case in relax_segment
  413. 1111    Bad case in relax_segment
  414. 1112    Bad case in fixup_segment
  415. 1113    Null pointer in symbol->FnInfo field
  416. 1114    input and output file names are the same
  417. 1115    error in adding up symbol types info
  418. 1116    Relocation to another special section needed
  419. */
  420. #undef __
  421. #define __ (42)         /* blatently illegal digit value */
  422.                         /* exceeds any normal radix */
  423. static const char hex_value[256] = {    /* for fast ASCII -> binary */
  424.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  425.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  426.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  427.     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, __, __, __, __, __, __,
  428.     __, 10, 11, 12, 13, 14, 15, __, __, __, __, __, __, __, __, __,
  429.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  430.     __, 10, 11, 12, 13, 14, 15, __, __, __, __, __, __, __, __, __,
  431.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  432.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  433.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  434.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  435.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  436.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  437.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  438.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  439.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __
  440. };
  441. static char *xmalloc(long n)
  442. {
  443.     char *retval;
  444.     if (!(retval = malloc((unsigned) n))) {
  445.         error("virtual memory exceeded");
  446.         exit(1);
  447.     }
  448.     memset(retval, 0, n);
  449.     return (retval);
  450. }
  451. /* Append a string onto another string */
  452. static void StringAppend(char **charPP, char *fromP, unsigned long length)
  453. {
  454.     if (length) {       /* Don't trust bcopy() of 0 chars. */
  455.         memcpy(*charPP, fromP, (int) length);
  456.         *charPP += length;
  457.     }
  458. }
  459. static const int        /* in: segT   out: N_TYPE bits */
  460. seg_N_TYPE[] = {
  461.     N_ABS,
  462.     N_TEXT,
  463.     N_DATA,
  464.     N_BSS,
  465.     N_UNDF,
  466.     N_UNDF,
  467.     N_UNDF,
  468.     N_UNDF,
  469.     N_UNDF,
  470.     N_UNDF
  471. };
  472. static const segT N_TYPE_seg[N_TYPE + 2] =  /* N_TYPE == 0x1E = 32-2 */
  473. {
  474.     SEG_UNKNOWN,        /* N_UNDF == 0 */
  475.     SEG_GOOF,
  476.     SEG_ABSOLUTE,       /* N_ABS == 2 */
  477.     SEG_GOOF,
  478.     SEG_TEXT,           /* N_TEXT == 4 */
  479.     SEG_GOOF,
  480.     SEG_DATA,           /* N_DATA == 6 */
  481.     SEG_GOOF,
  482.     SEG_BSS,            /* N_BSS == 8 */
  483.     SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
  484.     SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
  485.     SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF
  486. };
  487. static void subsegs_begin(void)
  488. {
  489.     /* Check table(s) seg_name[], seg_N_TYPE[] is in correct order */
  490.     know(SEG_ABSOLUTE == 0);
  491.     know(SEG_TEXT == 1);
  492.     know(SEG_DATA == 2);
  493.     know(SEG_BSS == 3);
  494.     know(SEG_UNKNOWN == 4);
  495.     know(SEG_NONE == 5);
  496.     know(SEG_PASS1 == 6);
  497.     know(SEG_GOOF == 7);
  498.     know(SEG_BIG == 8);
  499.     know(SEG_DIFFERENCE == 9);
  500.     know(SEG_MAXIMUM_ORDINAL == SEG_DIFFERENCE);
  501.     obstack_begin(&frags, 50000);
  502.     frchain_root = NULL;
  503.     frchain_now = NULL; /* Warn new_subseg() that we are booting. */
  504.     /* Fake up 1st frag. */
  505.     /* It won't be used=> is ok if obstack... */
  506.     /* pads the end of it for alignment. */
  507.     frag_now = (fragS *) obstack_alloc(&frags, SIZEOF_STRUCT_FRAG);
  508.     /* obstack_1blank( &frags, SIZEOF_STRUCT_FRAG, & frag_now ); */
  509.     /* This 1st frag will not be in any frchain. */
  510.     /* We simply give subseg_new somewhere to scribble. */
  511.     now_subseg = 42;    /* Lie for 1st call to subseg_new. */
  512.     subseg_new(SEG_DATA, 0);    /* .data 0 */
  513.     data0_frchainP = frchain_now;
  514.     IsSpecialSection = 0;
  515.     NumberOfSpecialSections = 0;
  516.     if (glevel > 1)
  517.         NumberOfDebugSections = 2;
  518.     else
  519.         NumberOfDebugSections = 0;
  520. }
  521. /* subseg_change()
  522.  * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
  523.  * subsegment. If we are already in the correct subsegment, change nothing.
  524.  * This is used eg as a worker for subseg_new [which does make a new frag_now]
  525.  * and for changing segments after we have read the source. We construct eg
  526.  * fixSs even after the source file is read, so we do have to keep the
  527.  * segment context correct.
  528.  */
  529. static void subseg_change(register segT seg, register int subseg)
  530. {
  531.     now_seg = seg;
  532.     now_subseg = subseg;
  533.     if (seg == SEG_DATA) {
  534.         seg_fix_rootP = &data_fix_root;
  535.     }
  536.     else {
  537.         know(seg == SEG_TEXT);
  538.         seg_fix_rootP = &text_fix_root;
  539.     }
  540. }
  541. /* subseg_new()
  542.  * If you attempt to change to the current subsegment, nothing happens.
  543.  * In:  segT, subsegT code for new subsegment.
  544.  *  frag_now -> incomplete frag for current subsegment.
  545.  *  If frag_now==NULL, then there is no old, incomplete frag, so
  546.  *  the old frag is not closed off.
  547.  * Out: now_subseg, now_seg updated.
  548.  *  Frchain_now points to the (possibly new) struct frchain for this
  549.  *  sub-segment.
  550.  *  Frchain_root updated if needed.
  551.  */
  552. static void subseg_new(register segT seg,register subsegT subseg) /* begin assembly for a new sub-segment */
  553. {
  554.     long tmp;           /* JF for obstack alignment hacking */
  555.     know(seg == SEG_DATA || seg == SEG_TEXT);
  556.     if (seg != now_seg || subseg != now_subseg) {   /* we just changed
  557.                         sub-segments */
  558.         register frchainS *frcP;    /* crawl frchain chain */
  559.         register frchainS **lastPP; /* address of last pointer */
  560.         frchainS *newP; /* address of new frchain */
  561.         register fragS *former_last_fragP;
  562.         register fragS *new_fragP;
  563.         if (frag_now) { /* If not bootstrapping. */
  564.             frag_now->fr_fix = obstack_next_free(&frags) - frag_now->fr_literal;
  565.             frag_wane(frag_now);    /* Close off any frag in old subseg. */
  566.         }
  567.         /* It would be nice to keep an obstack for each subsegment, if we
  568.         swap subsegments a lot. Hence we would have much fewer
  569.         frag_wanes(). */
  570.         obstack_finish(&frags);
  571.         /* If we don't do the above, the next object we put on obstack frags
  572.         will appear to start at the fr_literal of the current frag. Also,
  573.         above ensures that the next object will begin on a address that is
  574.         aligned correctly for the engine that runs this program. */
  575.         subseg_change(seg, (int) subseg);
  576.         /* Attempt to find or make a frchain for that sub seg. Crawl along
  577.         chain of frchainSs, begins @ frchain_root. If we need to make a
  578.         frchainS, link it into correct position of chain rooted in
  579.         frchain_root. */
  580.         lastPP = &frchain_root;
  581.         frcP = *(lastPP);
  582.         for (; frcP && (int) (frcP->frch_seg) <= (int) seg; frcP = *(lastPP = &frcP->frch_next)) {
  583.             if ((int) (frcP->frch_seg) == (int) seg && frcP->frch_subseg >= subseg) {
  584.                 break;
  585.             }
  586.         }
  587.         /* frcP:      Address of the 1st frchainS in correct segment with
  588.         frch_subseg >= subseg. We want to either use this frchainS, or we
  589.         want to insert a new frchainS just before it.
  590.  
  591.         If frcP==NULL, then we are at the end of the chain of frchainS-s. A
  592.         NULL frcP means we fell off the end of the chain looking for a
  593.         frch_subseg >= subseg, so we must make a new frchainS.
  594.  
  595.         If we ever maintain a pointer to the last frchainS in the chain, we
  596.         change that pointer ONLY when frcP==NULL.
  597.  
  598.         lastPP:    Address of the pointer with value frcP; Never NULL. May
  599.         point to frchain_root.
  600.  
  601.         */
  602.         if (!frcP
  603.                 || ((int) (frcP->frch_seg) > (int) seg
  604.                     || frcP->frch_subseg > subseg)) {   /* Kinky logic only
  605.                         works with 2 segments. */
  606.             /* This should be the only code that creates a frchainS. */
  607.             newP = (frchainS *) obstack_alloc(&frags, sizeof(frchainS));
  608.             /* obstack_1blank( &frags, sizeof(frchainS), &newP);This begines on a
  609.             good boundary because a obstack_done() preceeded  it.
  610.             It implies an obstack_done(), so we expect the next object allocated
  611.             to begin on a correct boundary. */
  612.             *lastPP = newP;
  613.             newP->frch_next = frcP; /* perhaps NULL */
  614.             (frcP = newP)->frch_subseg = subseg;
  615.             newP->frch_seg = seg;
  616.             newP->frch_last = NULL;
  617.         }
  618.         /* Here with frcP ->ing to the frchainS for subseg. */
  619.         frchain_now = frcP;
  620.         /* Make a fresh frag for the subsegment. We expect this to happen on a
  621.         correct boundary since it was proceeded by a obstack_done(). */
  622.         tmp = obstack_alignment_mask(&frags);
  623.         obstack_alignment_mask(&frags) = 0;
  624.         frag_now = (fragS *) obstack_alloc(&frags, SIZEOF_STRUCT_FRAG);
  625.         obstack_alignment_mask(&frags) = tmp;
  626.         /* But we want any more chars to come immediately after the structure we
  627.         just made. */
  628.         new_fragP = frag_now;
  629.         new_fragP->fr_next = NULL;
  630.         /* Append new frag to current frchain. */
  631.         former_last_fragP = frcP->frch_last;
  632.         if (former_last_fragP) {
  633.             know(former_last_fragP->fr_next == NULL);
  634.             know(frchain_now->frch_root);
  635.             former_last_fragP->fr_next = new_fragP;
  636.         }
  637.         else {
  638.             frcP->frch_root = new_fragP;
  639.         }
  640.         frcP->frch_last = new_fragP;
  641.     }                   /* if (changing subsegments) */
  642. }                       /* subseg_new() */
  643.  
  644. /* symbol_new()
  645.  * Return a pointer to a new symbol. Die if we can't make a new symbol.
  646.  * Fill in the symbol's values. Add symbol to end of symbol chain.
  647.  */
  648. static symbolS *symbol_new(
  649.     char *name,         /* We copy this: OK to alter your copy. */
  650.     unsigned char type, /* One of the types defined in the table seg_N_TYPE */
  651.     valueT value,       /* As in <a.out.h>, often an address. */
  652.                         /* Often used as offset from frag address. */
  653.     struct frag *frag)  /* For sy_frag. */
  654. {
  655.     register symbolS *symbolP;
  656.     register char *preserved_copy_of_name;
  657.     register unsigned int name_length;
  658.     char *p;
  659.     name_length = strlen(name) + 1;
  660.     obstack_grow(¬es, name, name_length);
  661.     p = obstack_finish(¬es);
  662.     preserved_copy_of_name = p;
  663.     p = obstack_alloc(¬es, sizeof(symbolS));
  664.     symbolP = (symbolS *) p;
  665.     symbolP->Name = preserved_copy_of_name;
  666.     symbolP->sy_type = type;
  667.     symbolP->SymbolValue = value;
  668.     symbolP->sy_frag = frag;
  669.     symbolP->Next = NULL;    /* End of chain. */
  670.     symbolP->sy_forward = NULL;
  671.     SetFlags(symbolP);
  672.     /* Link to end of symbol chain. */
  673.     if (symbol_lastP) {
  674.         symbol_lastP->Next = symbolP;
  675.     }
  676.     else {
  677.         symbol_rootP = symbolP;
  678.     }
  679.     symbol_lastP = symbolP;
  680.     return (symbolP);
  681. }
  682. /* colon()
  683.  * We have just seen "<name>:". Creates a struct symbol unless it already exists.
  684.  * Gripes if we are redefining a symbol incompatibly (and ignores it).
  685.  */
  686. static void colon(register char *sym_name)
  687. {                       /* just seen "x:" - rattle symbols & frags */
  688.     /* symbol name, as a cannonical string  We copy this string: OK to alter
  689.     later. */
  690.     register symbolS *symbolP;    /* symbol we are working with */
  691.  
  692.     if ((symbolP = symbol_table_lookup(sym_name)) != NULL) {
  693.         /* Now check for undefined symbols */
  694.         if ((symbolP->sy_type & N_TYPE) == N_UNDF) {
  695.             if (symbolP->SymbolValue == 0) {
  696.                 symbolP->sy_frag = frag_now;
  697.                 symbolP->SymbolValue = obstack_next_free(&frags) - frag_now->fr_literal;
  698.                 know(N_UNDF == 0);
  699.                 symbolP->sy_type |= seg_N_TYPE[(int) now_seg];  /* keep N_EXT bit */
  700.  
  701.                 if (symbolP->StorageClass == 0) {
  702.                     if (now_seg == SEG_TEXT)
  703.                         symbolP->StorageClass = 6;    /* Code label within a module */
  704.                     else
  705.                         symbolP->StorageClass = 3;
  706.  
  707.                 }
  708.                 SetFlags(symbolP);
  709.                 if (symbolP->Flags & IS_TEXT) {
  710.                     symbolP->SectionNumber = SECTION_TEXT;
  711.                 }
  712.                 else if (symbolP->Flags & IS_DATA) {
  713.                     symbolP->SectionNumber = SECTION_DATA;
  714.                 }
  715.             }
  716.             else {
  717.                 InternalError(1000);
  718.             }
  719.         }
  720.         else {
  721.             InternalError(1001);
  722.         }
  723.     }
  724.     else {
  725.         symbolP = symbol_new(sym_name,
  726.                             (unsigned char) (seg_N_TYPE[(int) now_seg]),
  727.                 (valueT) (obstack_next_free(&frags) - frag_now->fr_literal),
  728.                             frag_now);
  729.         symbol_table_insert(symbolP);
  730.         if (symbolP->StorageClass == 0) {
  731.             if (now_seg == SEG_TEXT)
  732.                 symbolP->StorageClass = 6;  /* Code label within a module */
  733.             else
  734.                 symbolP->StorageClass = 3;
  735.         }
  736.         SetFlags(symbolP);
  737.         if (symbolP->Flags & IS_TEXT) {
  738.             symbolP->SectionNumber = SECTION_TEXT;
  739.         }
  740.         else if (symbolP->Flags & IS_DATA) {
  741.             symbolP->SectionNumber = SECTION_DATA;
  742.         }
  743.     }
  744. }
  745.  
  746. static void SetFlags(symbolS *coffS)
  747. {
  748.     if (now_seg == SEG_TEXT) {
  749.         coffS->Flags |= IS_TEXT;
  750.         coffS->Flags &= ~(IS_DATA | IS_BSS);
  751.     }
  752.     else if (now_seg == SEG_DATA) {
  753.         coffS->Flags |= IS_DATA;
  754.         coffS->Flags &= ~(IS_TEXT | IS_BSS);
  755.     }
  756. }
  757.  
  758. /*
  759.  *          symbol_find_or_make()
  760.  * If a symbol name does not exist, create it as undefined, and insert
  761.  * it into the symbol table. Return a pointer to it.
  762.  */
  763. static symbolS *symbol_find_or_make(char *name)
  764. {
  765.     register symbolS *symbolP;
  766.     symbolP = symbol_table_lookup(name);
  767.     if (symbolP == NULL) {
  768.         symbolP = symbol_new(name, N_UNDF,  0, &zero_address_frag);
  769.         symbol_table_insert(symbolP);
  770.     }
  771.     return (symbolP);
  772. }
  773.  
  774. /*
  775.  *          frag_grow()
  776.  *
  777.  * Internal.
  778.  * Try to augment current frag by nchars chars.
  779.  * If there is no room, close of the current frag with a ".fill 0"
  780.  * and begin a new frag. Unless the new frag has nchars chars available
  781.  * do not return. Do not set up any fields of *now_frag.
  782.  */
  783. static void frag_grow(unsigned int nchars)
  784. {
  785.     if (obstack_room(&frags) < nchars) {
  786.         unsigned int n, oldn;
  787.         long oldc;
  788.         frag_wane(frag_now);
  789.         frag_new(0);
  790.         oldn = (unsigned) -1;
  791.         oldc = frags.chunk_size;
  792.         frags.chunk_size = 2 * nchars;
  793.         while ((n = obstack_room(&frags)) < nchars && n < oldn) {
  794.             frag_wane(frag_now);
  795.             frag_new(0);
  796.             oldn = n;
  797.         }
  798.         frags.chunk_size = oldc;
  799.     }
  800.     else return;
  801.     if (obstack_room(&frags) < nchars) {
  802.         InternalError(1003);
  803.     }
  804. }
  805. /* frag_new()
  806.  * Call this to close off a completed frag, and start up a new (empty)
  807.  * frag, in the same subsegment as the old frag.
  808.  * [frchain_now remains the same but frag_now is updated.]
  809.  * Because this calculates the correct value of fr_fix by
  810.  * looking at the obstack 'frags', it needs to know how many
  811.  * characters at the end of the old frag belong to (the maximal)
  812.  * fr_var: the rest must belong to fr_fix.
  813.  * It doesn't actually set up the old frag's fr_var: you may have
  814.  * set fr_var == 1, but allocated 10 chars to the end of the frag:
  815.  * in this case you pass old_frags_var_max_size == 10.
  816.  * Make a new frag, initialising some components. Link new frag at end
  817.  * of frchain_now.
  818.  * input: old_frags_var_max_size Number of chars
  819.  * (already allocated on obstack frags) in variable_length part of frag.
  820.  */
  821. static void frag_new(int old_frags_var_max_size)
  822. {
  823.     register fragS *former_last_fragP;
  824.     register frchainS *frchP;
  825.     long tmp;
  826.     frag_now->fr_fix = (char *) (obstack_next_free(&frags)) -
  827.         (frag_now->fr_literal) - old_frags_var_max_size;
  828.     /* Fix up old frag's fr_fix. */
  829.     obstack_finish(&frags);
  830.     /* This will align the obstack so the */
  831.     /* next struct we allocate on it will */
  832.     /* begin at a correct boundary. */
  833.     frchP = frchain_now;
  834.     know(frchP);
  835.     former_last_fragP = frchP->frch_last;
  836.     know(former_last_fragP);
  837.     know(former_last_fragP == frag_now);
  838.     obstack_blank(&frags, SIZEOF_STRUCT_FRAG);
  839.     /* We expect this will begin at a correct */
  840.     /* boundary for a struct. */
  841.     tmp = obstack_alignment_mask(&frags);
  842.     obstack_alignment_mask(&frags) = 0; /* Turn off alignment */
  843.     frag_now = (fragS *) obstack_finish(&frags);
  844.     obstack_alignment_mask(&frags) = tmp;   /* Restore alignment */
  845.     /* Just in case we don't get zero'd bytes */
  846. //    memset(frag_now,0, SIZEOF_STRUCT_FRAG);
  847.     /* Generally, frag_now->points to an address rounded up to next
  848.     alignment. */
  849.     /* However, characters will add to obstack frags IMMEDIATELY after the
  850.     struct frag, */
  851.     /* even if they are not starting at an alignment address. */
  852.     former_last_fragP->fr_next = frag_now;
  853.     frchP->frch_last = frag_now;
  854.     frag_now->fr_next = NULL;
  855. }                       /* frag_new() */
  856. /* frag_more()
  857.  * Start a new frag unless we have n more chars of room in the current frag.
  858.  * Close off the old frag with a .fill 0.
  859.  * Return the address of the 1st char to write into. Advance
  860.  * frag_now_growth past the new chars.
  861.  */
  862. static char *frag_more(int nchars)
  863. {
  864.     register char *retval;
  865.     frag_grow(nchars);
  866.     retval = obstack_next_free(&frags);
  867.     obstack_blank_fast(&frags, nchars);
  868.     return (retval);
  869. }                       /* frag_more() */
  870. /*
  871.  *          frag_var()
  872.  * Start a new frag unless we have max_chars more chars of room in the current frag.
  873.  * Close off the old frag with a .fill 0.
  874.  *
  875.  * Set up a machine_dependent relaxable frag, then start a new frag.
  876.  * Return the address of the 1st char of the var part of the old frag
  877.  * to write into.
  878.  */
  879. static char *frag_var(
  880.     relax_stateT type,
  881.     int max_chars,
  882.     int var,
  883.     relax_substateT subtype,
  884.     symbolS *symbol,
  885.     long int offset,
  886.     char *opcode)
  887. {
  888.     register char *retval;
  889.     frag_grow(max_chars);
  890.     retval = obstack_next_free(&frags);
  891.     obstack_blank_fast(&frags, max_chars);
  892.     frag_now->fr_var = var;
  893.     frag_now->fr_type = type;
  894.     frag_now->fr_subtype = subtype;
  895.     frag_now->fr_symbol = symbol;
  896.     frag_now->fr_offset = offset;
  897.     frag_now->fr_opcode = opcode;
  898.     frag_new(max_chars);
  899.     return (retval);
  900. }                       /* frag_var() */
  901. /*
  902.  *  frag_wane() Reduce the variable end of a frag to a harmless state.
  903.  */
  904. static void frag_wane(fragS * fragP)
  905. {
  906.     fragP->fr_type = rs_fill;
  907.     fragP->fr_offset = 0;
  908.     fragP->fr_var = 0;
  909. }
  910. /*
  911.  *          frag_align()
  912.  * Make a frag for ".align foo,bar". Call is "frag_align (foo,bar);".
  913.  * Foo & bar are absolute integers.
  914.  * Call to close off the current frag with a ".align", then start a new
  915.  * (so far empty) frag, in the same subsegment as the last frag.
  916.  */
  917. static void frag_align(int alignment, int fill_character)
  918. {
  919.     *(frag_var(rs_align, 1, 1, (relax_substateT) 0, (symbolS *) 0,
  920.             (long) alignment, (char *) 0)) = fill_character;
  921. }
  922.  
  923.  
  924. /*
  925.  * Summary of operand().
  926.  * in:  InputPointer points to 1st char of operand, which may
  927.  *  be a space.
  928.  * out: A expressionS. X_seg determines how to understand the rest of the
  929.  *  expressionS.
  930.  *  The operand may have been empty: in this case X_seg == SEG_NONE.
  931.  *  InputPointer -> (next non-blank) char after operand.
  932.  */
  933. static segT operand(register expressionS *expressionP)
  934. {
  935.     register char c;
  936.     register char *name;/* points to name of symbol */
  937.     register symbolS *symbolP;    /* Points to symbol */
  938.     SKIP_WHITESPACE();  /* Leading whitespace is part of operand. */
  939.     c = *InputPointer++;  /* InputPointer -> past char in c. */
  940.     if (isdigit(c)) {
  941.         register valueT number; /* offset or (absolute) value */
  942.         register short int digit;   /* value of next digit in current radix */
  943.         /* invented for humans only, hope */
  944.         /* optimising compiler flushes it! */
  945.         register short int radix;   /* 8, 10 or 16 */
  946.         /* 0 means we saw start of a floating- */
  947.         /* point constant. */
  948.         register short int maxdig;  /* Highest permitted digit value. */
  949.         register int too_many_digits;   /* If we see >= this number of */
  950.         /* digits, assume it is a bignum. */
  951.         register char *digit_2; /* -> 2nd digit of number. */
  952.         int small;      /* TRUE if fits in 32 bits. */
  953.         if (c == '0') { /* non-decimal radix */
  954.             if ((c = *InputPointer++) == 'x' || c == 'X') {
  955.                 c = *InputPointer++;  /* read past "0x" or "0X" */
  956.                 maxdig = radix = 16;
  957.                 too_many_digits = 9;
  958.             }
  959.             else {
  960.                 /* If it says '0f' and the line ends or it DOESN'T look like
  961.                 a floating point #, its a local label ref.  DTRT */
  962.                 if (c == 'f' && (!*InputPointer ||
  963.                             (!index("+-.0123456789", *InputPointer)))) {
  964.                     maxdig = radix = 10;
  965.                     too_many_digits = 11;
  966.                     c = '0';
  967.                     InputPointer -= 2;
  968.                 }
  969.                 else {  /* By elimination, assume octal radix. */
  970.                     radix = 8;
  971.                     maxdig = 10;    /* Un*x sux. Compatibility. */
  972.                     too_many_digits = 11;
  973.                 }
  974.             }
  975.             /* c == char after "0" or "0x" or "0X" or "0e" etc. */
  976.         }
  977.         else {
  978.             maxdig = radix = 10;
  979.             too_many_digits = 11;
  980.         }
  981. /*
  982.  * Most numbers fit into 32 bits, and we want this case to be fast.So we pretend it
  983.    will fit into 32 bits. If, after making up a 32 bit number, we realise that we
  984.    have scanned more digits than comfortably fit into 32 bits, we re-scan the digits
  985.    coding them into a bignum. For decimal and octal numbers we are conservative:
  986.    some numbers may be assumed bignums when in fact they do fit into 32 bits.Numbers
  987.    of any radix can have excess leading zeros: we strive to recognise this and cast
  988.    them back into 32 bits. The number we are looking for is expected to be positive,
  989.    but if it fits into 32 bits as an unsigned number, we let it be a 32-bit
  990.    number. The cavalier approach is for speed in ordinary cases.
  991.  */
  992.         digit_2 = InputPointer;
  993.         for (number = 0; (digit = hex_value[c]) < maxdig; c = *InputPointer++) {
  994.             number = number * radix + digit;
  995.         }
  996.         /* C contains character after number. */
  997.         /* InputPointer -> char after C. */
  998.         small = InputPointer - digit_2 < too_many_digits;
  999.         if (!small) {
  1000.             InternalError(1004);
  1001.         }
  1002.         /* Here with number, in correct radix. c is the next char. Note
  1003.         that unlike Un*x, we allow "011f" "0x9f" to both mean the same
  1004.         as the (conventional) "9f". This is simply easier than checking
  1005.         for strict canonical form. Syntax sux! */
  1006.         expressionP->X_add_number = number;
  1007.         expressionP->X_seg = SEG_ABSOLUTE;
  1008.         expressionP->X_subtract_symbol = NULL;
  1009.         expressionP->X_add_symbol = NULL;
  1010.         InputPointer--;   /* Restore following character. */
  1011.         SKIP_WHITESPACE();  /* -> 1st char after operand. */
  1012.         know(*InputPointer != ' ');
  1013.         return (expressionP->X_seg);
  1014.     }
  1015.     else if (c == '.' && !is_part_of_name(*InputPointer)) {
  1016.         extern struct obstack frags;
  1017.         /* '.' is pseudo symbol with value of current location in
  1018.         current segment. . . */
  1019.         symbolP = symbol_new("L0\001",
  1020.                             (unsigned char) (seg_N_TYPE[(int) now_seg]),
  1021.                 (valueT) (obstack_next_free(&frags) - frag_now->fr_literal),
  1022.                             frag_now);
  1023.         expressionP->X_add_number = 0;
  1024.         expressionP->X_add_symbol = symbolP;
  1025.         expressionP->X_seg = now_seg;
  1026.     }
  1027.     else if (is_name_beginner(c)) { /* here if did not begin with a digit */
  1028.         /* Identifier begins here. This is kludged for speed, so code is
  1029.         repeated. */
  1030.         name = --InputPointer;
  1031.         c = get_symbol_end();
  1032.         symbolP = symbol_table_lookup(name);
  1033.         if (symbolP) {
  1034.             /* If we have an absolute symbol, then we know it's value now. */
  1035.             register segT seg;
  1036.             seg = N_TYPE_seg[(int) symbolP->sy_type & N_TYPE];
  1037.             if ((expressionP->X_seg = seg) == SEG_ABSOLUTE) {
  1038.                 expressionP->X_add_number = symbolP->SymbolValue;
  1039.             }
  1040.             else {
  1041.                 expressionP->X_add_number = 0;
  1042.                 expressionP->X_add_symbol = symbolP;
  1043.             }
  1044.         }
  1045.         else {
  1046.             expressionP->X_add_symbol
  1047.                 = symbolP
  1048.                 = symbol_new(name, N_UNDF,  0, &zero_address_frag);
  1049.             expressionP->X_add_number = 0;
  1050.             expressionP->X_seg = SEG_UNKNOWN;
  1051.             symbol_table_insert(symbolP);
  1052.         }
  1053.         *InputPointer = c;
  1054.         expressionP->X_subtract_symbol = NULL;
  1055.     }
  1056.     else if (c == '(') {/* didn't begin with digit & not a name */
  1057.         (void) expression(expressionP);
  1058.         /* Expression() will pass trailing whitespace */
  1059.         if (*InputPointer++ != ')') {
  1060.             InternalError(3061);
  1061.             InputPointer--;
  1062.         }
  1063.         /* here with InputPointer -> char after "(...)" */
  1064.     }
  1065.     else if (c == '~' || c == '-') {    /* unary operator: hope for
  1066.                         SEG_ABSOLUTE */
  1067.         switch (operand(expressionP)) {
  1068.         case SEG_ABSOLUTE:
  1069.             /* InputPointer -> char after operand */
  1070.             if (c == '-') {
  1071.                 expressionP->X_add_number = -expressionP->X_add_number;
  1072. /*
  1073.  * Notice: '-' may  overflow: no warning is given. This is compatible
  1074.  * with other people's assemblers. Sigh.
  1075.  */
  1076.             }
  1077.             else {
  1078.                 expressionP->X_add_number = ~expressionP->X_add_number;
  1079.             }
  1080.             break;
  1081.         case SEG_TEXT:
  1082.         case SEG_DATA:
  1083.         case SEG_BSS:
  1084.         case SEG_PASS1:
  1085.         case SEG_UNKNOWN:
  1086.             if (c == '-') {
  1087.                 expressionP->X_subtract_symbol = expressionP->X_add_symbol;
  1088.                 expressionP->X_add_symbol = 0;
  1089.                 expressionP->X_seg = SEG_DIFFERENCE;
  1090.                 break;
  1091.             }
  1092.         default:       /* unary on non-absolute is unsuported */
  1093.             InternalError(3062);
  1094.             break;
  1095.             /* Expression undisturbed from operand(). */
  1096.         }
  1097.     }
  1098.     else {
  1099.         /* can't imagine any other kind of operand */
  1100.         expressionP->X_seg = SEG_NONE;
  1101.         InputPointer--;
  1102.     }
  1103. /*
  1104.  * It is more 'efficient' to clean up the expressions when they are created.
  1105.  * Doing it here saves lines of code.
  1106.  */
  1107.  
  1108.     clean_up_expression(expressionP);
  1109.     SKIP_WHITESPACE();  /* -> 1st char after operand. */
  1110.     know(*InputPointer != ' ');
  1111.     return (expressionP->X_seg);
  1112. }                       /* operand */
  1113. /* Internal. Simplify a struct expression for use by AsmExpression()
  1114.  * In:  address of a expressionS.
  1115.  *  The X_seg field of the expressionS may only take certain values.
  1116.  *  Now, we permit SEG_PASS1 to make code smaller & faster.
  1117.  *  Elsewise we waste time special-case testing. Sigh. Ditto SEG_NONE.
  1118.  * Out: expressionS may have been modified:
  1119.  *  'foo-foo' symbol references cancelled to 0,
  1120.  *      which changes X_seg from SEG_DIFFERENCE to SEG_ABSOLUTE;
  1121.  *  Unused fields zeroed to help AsmExpression().
  1122.  */
  1123. static void clean_up_expression(register expressionS *expressionP)
  1124. {
  1125.     switch (expressionP->X_seg) {
  1126.     case SEG_NONE:
  1127.     case SEG_PASS1:
  1128.         expressionP->X_add_symbol = NULL;
  1129.         expressionP->X_subtract_symbol = NULL;
  1130.         expressionP->X_add_number = 0;
  1131.         break;
  1132.     case SEG_BIG:
  1133.     case SEG_ABSOLUTE:
  1134.         expressionP->X_subtract_symbol = NULL;
  1135.         expressionP->X_add_symbol = NULL;
  1136.         break;
  1137.     case SEG_TEXT:
  1138.     case SEG_DATA:
  1139.     case SEG_BSS:
  1140.     case SEG_UNKNOWN:
  1141.         expressionP->X_subtract_symbol = NULL;
  1142.         break;
  1143.     case SEG_DIFFERENCE:
  1144.         /* It does not hurt to 'cancel' NULL==NULL when comparing symbols for
  1145.         'eq'ness. It is faster to re-cancel them to NULL than to check for
  1146.         this special case. */
  1147.         if (expressionP->X_subtract_symbol == expressionP->X_add_symbol
  1148.                 || (expressionP->X_subtract_symbol
  1149.                     && expressionP->X_add_symbol
  1150.                     && expressionP->X_subtract_symbol->sy_frag == expressionP->X_add_symbol->sy_frag
  1151.                     && expressionP->X_subtract_symbol->SymbolValue == expressionP->X_add_symbol->SymbolValue)) {
  1152.             expressionP->X_subtract_symbol = NULL;
  1153.             expressionP->X_add_symbol = NULL;
  1154.             expressionP->X_seg = SEG_ABSOLUTE;
  1155.         }
  1156.         break;
  1157.     default:
  1158.         InternalError(1103);
  1159.         break;
  1160.     }
  1161. }
  1162. /*
  1163.  *          expr_part ()
  1164.  * Internal. Made a function because this code is used in 2 places.
  1165.  * Generate error or correct X_?????_symbol of expressionS.
  1166.  * symbol_1 += symbol_2 ... well ... sort of.
  1167.  */
  1168. static segT expr_part(symbolS **symbol_1_PP,symbolS * symbol_2_P)
  1169. {
  1170.     segT return_value;
  1171.     know((*symbol_1_PP) == NULL
  1172.         || ((*symbol_1_PP)->sy_type & N_TYPE) == N_TEXT
  1173.         || ((*symbol_1_PP)->sy_type & N_TYPE) == N_DATA
  1174.         || ((*symbol_1_PP)->sy_type & N_TYPE) == N_BSS
  1175.         || ((*symbol_1_PP)->sy_type & N_TYPE) == N_UNDF
  1176.         );
  1177.     know(symbol_2_P == NULL
  1178.         || (symbol_2_P->sy_type & N_TYPE) == N_TEXT
  1179.         || (symbol_2_P->sy_type & N_TYPE) == N_DATA
  1180.         || (symbol_2_P->sy_type & N_TYPE) == N_BSS
  1181.         || (symbol_2_P->sy_type & N_TYPE) == N_UNDF
  1182.         );
  1183.     if (*symbol_1_PP) {
  1184.         if (((*symbol_1_PP)->sy_type & N_TYPE) == N_UNDF) {
  1185.             if (symbol_2_P) {
  1186.                 return_value = SEG_PASS1;
  1187.                 *symbol_1_PP = NULL;
  1188.             }
  1189.             else {
  1190.                 know(((*symbol_1_PP)->sy_type & N_TYPE) == N_UNDF);
  1191.                 return_value = SEG_UNKNOWN;
  1192.             }
  1193.         }
  1194.         else {
  1195.             if (symbol_2_P) {
  1196.                 if ((symbol_2_P->sy_type & N_TYPE) == N_UNDF) {
  1197.                     *symbol_1_PP = NULL;
  1198.                     return_value = SEG_PASS1;
  1199.                 }
  1200.                 else {
  1201.                     /* {seg1} - {seg2} */
  1202.                     InternalError(1063);
  1203.                 }
  1204.             }
  1205.             else {
  1206.                 return_value = N_TYPE_seg[(*symbol_1_PP)->sy_type & N_TYPE];
  1207.             }
  1208.         }
  1209.     }
  1210.     else {              /* (* symbol_1_PP) == NULL */
  1211.         if (symbol_2_P) {
  1212.             *symbol_1_PP = symbol_2_P;
  1213.             return_value = N_TYPE_seg[(symbol_2_P)->sy_type & N_TYPE];
  1214.         }
  1215.         else {
  1216.             *symbol_1_PP = NULL;
  1217.             return_value = SEG_ABSOLUTE;
  1218.         }
  1219.     }
  1220.     know(return_value == SEG_ABSOLUTE
  1221.         || return_value == SEG_TEXT
  1222.         || return_value == SEG_DATA
  1223.         || return_value == SEG_BSS
  1224.         || return_value == SEG_UNKNOWN
  1225.         || return_value == SEG_PASS1
  1226.         );
  1227.     know((*symbol_1_PP) == NULL
  1228.     || ((*symbol_1_PP)->sy_type & N_TYPE) == seg_N_TYPE[(int) return_value]);
  1229.     return (return_value);
  1230. }                       /* expr_part() */
  1231. /* Expression parser. */
  1232. /*
  1233.  * We allow an empty expression, and just assume (absolute,0) silently.
  1234.  * Unary operators and parenthetical expressions are treated as operands.
  1235.  * As usual, Q==quantity==operand, O==operator, X==expression mnemonics.
  1236.  * We used to do a aho/ullman shift-reduce parser, but the logic got so
  1237.  * warped that I flushed it and wrote a recursive-descent parser instead.
  1238.  * Now things are stable, would anybody like to write a fast parser?
  1239.  * Most expressions are either register (which does not even reach here)
  1240.  * or 1 symbol. Then "symbol+constant" and "symbol-symbol" are common.
  1241.  * So I guess it doesn't really matter how inefficient more complex expressions
  1242.  * are parsed.
  1243.  * After AsmExpression(RANK,resultP) InputPointer -> operator of rank <= RANK.
  1244.  * Also, we have consumed any leading or trailing spaces (operand does that)
  1245.  * and done all intervening operators.
  1246.  */
  1247. typedef enum {
  1248.     O_illegal,          /* (0)  what we get for illegal op */
  1249.     O_multiply,         /* (1)  * */
  1250.     O_divide,           /* (2)  / */
  1251.     O_modulus,          /* (3)  % */
  1252.     O_left_shift,       /* (4)  < */
  1253.     O_right_shift,      /* (5)  > */
  1254.     O_bit_inclusive_or, /* (6)  | */
  1255.     O_bit_or_not,       /* (7)  ! */
  1256.     O_bit_exclusive_or, /* (8)  ^ */
  1257.     O_bit_and,          /* (9)  & */
  1258.     O_add,              /* (10) + */
  1259.     O_subtract          /* (11) - */
  1260. }
  1261. operatorT;
  1262. #undef __
  1263. #define __ O_illegal
  1264. static const operatorT op_encoding[256] = { /* maps ASCII -> operators */
  1265.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  1266.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  1267.     __, O_bit_or_not, __, __, __, O_modulus, O_bit_and, __,
  1268.     __, __, O_multiply, O_add, __, O_subtract, __, O_divide,
  1269.     __, __, __, __, __, __, __, __,
  1270.     __, __, __, __, O_left_shift, __, O_right_shift, __,
  1271.     __, __, __, __, __, __, __, __,
  1272.     __, __, __, __, __, __, __, __,
  1273.     __, __, __, __, __, __, __, __,
  1274.     __, __, __, __, __, __, O_bit_exclusive_or, __,
  1275.     __, __, __, __, __, __, __, __,
  1276.     __, __, __, __, __, __, __, __,
  1277.     __, __, __, __, __, __, __, __,
  1278.     __, __, __, __, O_bit_inclusive_or, __, __, __,
  1279.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  1280.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  1281.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  1282.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  1283.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  1284.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  1285.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  1286.     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __
  1287. };
  1288. /*
  1289.  *  Rank    Examples
  1290.  *  0   operand, (expression)
  1291.  *  1   + -
  1292.  *  2   & ^ ! |
  1293.  *  3   * / % < >
  1294.  */
  1295. static const operator_rankT
  1296. op_rank[] = {0, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1};
  1297. static segT             /* Return resultP -> X_seg. */
  1298. AsmExpression(register operator_rankT rank,   /* Larger # is higher rank. */
  1299.     register expressionS *resultP)  /* Deliver result here. */
  1300. {
  1301.     expressionS right;
  1302.     register operatorT op_left;
  1303.     register char c_left;   /* 1st operator character. */
  1304.     register operatorT op_right;
  1305.     register char c_right;
  1306.     know(rank >= 0);
  1307.     (void) operand(resultP);
  1308.     know(*InputPointer != ' ');   /* Operand() gobbles spaces. */
  1309.     c_left = *InputPointer;   /* Potential operator character. */
  1310.     op_left = op_encoding[c_left];
  1311.     while (op_left != O_illegal && op_rank[(int) op_left] > rank) {
  1312.         InputPointer++;   /* -> after 1st character of operator. */
  1313.         /* Operators "<<" and ">>" have 2 characters. */
  1314.         if (*InputPointer == c_left && (c_left == '<' || c_left == '>')) {
  1315.             InputPointer++;
  1316.         }               /* -> after operator. */
  1317.         if (SEG_NONE == AsmExpression(op_rank[(int) op_left], &right)) {
  1318.             InternalError(1066);
  1319.         }
  1320.         know(*InputPointer != ' ');
  1321.         c_right = *InputPointer;
  1322.         op_right = op_encoding[c_right];
  1323.         if (*InputPointer == c_right && (c_right == '<' || c_right == '>')) {
  1324.             InputPointer++;
  1325.         }               /* -> after operator. */
  1326.         know((int) op_right == 0
  1327.             || op_rank[(int) op_right] <= op_rank[(int) op_left]);
  1328.         /* InputPointer -> after right-hand quantity. */
  1329.         /* left-hand quantity in resultP */
  1330.         /* right-hand quantity in right. */
  1331.         /* operator in op_left. */
  1332.         if (resultP->X_seg == SEG_PASS1 || right.X_seg == SEG_PASS1) {
  1333.             resultP->X_seg = SEG_PASS1;
  1334.         }
  1335.         else {
  1336.             if (op_left == O_subtract) {
  1337.                 /* Convert - into + by exchanging symbols and negating
  1338.                 number. I know -infinity can't be negated in 2's
  1339.                 complement: but then it can't be subtracted either. This
  1340.                 trick does not cause any further inaccuracy. */
  1341.                 register symbolS *symbolP;
  1342.                 right.X_add_number = -right.X_add_number;
  1343.                 symbolP = right.X_add_symbol;
  1344.                 right.X_add_symbol = right.X_subtract_symbol;
  1345.                 right.X_subtract_symbol = symbolP;
  1346.                 if (symbolP) {
  1347.                     right.X_seg = SEG_DIFFERENCE;
  1348.                 }
  1349.                 op_left = O_add;
  1350.             }
  1351.             if (op_left == O_add) {
  1352.                 segT seg1;
  1353.                 segT seg2;
  1354.                 know(resultP->X_seg == SEG_DATA
  1355.                     || resultP->X_seg == SEG_TEXT
  1356.                     || resultP->X_seg == SEG_BSS
  1357.                     || resultP->X_seg == SEG_UNKNOWN
  1358.                     || resultP->X_seg == SEG_DIFFERENCE
  1359.                     || resultP->X_seg == SEG_ABSOLUTE
  1360.                     || resultP->X_seg == SEG_PASS1
  1361.                     );
  1362.                 know(right.X_seg == SEG_DATA
  1363.                     || right.X_seg == SEG_TEXT
  1364.                     || right.X_seg == SEG_BSS
  1365.                     || right.X_seg == SEG_UNKNOWN
  1366.                     || right.X_seg == SEG_DIFFERENCE
  1367.                     || right.X_seg == SEG_ABSOLUTE
  1368.                     || right.X_seg == SEG_PASS1
  1369.                     );
  1370.                 clean_up_expression(&right);
  1371.                 clean_up_expression(resultP);
  1372.                 seg1 = expr_part(&resultP->X_add_symbol, right.X_add_symbol);
  1373.                 seg2 = expr_part(&resultP->X_subtract_symbol, right.X_subtract_symbol);
  1374.                 if (seg1 == SEG_PASS1 || seg2 == SEG_PASS1) {
  1375.                     need_pass_2 = TRUE;
  1376.                     resultP->X_seg = SEG_PASS1;
  1377.                 }
  1378.                 else if (seg2 == SEG_ABSOLUTE)
  1379.                     resultP->X_seg = seg1;
  1380.                 else if (seg1 != SEG_UNKNOWN
  1381.                         && seg1 != SEG_ABSOLUTE
  1382.                         && seg2 != SEG_UNKNOWN
  1383.                         && seg1 != seg2) {
  1384.                     know(seg2 != SEG_ABSOLUTE);
  1385.                     know(resultP->X_subtract_symbol);
  1386.                     know(seg1 == SEG_TEXT || seg1 == SEG_DATA || seg1 == SEG_BSS);
  1387.                     know(seg2 == SEG_TEXT || seg2 == SEG_DATA || seg2 == SEG_BSS);
  1388.                     know(resultP->X_add_symbol);
  1389.                     know(resultP->X_subtract_symbol);
  1390.                     InternalError(1067);
  1391.                 }
  1392.                 else
  1393.                     resultP->X_seg = SEG_DIFFERENCE;
  1394.                 resultP->X_add_number += right.X_add_number;
  1395.                 clean_up_expression(resultP);
  1396.             }
  1397.             else {      /* Not +. */
  1398.                 if (resultP->X_seg == SEG_UNKNOWN || right.X_seg == SEG_UNKNOWN) {
  1399.                     resultP->X_seg = SEG_PASS1;
  1400.                     need_pass_2 = TRUE;
  1401.                 }
  1402.                 else {
  1403.                     resultP->X_subtract_symbol = NULL;
  1404.                     resultP->X_add_symbol = NULL;
  1405.                     /* Will be SEG_ABSOLUTE. */
  1406.                     if (resultP->X_seg != SEG_ABSOLUTE || right.X_seg != SEG_ABSOLUTE) {
  1407.                         InternalError(1068);
  1408.                     }
  1409.                     else {
  1410.                         switch (op_left) {
  1411.                         case O_bit_inclusive_or:
  1412.                             resultP->X_add_number |= right.X_add_number;
  1413.                             break;
  1414.                         case O_modulus:
  1415.                             if (right.X_add_number) {
  1416.                                 resultP->X_add_number %= right.X_add_number;
  1417.                             }
  1418.                             else {
  1419.                                 InternalError(1069);
  1420.                             }
  1421.                             break;
  1422.                         case O_bit_and:
  1423.                             resultP->X_add_number &= right.X_add_number;
  1424.                             break;
  1425.                         case O_multiply:
  1426.                             resultP->X_add_number *= right.X_add_number;
  1427.                             break;
  1428.                         case O_divide:
  1429.                             if (right.X_add_number) {
  1430.                                 resultP->X_add_number /= right.X_add_number;
  1431.                             }
  1432.                             else {
  1433.                                 InternalError(1069); /* division par zero */
  1434.                             }
  1435.                             break;
  1436.                         case O_left_shift:
  1437.                             resultP->X_add_number <<= right.X_add_number;
  1438.                             break;
  1439.                         case O_right_shift:
  1440.                             resultP->X_add_number >>= right.X_add_number;
  1441.                             break;
  1442.                         case O_bit_exclusive_or:
  1443.                             resultP->X_add_number ^= right.X_add_number;
  1444.                             break;
  1445.                         case O_bit_or_not:
  1446.                             resultP->X_add_number |= ~right.X_add_number;
  1447.                             break;
  1448.                         default:
  1449.                             InternalError(1104);
  1450.                             break;
  1451.                         }   /* switch(operator) */
  1452.                     }
  1453.                 }       /* If we have to force need_pass_2. */
  1454.             }           /* If operator was +. */
  1455.         }               /* If we didn't set need_pass_2. */
  1456.         op_left = op_right;
  1457.     }                   /* While next operator is >= this rank. */
  1458.     return (resultP->X_seg);
  1459. }
  1460. /* get_symbol_end()
  1461.  * Assume InputPointer is at start of symbol name.
  1462.  * Advance InputPointer past symbol name.
  1463.  * Turn that character into a '\0', returning its former value.
  1464.  * This allows a string compare of the symbol name.
  1465.  * There will always be a char following symbol name, because all good
  1466.  * lines end in end-of-line.
  1467.  */
  1468. static char get_symbol_end()
  1469. {
  1470.     register char c;
  1471.     while (is_part_of_name(c = *InputPointer++));
  1472.     *--InputPointer = 0;
  1473.     return (c);
  1474. }
  1475. char *file_name;
  1476. /*
  1477.  * We expect the following sanitation has already been done.
  1478.  * No comments, reduce a comment to a space.
  1479.  * Reduce a tab to a space unless it is 1st char of line.
  1480.  * All multiple tabs and spaces collapsed into 1 char. Tab only
  1481.  * legal if 1st char of line.
  1482.  * # line file statements converted to .line x;.file y; statements.
  1483.  * Escaped newlines at end of line: remove them but add as many newlines
  1484.  * to end of statement as you removed in the middle, to synch line numbers.
  1485.  */
  1486. #define BEFORE_STRING ("\n")
  1487. #define AFTER_STRING ("\0") /* bcopy of 0 chars might choke. */
  1488. #define BEFORE_SIZE (1)
  1489. #define AFTER_SIZE  (1)
  1490. static char *buffer_start;  /* -> 1st char of full buffer area. */
  1491. static char *partial_where; /* -> after last full line in buffer. */
  1492. static int partial_size;/* >=0. Number of chars in partial line in buffer. */
  1493. /* Because we need AFTER_STRING just after last full line, it clobbers 1st part of
  1494.    partial line. So we preserve 1st part of partial line here. */
  1495. static char save_source[AFTER_SIZE];
  1496. /* What is the largest size buffer that input_file_give_next_buffer()
  1497. could return to us? */
  1498. static int buffer_length;
  1499. /*
  1500. We must track the physical file and line number for error messages.
  1501. We also track a "logical" file and line number corresponding to lcc
  1502. source line numbers.
  1503. */
  1504.  
  1505. static int physical_input_line, logical_input_line;
  1506. static void InitAsmInput(void)
  1507. {
  1508.     buffer_length = BUFFER_SIZE;
  1509.     buffer_start = xmalloc((long) (BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE));
  1510.     bcopy(BEFORE_STRING, buffer_start, (int) BEFORE_SIZE);
  1511.     /* Line number things. */
  1512.     logical_input_line = 0;
  1513. }
  1514. /* Return start of caller's part of buffer. */
  1515. static char *SetObjFileName(char *filename)
  1516. {
  1517.     char *p;
  1518.     file_name = filename;
  1519.     physical_input_line = 0;
  1520.     partial_size = 0;
  1521.     OutputFileName = xmalloc(256);
  1522.     p = strrchr(filename,'\\');
  1523.     if (p == NULL) p = filename;
  1524.     else p++;
  1525.     strcpy(OutputFileName,p);
  1526.     p = strrchr(OutputFileName,'.');
  1527.     if (p) *p = 0;
  1528.     else p = OutputFileName + strlen(filename);
  1529.     strcat(p,".obj");
  1530.     if (!strcmp(OutputFileName,filename)) {
  1531.         InternalError(1114); /* input and output file names are the same? */
  1532.     }
  1533.     return (buffer_start + BEFORE_SIZE);
  1534. }
  1535. static void bump_line_counters(void)
  1536. {
  1537.     ++physical_input_line;
  1538.     ++logical_input_line;
  1539. }
  1540.  
  1541. /* Nonzero if we've hit a 'bad error', and should not write an obj file,
  1542.    and exit with a nonzero error code */
  1543. static int bad_error = 0;
  1544. void InternalError(int err)
  1545. {
  1546.     if (err < 2000) {
  1547.         fprintf(stderr,"Internal error %d\t",err);
  1548.     }
  1549.     else if (err < 3000) {
  1550.         fprintf(stderr,"Internal error %d\t",err);
  1551.         bad_error++;
  1552.     }
  1553.     else if (err < 4000) {
  1554.         fprintf(stderr,"Warning %d\t",err);
  1555.     }
  1556.     printf("line %d\n",physical_input_line);
  1557.     if (err < 2000) exit(err);
  1558. }
  1559. void WriteError(void)
  1560. {
  1561.     fprintf(stderr,"Write error. Disk Full?\n");
  1562.     exit(1);
  1563. }
  1564. /* obstack.c - subroutines used implicitly by object stack macros */
  1565. /* Determine default alignment.  */
  1566. struct fooalign {
  1567.     char x;
  1568.     double d;
  1569. };
  1570. #define DEFAULT_ALIGNMENT ((char *)&((struct fooalign *) 0)->d - (char *)0)
  1571. /* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
  1572.    But in fact it might be less smart and round addresses to as much as
  1573.    DEFAULT_ROUNDING.  So we prepare for it to do that.  */
  1574. #define DEFAULT_ROUNDING 4
  1575. /* When we copy a long block of data, this is the unit to do it with. */
  1576. #ifndef COPYING_UNIT
  1577. #define COPYING_UNIT int
  1578. #endif
  1579. static void _obstack_begin(struct obstack * h, int size, int alignment, void *(*chunkfun) (int), void (*freefun) (void *))
  1580. {
  1581.     register struct _obstack_chunk *chunk;  /* points to new chunk */
  1582.     if (alignment == 0)
  1583.         alignment = DEFAULT_ALIGNMENT;
  1584.     if (size == 0) {
  1585.         /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. Use the
  1586.         values for range checking, because if range checking is off, the
  1587.         extra bytes won't be missed terribly, but if range checking is on
  1588.         and we used a larger request, a whole extra 4096 bytes would be
  1589.         allocated.
  1590.  
  1591.         These number are irrelevant to the new GNU malloc.  I suspect it is
  1592.         less sensitive to the size of the request.  */
  1593.         int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
  1594.                     + 4 + DEFAULT_ROUNDING - 1)
  1595.                     & ~(DEFAULT_ROUNDING - 1));
  1596.         size = 4096 - extra;
  1597.     }
  1598.     h->chunkfun = (struct _obstack_chunk * (*) (int)) chunkfun;
  1599.     h->freefun = freefun;
  1600.     h->chunk_size = size;
  1601.     h->alignment_mask = alignment - 1;
  1602.     chunk = h->chunk = (*h->chunkfun) (h->chunk_size);
  1603.     h->next_free = h->object_base = chunk->contents;
  1604.     h->chunk_limit = chunk->limit
  1605.         = (char *) chunk + h->chunk_size;
  1606.     chunk->prev = 0;
  1607. }
  1608. /* Allocate a new current chunk for the obstack *H on the assumption that LENGTH
  1609.    bytes need to be added to the current object, or a new object of length LENGTH
  1610.    allocated. Copies any partial object from the end of the old chunk to the
  1611.    beginning of the new one.
  1612. */
  1613. static void _obstack_newchunk(struct obstack * h, int length)
  1614. {
  1615.     register struct _obstack_chunk *old_chunk = h->chunk;
  1616.     register struct _obstack_chunk *new_chunk;
  1617.     register long new_size;
  1618.     register int obj_size = h->next_free - h->object_base;
  1619.     register int i;
  1620.     int already;
  1621.     /* Compute size for new chunk.  */
  1622.     new_size = (obj_size + length) + (obj_size >> 3) + 100;
  1623.     if (new_size < h->chunk_size)
  1624.         new_size = h->chunk_size;
  1625.     /* Allocate and initialize the new chunk.  */
  1626.     new_chunk = h->chunk = (*h->chunkfun) (new_size);
  1627.     new_chunk->prev = old_chunk;
  1628.     new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
  1629.     /* Move the existing object to the new chunk. Word at a time is fast and
  1630.     is safe if the object is sufficiently aligned.  */
  1631.     if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT) {
  1632.         for (i = obj_size / sizeof(COPYING_UNIT) - 1;
  1633.                 i >= 0; i--)
  1634.             ((COPYING_UNIT *) new_chunk->contents)[i]
  1635.                 = ((COPYING_UNIT *) h->object_base)[i];
  1636.         /* We used to copy the odd few remaining bytes as one extra
  1637.         COPYING_UNIT, but that can cross a page boundary on a machine which
  1638.         does not do strict alignment for COPYING_UNITS.  */
  1639.         already = obj_size / sizeof(COPYING_UNIT) * sizeof(COPYING_UNIT);
  1640.     }
  1641.     else
  1642.         already = 0;
  1643.     /* Copy remaining bytes one by one.  */
  1644.     for (i = already; i < obj_size; i++)
  1645.         new_chunk->contents[i] = h->object_base[i];
  1646.     /* If the object just copied was the only data in OLD_CHUNK, free that
  1647.     chunk and remove it from the chain.  */
  1648.     if (h->object_base == old_chunk->contents) {
  1649.         new_chunk->prev = old_chunk->prev;
  1650.         (*h->freefun) (old_chunk);
  1651.     }
  1652.     h->object_base = new_chunk->contents;
  1653.     h->next_free = h->object_base + obj_size;
  1654. }
  1655. /*
  1656.  * In: a character.
  1657.  * Out: TRUE if this character ends a line.
  1658.  */
  1659. #define _ (0)
  1660. static const char is_end_of_line[256] = {
  1661.     _, _, _, _, _, _, _, _, _, _, 99, _, _, _, _, _,    /* @abcdefghijklmno */
  1662.     _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
  1663.     _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
  1664.     _, _, _, _, _, _, _, _, _, _, _, 99, _, _, _, _,    /* 0123456789:;<=>? */
  1665.     _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
  1666.     _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
  1667.     _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
  1668.     _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
  1669.     _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
  1670.     _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
  1671.     _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
  1672.     _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
  1673.     _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _  /* */
  1674. };
  1675. #undef _
  1676. static char *hash_insert(struct HASH_LIST * where, char *name, char *data)
  1677. {
  1678.     struct HASH_LIST *rvp, *result,**slots;
  1679.     register int h;
  1680.     register char *p = name;
  1681.     int len;
  1682.  
  1683.     for (h = 0; *p;)
  1684.         h = (h << 2) ^ *p++;
  1685.     h &= HASHSIZE-1;
  1686.     slots = (struct HASH_LIST **)where->Data;
  1687.     rvp = slots[h];
  1688.     len = p - name;
  1689.     while (rvp) {
  1690.         if (rvp->len == len && !strcmp(name, rvp->Name)) return(rvp->Name);
  1691.         rvp = rvp->Next;
  1692.     }
  1693.     rvp = slots[h];
  1694.     result = (struct HASH_LIST *)allocate(sizeof(struct HASH_LIST),4);
  1695.     result->Next = rvp;
  1696.     result->Name = name;
  1697.     result->len = len;
  1698.     slots[h] = result;
  1699.     result->Data = data;
  1700.     return ("");
  1701. }
  1702. static char *hash_find(struct HASH_LIST * w, char *n)
  1703. {
  1704.     register struct HASH_LIST *rvp;
  1705.     register int h;
  1706.     register char *p = n;
  1707.  
  1708.     for (h = 0; *p;)
  1709.         h = (h << 2) ^ *p++;
  1710.     rvp = ((struct HASH_LIST **)w->Data)[h & (HASHSIZE-1)];
  1711.     h = p - n;
  1712.     while (rvp) {
  1713.         if ((rvp->len == h) && !strcmp(n, rvp->Name)) return(rvp->Data);
  1714.         rvp = rvp->Next;
  1715.     }
  1716.     return (NULL);
  1717. }
  1718. static struct HASH_LIST *hash_new(void)
  1719. {
  1720.     struct HASH_LIST *r;
  1721.     r = (struct HASH_LIST *) allocate(sizeof(struct HASH_LIST),4);
  1722.     r->Name = xmalloc(1);
  1723.     r->Data = xmalloc((HASHSIZE+1)*sizeof(struct HASH_LIST *));
  1724.     return (r);
  1725. }
  1726. static void symbol_table_insert(symbolS *symbolP)
  1727. {
  1728.     struct HASH_LIST *rvp;
  1729.     struct HASH_LIST *result,**slots;
  1730.     register int h;
  1731.     register char *p = symbolP->Name;
  1732.     char *n = p;
  1733.  
  1734.     for (h = 0; *p;)
  1735.         h = (h << 2) ^ *p++;
  1736.     h &= HASHSIZE-1;
  1737.     slots = (struct HASH_LIST **)sy_hash->Data;
  1738.     rvp = slots[h];
  1739.     result = (struct HASH_LIST *) allocate(sizeof(struct HASH_LIST),4);
  1740.     result->Next = rvp;
  1741.     result->Name = n;
  1742.     result->len = p - n;
  1743.     result->Data = (char *)symbolP;
  1744.     slots[h] = result;
  1745.     return;
  1746. }
  1747. /* set up pseudo-op tables */
  1748. static struct hash_control *po_hash = NULL; /* use before set up: NULL->
  1749.                         address error */
  1750. static symbolS *CurrentFunctionSymbol;
  1751.  
  1752. static char *input_buffer(char *inbuffer,int len)
  1753. {
  1754.     register char *limit;   /* -> just after last char of buffer. */
  1755.     if (partial_size) {
  1756.         bcopy(partial_where, buffer_start + BEFORE_SIZE, (int) partial_size);
  1757.         bcopy(save_source, buffer_start + BEFORE_SIZE, (int) AFTER_SIZE);
  1758.     }
  1759.     memcpy(buffer_start + BEFORE_SIZE + partial_size,inbuffer,len);
  1760.     limit = buffer_start + BEFORE_SIZE + partial_size + len;
  1761.     if (len) {
  1762.         register char *p;   /* Find last newline. */
  1763.         for (p = limit; *--p != '\n';) {
  1764.         }
  1765.         ++p;
  1766.         if (p <= buffer_start + BEFORE_SIZE) {
  1767.             InternalError(1006);
  1768.         }
  1769.         partial_where = p;
  1770.         partial_size = limit - p;
  1771.         bcopy(partial_where, save_source, (int) AFTER_SIZE);
  1772.         bcopy(AFTER_STRING, partial_where, (int) AFTER_SIZE);
  1773.     }
  1774.     else {
  1775.         partial_where = 0;
  1776.         if (partial_size > 0) {
  1777.             InternalError(2070);
  1778.         }
  1779.     }
  1780.     return (partial_where);
  1781. }
  1782.  
  1783. /* AsmReadBuffer()
  1784.  * File has already been opened, and will be closed by our caller.
  1785.  * We read the file, putting things into a web that
  1786.  * represents what we have been reading.
  1787.  */
  1788. void AsmReadBuffer(char *buffer,int len)
  1789. {
  1790.     register char c;
  1791.     register char *s;   /* string of symbol, '\0' appended */
  1792.     pseudo_typeS *pop;
  1793.  
  1794.     buffer_limit = input_buffer(buffer,len);   /* We have
  1795.                         another line to parse. */
  1796.     know(buffer_limit[-1] == '\n'); /* Must have a sentinel. */
  1797.     InputPointer = buffer_start + BEFORE_SIZE;
  1798. contin:
  1799.     while (InputPointer < buffer_limit) { /* We have more of this
  1800.                         buffer to parse. */
  1801.         /* We now have InputPointer -> 1st char of next line. If
  1802.         InputPointer [-1] == '\n' then we just scanned another
  1803.         line: so bump line counters. */
  1804.         if (InputPointer[-1] == '\n') {
  1805.             bump_line_counters();
  1806.         }
  1807.         /* We are at the begining of a line, or similar place. We expect
  1808.             a well-formed assembler statement. A "symbol-name:" is a
  1809.             statement. */
  1810.         while ((c = *InputPointer++) == '\t' || c == ' ') {
  1811.             ;
  1812.         }
  1813.         know(c != ' '); /* No further leading whitespace. */
  1814.         /* c is the 1st significant character. InputPointer points
  1815.             after that character. */
  1816.         if (c == '\n') {
  1817.             continue;
  1818.         }
  1819.         if (c == ';') {
  1820.             while (*InputPointer != '\n')
  1821.                 InputPointer++;
  1822.                 continue;
  1823.         }
  1824.         if (is_name_beginner(c)) {  /* want user-defined label or
  1825.                         pseudo/opcode */
  1826.             s = --InputPointer;
  1827.             while (is_part_of_name(c = *InputPointer++));
  1828.             *--InputPointer = 0;
  1829.             /* C is character after symbol. That character's place in the
  1830.                 input line is now '\0'. S points to the beginning of the
  1831.                 symbol. [In case of pseudo-op, s -> '.'.]
  1832.                 InputPointer -> '\0' where c was. */
  1833.             if (c == ':') {
  1834.                 colon(s);   /* user-defined label */
  1835.                 *InputPointer++ = ':';    /* Put ':' back for error
  1836.                         messages' sake. */
  1837.                     /* InputPointer -> after ':'. */
  1838.                 SKIP_WHITESPACE();
  1839.             }
  1840.             else {  /* expect pseudo-op or machine instruction */
  1841.                 if (*s == '.') {
  1842.                     /* PSEUDO - OP.
  1843.                         WARNING: c has next char, which may be end-of-line.
  1844.                         We lookup the pseudo-op table with s+1 because we
  1845.                         already know that the pseudo-op begins with a '.'. */
  1846.                     pop = (pseudo_typeS *) hash_find(po_hash, s + 1);
  1847.                         /* Print the error msg now, while we still can */
  1848.                     if (!pop) {
  1849.                         InternalError(1010);
  1850.                     }
  1851.                     /* Put it back for error messages etc. */
  1852.                     *InputPointer = c;
  1853.                     /* The following skip of whitespace is compulsory. */
  1854.                     /* A well shaped space is sometimes all that
  1855.                     seperates keyword from operands. */
  1856.                     if (c == ' ' || c == '\t') {    /* Skip seperator
  1857.                     after keyword. */
  1858.                         InputPointer++;
  1859.                     }
  1860.                     /* Input_line is restored. InputPointer -> 1st
  1861.                         non-blank char after pseudo-operation. */
  1862.                     if (!pop) {
  1863.                         ignore_rest_of_line();
  1864.                         break;
  1865.                     }
  1866.                     else
  1867.                         (*pop->poc_handler)();
  1868.                 }
  1869.                 else {  /* machine instruction */
  1870.                     /* WARNING: c has char, which may be end-of-line. */
  1871.                     /* Also: InputPointer -> `\0` where c was. */
  1872.                     *InputPointer = c;
  1873.                     while (!is_end_of_line[*InputPointer]) {
  1874.                         InputPointer++;
  1875.                     }
  1876.                     c = *InputPointer;
  1877.                     *InputPointer = '\0';
  1878.                     Asm386Instruction(s); /* Assemble 1 instruction. */
  1879.                     *InputPointer++ = c;
  1880.                     /* We resume loop AFTER the end-of-line from this
  1881.                         instruction */
  1882.                 }   /* if (*s=='.') */
  1883.             }       /* if c==':' */
  1884.             continue;
  1885.         }           /* if (is_name_beginner(c) */
  1886.         if (is_end_of_line[c]) {    /* empty statement */
  1887.             continue;
  1888.         }
  1889.         if (isdigit(c)) {   /* local label  ("4:") unsupported */
  1890.             InternalError(1011);
  1891.             InputPointer--;
  1892.             ignore_rest_of_line();
  1893.             continue;
  1894.         }
  1895.         {
  1896.             int i;
  1897.             for (i=0; i<40;i++) putchar(InputPointer[i]);
  1898.             putchar('\n');
  1899.         }
  1900.         InternalError(1012);
  1901.         ignore_rest_of_line();
  1902.     }               /* while (InputPointer<buffer_limit ) */
  1903.     if (old_buffer) {
  1904.         bump_line_counters();
  1905.         if (old_input == 0)
  1906.             return;
  1907.         buffer = old_buffer;
  1908.         InputPointer = old_input;
  1909.         buffer_limit = old_limit;
  1910.         old_buffer = 0;
  1911.         goto contin;
  1912.     }
  1913. }                       /* AsmReadBuffer() */
  1914.  
  1915. static void s_byte(void)
  1916. {
  1917.     cons(1);
  1918. }
  1919. static void s_int(void)
  1920. {
  1921.     cons(4);
  1922. }
  1923.  
  1924. static void s_short(void)
  1925. {
  1926.     cons(2);
  1927. }
  1928.  
  1929. static void s_align(void)
  1930. {
  1931.     register int temp;
  1932.     register long int temp_fill;
  1933.     temp = get_absolute_expression();
  1934. #define MAX_ALIGNMENT (15)
  1935.     if (temp > MAX_ALIGNMENT) {
  1936.         InternalError(1013);
  1937.     }
  1938.     else if (temp < 0) {
  1939.         InternalError(2014);
  1940.         temp = 0;
  1941.     }
  1942.     if (*InputPointer == ',') {
  1943.         InputPointer++;
  1944.         temp_fill = get_absolute_expression();
  1945.     }
  1946.     else
  1947.         temp_fill = 0;
  1948.     /* Only make a frag if we HAVE to. . . */
  1949.     if (temp && !need_pass_2)
  1950.         frag_align(temp, (int) temp_fill);
  1951.     demand_empty_rest_of_line();
  1952. }
  1953. static void s_comm(void)
  1954. {
  1955.     register char *name, *sname;
  1956.     register char c;
  1957.     register char *p;
  1958.     register int temp;
  1959.     register symbolS *symbolP;
  1960.  
  1961.     name = InputPointer;
  1962.     c = get_symbol_end();
  1963.     /* just after name is now '\0' */
  1964.     p = InputPointer;
  1965.     *p = c;
  1966.     SKIP_WHITESPACE();
  1967.     if (*InputPointer != ',') {
  1968.         InternalError(2015);
  1969.         ignore_rest_of_line();
  1970.         return;
  1971.     }
  1972.     InputPointer++;   /* skip ',' */
  1973.     if ((temp = get_absolute_expression()) < 0) {
  1974.         InternalError(1064);
  1975.     }
  1976.     *p = 0;
  1977.     symbolP = symbol_find_or_make(name);
  1978.     sname = xmalloc(strlen(name) + 1);
  1979.     strcpy(sname, name);
  1980.     *p = c;
  1981.     if (symbolP->SymbolValue) {
  1982.         if (symbolP->SymbolValue != (unsigned) temp) {
  1983.             InternalError(1071);
  1984.         }
  1985.     }
  1986.     else {
  1987.         symbolP->SymbolValue = temp;
  1988.         symbolP->sy_type |= N_EXT;
  1989.     }
  1990.     MakeBssSymbol(symbolP,temp,0);
  1991.     know(symbolP->sy_frag == &zero_address_frag);
  1992.     free(sname);
  1993.     demand_empty_rest_of_line();
  1994. }
  1995. static void s_data(void)
  1996. {
  1997.     register int temp;
  1998.     temp = get_absolute_expression();
  1999.     subseg_new(SEG_DATA, (subsegT) temp);
  2000.     demand_empty_rest_of_line();
  2001. }
  2002. static char fbuf[256];
  2003. static void s_file(void)
  2004. {
  2005.     int length;
  2006.     /* Some assemblers tolerate immediately following '"' */
  2007.     SKIP_WHITESPACE();
  2008.     memset(fbuf, 0, 256);
  2009.     if (*InputPointer == '"')
  2010.         InputPointer++;
  2011.     length = 0;
  2012.     while (*InputPointer != '"') {
  2013.         fbuf[length] = *InputPointer++;
  2014.         length++;
  2015.         if (length > 254)
  2016.             break;
  2017.     }
  2018.     SourceFileName = fbuf;
  2019.     if (*InputPointer == '"')
  2020.         InputPointer++;
  2021.     demand_empty_rest_of_line();
  2022. }
  2023. static void s_globl(void)
  2024. {
  2025.     register char *name;
  2026.     register int c;
  2027.     register symbolS *symbolP;
  2028.  
  2029.     do {
  2030.         name = InputPointer;
  2031.         c = get_symbol_end();
  2032.         symbolP = symbol_find_or_make(name);
  2033.         symbolP->StorageClass = 2;  /* external symbol */
  2034.         *InputPointer = c;
  2035.         SKIP_WHITESPACE();
  2036.         symbolP->sy_type |= N_EXT;
  2037.         if (c == ',') {
  2038.             InputPointer++;
  2039.             SKIP_WHITESPACE();
  2040.             if (*InputPointer == '\n')
  2041.                 c = '\n';
  2042.         }
  2043.     } while (c == ',');
  2044.     demand_empty_rest_of_line();
  2045. }
  2046. static void MakeBssSymbol(symbolS *symbolP,int siz,int localflag)
  2047. {
  2048.     if (localflag)
  2049.         symbolP->SymbolValue = local_bss_counter;
  2050.     else
  2051.         symbolP->SymbolValue = siz;
  2052.     symbolP->sy_type = N_BSS;
  2053.     symbolP->Flags = IS_BSS;
  2054.     local_bss_counter += siz;
  2055.     if (localflag)
  2056.         symbolP->StorageClass = 3;  /* static symbol */
  2057.     else
  2058.         symbolP->StorageClass = 2;  /* external symbol */
  2059.     if (localflag)
  2060.         symbolP->SectionNumber = SECTION_BSS;
  2061.     else
  2062.         symbolP->SectionNumber = 0;
  2063. }
  2064. static void s_lcomm(void)
  2065. {
  2066.     register char *name;
  2067.     register char c;
  2068.     register char *p;
  2069.     register int temp;
  2070.     register symbolS *symbolP;
  2071.     name = InputPointer;
  2072.     c = get_symbol_end();
  2073.     p = InputPointer;
  2074.     SKIP_WHITESPACE();
  2075.     *p = c;
  2076.     if (*InputPointer != ',') {
  2077.         InternalError(1072);
  2078.     }
  2079.     InputPointer++;
  2080.     if ((temp = get_absolute_expression()) < 0) {
  2081.         InternalError(1073);
  2082.     }
  2083.     *p = 0;
  2084.     symbolP = symbol_find_or_make(name);
  2085.     *p = c;
  2086.     if (((symbolP->sy_type == N_BSS
  2087.                 && symbolP->SymbolValue == local_bss_counter)
  2088.                 || ((symbolP->sy_type & N_TYPE) == N_UNDF
  2089.                     && symbolP->SymbolValue == 0))) {
  2090.         MakeBssSymbol(symbolP,temp,1);
  2091.     }
  2092.     else {
  2093.         InternalError(1074);
  2094.     }
  2095.     demand_empty_rest_of_line();
  2096. }
  2097. static COFF_LINE *lastLine;
  2098. static void s_line(void)
  2099. {
  2100.     int l,c;
  2101.  
  2102.     do {
  2103.         c = *InputPointer++;
  2104.     } while (c == '\t' || c == ' ');
  2105.     InputPointer--;
  2106.     l = atoi(InputPointer);
  2107.     while (*InputPointer != '\n') InputPointer++;
  2108.     if (CurrentFunctionSymbol) {
  2109.         COFF_LINE *coffL, *rvpL;
  2110.         if (CurrentFunctionSymbol->StartLine == 0) {
  2111.             CurrentFunctionSymbol->StartLine = l;
  2112.         }
  2113.         else {
  2114.             coffL = (COFF_LINE *) allocate(sizeof(COFF_LINE),3);
  2115.             coffL->Next = NULL;
  2116.             coffL->Frag = frag_now;
  2117.             coffL->Line = l - CurrentFunctionSymbol->StartLine;
  2118.             coffL->fragOffset = obstack_next_free(&frags) - frag_now->fr_literal;
  2119.             rvpL = CurrentFunctionSymbol->Lines;
  2120.             if (rvpL == NULL) {
  2121.                 CurrentFunctionSymbol->Lines = coffL;
  2122.                 lastLine = coffL;
  2123.             }
  2124.             else {
  2125.                 lastLine->Next = coffL;
  2126.                 lastLine = coffL;
  2127.             }
  2128.             CurrentFunctionSymbol->EndLine = l;
  2129.         }
  2130.     }
  2131.     if (l > 0)
  2132.         logical_input_line = l;
  2133.     demand_empty_rest_of_line();
  2134. }
  2135. static void s_lsym(void)
  2136. {
  2137.     register char *name;
  2138.     register char c;
  2139.     register char *p;
  2140.     register segT segment;
  2141.     expressionS exp;
  2142.  
  2143.     name = InputPointer;
  2144.     c = get_symbol_end();
  2145.     p = InputPointer;
  2146.     *p = c;
  2147.     SKIP_WHITESPACE();
  2148.     if (*InputPointer != ',') {
  2149.         *p = 0;
  2150.         InternalError(1075);
  2151.     }
  2152.     InputPointer++;
  2153.     segment = expression(&exp);
  2154.     if (segment != SEG_ABSOLUTE && segment != SEG_DATA &&
  2155.             segment != SEG_TEXT && segment != SEG_BSS) {
  2156.         InternalError(2016);
  2157.         ignore_rest_of_line();
  2158.         return;
  2159.     }
  2160.     know(segment == SEG_ABSOLUTE || segment == SEG_DATA || segment == SEG_TEXT || segment == SEG_BSS);
  2161.     *p = 0;
  2162.     symbol_new(name, (unsigned char) (seg_N_TYPE[(int) segment]),
  2163.                     (valueT) (exp.X_add_number), &zero_address_frag);
  2164.     *p = c;
  2165.     demand_empty_rest_of_line();
  2166. }
  2167. static void s_space(void)
  2168. {
  2169.     long int temp_repeat;
  2170.     register long int temp_fill;
  2171.     register char *p;
  2172.     /* Just like .fill, but temp_size = 1 */
  2173.     if (get_absolute_expression_and_terminator(&temp_repeat) == ',') {
  2174.         temp_fill = get_absolute_expression();
  2175.     }
  2176.     else {
  2177.         InputPointer--;   /* Backup over what was not a ','. */
  2178.         temp_fill = 0;
  2179.     }
  2180.     if (temp_repeat <= 0) {
  2181.         InternalError(1076);
  2182.     }
  2183.     if (!need_pass_2) {
  2184.         p = frag_var(rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
  2185.                     temp_repeat, (char *) 0);
  2186.         *p = (char) temp_fill;
  2187.     }
  2188.     demand_empty_rest_of_line();
  2189. }
  2190. static void s_text(void)
  2191. {
  2192.     register int temp;
  2193.     temp = get_absolute_expression();
  2194.     subseg_new(SEG_TEXT, (subsegT) temp);
  2195.     demand_empty_rest_of_line();
  2196. }
  2197.  
  2198. static void CreateNewSection(char *name)
  2199. {
  2200.     NewSection *aNewSection;
  2201.  
  2202.     CurrentSpecialSection = aNewSection = (NewSection *)xmalloc(sizeof(NewSection));
  2203.     if (SectionList == NULL) {
  2204.         SectionList = aNewSection;
  2205.     }
  2206.     else {
  2207.         NewSection *rvp;
  2208.  
  2209.         rvp = SectionList;
  2210.         while (rvp->Next) rvp = rvp->Next;
  2211.         rvp->Next = aNewSection;
  2212.     }
  2213.     strcpy(aNewSection->Name,name);
  2214.     aNewSection->Number = 3 + NumberOfSpecialSections++;
  2215. }
  2216.  
  2217.  
  2218. static void s_section(void)
  2219. {
  2220.     char *name,delim;
  2221.  
  2222.     name = InputPointer;
  2223.     delim = get_symbol_end();
  2224.     if (!strcmp(name,".text")) {
  2225.         IsSpecialSection = 0;
  2226.         subseg_new(SEG_TEXT,0);
  2227.     }
  2228.     else if (!strcmp(name,".data")) {
  2229.         IsSpecialSection = 0;
  2230.         subseg_new(SEG_DATA,0);
  2231.     }
  2232.     else {
  2233.         IsSpecialSection = 1;
  2234.         CreateNewSection(name);
  2235.     }
  2236.     *InputPointer = delim;
  2237.     demand_empty_rest_of_line();
  2238. }
  2239.  
  2240. static void s_type(void)
  2241. {
  2242.     char *name;
  2243.     char delim;
  2244.     symbolS *symbolP;
  2245.  
  2246.     name = InputPointer;
  2247.     delim = get_symbol_end();
  2248.     symbolP = symbol_find_or_make(name);
  2249.     *InputPointer++ = delim;
  2250.     SKIP_WHITESPACE();
  2251.     if (*InputPointer == ',')
  2252.         InputPointer++;
  2253.     switch (*InputPointer) {
  2254.     case 'f':          /* function */
  2255.         symbolP->Flags |= IS_TEXT | IS_FUNCTION;
  2256.         symbolP->Flags &= ~IS_DATA;
  2257.         symbolP->SectionNumber = SECTION_TEXT;
  2258.         if (symbolP->StorageClass == 0)
  2259.             symbolP->StorageClass = 3; /* Static */
  2260.         symbolP->Type = 0x20;
  2261.         symbolP->FnInfo = (COFF_FN *) xmalloc(sizeof(COFF_FN));
  2262.         CurrentFunctionSymbol = symbolP;
  2263.         break;
  2264.     case 'o':          /* data */
  2265.         symbolP->Flags |= IS_DATA;
  2266.         symbolP->Flags &= ~(IS_TEXT|IS_BSS);
  2267.         symbolP->SectionNumber = SECTION_DATA;
  2268.         if (symbolP->StorageClass == 0)
  2269.             symbolP->StorageClass = 3;
  2270.         break;
  2271.     default:
  2272.         InternalError(1008);
  2273.     }
  2274.     while (!is_end_of_line[*InputPointer]) {
  2275.         delim = *InputPointer++;
  2276.     }
  2277.     demand_empty_rest_of_line();
  2278. }
  2279. static void s_size(void)
  2280. {
  2281.     char *name;
  2282.     char delim;
  2283.     int c;
  2284.     symbolS *coffS, *endS;
  2285.  
  2286.     name = InputPointer;
  2287.     delim = get_symbol_end();
  2288.     coffS = symbol_find_or_make(name);
  2289.     *InputPointer++ = delim;
  2290.     SKIP_WHITESPACE();
  2291.     c = *InputPointer;
  2292.     if (c <= '9' && c >= '0') {
  2293.         get_absolute_expression();
  2294.     }
  2295.     else {
  2296.         name = InputPointer;
  2297.         delim = get_symbol_end();
  2298.         endS = symbol_find_or_make(name);
  2299.         coffS->FnInfo->End = endS;
  2300.         coffS->FnInfo->Start = coffS;
  2301.     }
  2302.     while (!is_end_of_line[*InputPointer])
  2303.         InputPointer++;
  2304.     demand_empty_rest_of_line();
  2305. }
  2306. static void demand_empty_rest_of_line(void)
  2307. {
  2308.     SKIP_WHITESPACE();
  2309.     if (is_end_of_line[*InputPointer]) {
  2310.         InputPointer++;
  2311.     }
  2312.     else {
  2313.         ignore_rest_of_line();
  2314.     }
  2315. }                       /* Return pointing just after end-of-line. */
  2316.  
  2317. static void ignore_rest_of_line(void)
  2318. {                       /* For suspect lines: gives warning. */
  2319.     if (!is_end_of_line[*InputPointer]) {
  2320.         InternalError(2077);
  2321.         while (InputPointer < buffer_limit
  2322.                 && !is_end_of_line[*InputPointer]) {
  2323.             InputPointer++;
  2324.         }
  2325.     }
  2326.     InputPointer++;   /* Return pointing just after end-of-line. */
  2327.     know(is_end_of_line[InputPointer[-1]]);
  2328. }
  2329. /*
  2330.  *          cons()
  2331.  * CONStruct more frag of .bytes, or .words etc.
  2332.  * Should need_pass_2 be TRUE then emit no frag(s).
  2333.  * This understands EXPRESSIONS, as opposed to big_cons().
  2334.  * Bug (?)
  2335.  * This has a split personality. We use expression() to read the
  2336.  * value. We can detect if the value won't fit in a byte or word.
  2337.  * But we can't detect if expression() discarded significant digits
  2338.  * in the case of a long. Not worth the crocks required to fix it.
  2339.  */
  2340. static void cons(int nbytes)
  2341. {                       /* worker to do .byte etc statements */
  2342.     /* clobbers InputPointer, checks */
  2343.     /* end-of-line. */
  2344.     /* 1=.byte, 2=.word, 4=.long */
  2345.     register char c;
  2346.     register long int mask; /* High-order bits we will left-truncate, */
  2347.     /* but includes sign bit also. */
  2348.     register long int get;  /* what we get */
  2349.     register long int use;  /* get after truncation. */
  2350.     register long int unmask;   /* what bits we will store */
  2351.     register char *p;
  2352.     register segT segment;
  2353.     expressionS exp;
  2354.     /* InputPointer -> 1st char after pseudo-op-code and could legally
  2355.     be a end-of-line. (Or, less legally an eof - which we cope with.) */
  2356.     if (nbytes >= sizeof(long int))
  2357.         mask = 0;
  2358.     else
  2359.         mask = ~0 << (8 * nbytes);  /* Don't store these bits. */
  2360.     unmask = ~mask;     /* Do store these bits. */
  2361.     /* The following awkward logic is to parse ZERO or more expressions,
  2362.     comma seperated. Recall an expression includes its leading & trailing
  2363.     blanks. We fake a leading ',' if there is (supposed to be) a 1st
  2364.     expression, and keep demanding 1 expression for each ','. */
  2365.     if (is_it_end_of_statement()) {
  2366.         c = 0;          /* Skip loop. */
  2367.         InputPointer++;   /* Matches end-of-loop 'correction'. */
  2368.     }
  2369.     else
  2370.         c = ',';        /* Do loop. */
  2371.     while (c == ',') {
  2372.         segment = expression(&exp); /* At least scan over the expression. */
  2373.         if (!need_pass_2) { /* Still worthwhile making frags. */
  2374.             /* Don't call this if we are going to junk this pass anyway! */
  2375.             know(segment != SEG_PASS1);
  2376.             if (segment == SEG_DIFFERENCE && exp.X_add_symbol == NULL) {
  2377.                 InternalError(1087);
  2378.             }
  2379.             if (!IsSpecialSection) {
  2380.                 p = frag_more(nbytes);
  2381.             }
  2382.             else {
  2383.                 char *tmp = CurrentSpecialSection->data;
  2384.                 CurrentSpecialSection->data = xmalloc(CurrentSpecialSection->DataSize + nbytes);
  2385.                 if (tmp) {
  2386.                     memcpy(CurrentSpecialSection->data,tmp,CurrentSpecialSection->DataSize);
  2387.                     p = CurrentSpecialSection->data + CurrentSpecialSection->DataSize;
  2388.                 }
  2389.                 else p = CurrentSpecialSection->data;
  2390.                 CurrentSpecialSection->DataSize += nbytes;
  2391.             }
  2392.             switch (segment) {
  2393.             case SEG_BIG:
  2394.                 InternalError(1088);
  2395.                 break;
  2396.             case SEG_NONE:
  2397.                 InternalError(1089);
  2398.                 /* fall into SEG_ABSOLUTE */
  2399.             case SEG_ABSOLUTE:
  2400.                 get = exp.X_add_number;
  2401.                 use = get & unmask;
  2402.                 if ((get & mask) && (get & mask) != mask) { /* Leading bits
  2403.                         contain both 0s & 1s. */
  2404.                     InternalError(1090);
  2405.                 }
  2406.                 switch(nbytes) {
  2407.                     case 1:
  2408.                         p[0] = (unsigned char)use;
  2409.                         break;
  2410.                     case 2:
  2411.                         *(unsigned short *)(p) = (unsigned short)use;
  2412.                         break;
  2413.                     case 4:
  2414.                         *(unsigned long *)(p) = use;
  2415.                         break;
  2416.                     default:
  2417.                         printf("Internal error nbytes=%d\n",nbytes);
  2418.                         break;
  2419.                 }
  2420.                 break;
  2421.             case SEG_DIFFERENCE:
  2422.             case SEG_BSS:
  2423.             case SEG_UNKNOWN:
  2424.             case SEG_TEXT:
  2425.             case SEG_DATA:
  2426.                 if (IsSpecialSection) {
  2427.                     InternalError(1116);
  2428.                 }
  2429.                 newFixup(frag_now, p - frag_now->fr_literal, (short int) nbytes,
  2430.                         exp.X_add_symbol, exp.X_subtract_symbol,
  2431.                         exp.X_add_number, 0);
  2432.                 break;
  2433.             default:
  2434.                 InternalError(1107);
  2435.                 break;
  2436.             }           /* switch(segment) */
  2437.         }               /* if(!need_pass_2) */
  2438.         c = *InputPointer++;
  2439.     }                   /* while(c==',') */
  2440.     InputPointer--;   /* Put terminator back into stream. */
  2441.     demand_empty_rest_of_line();
  2442. }                       /* cons() */
  2443.  
  2444. static long int get_absolute_expression(void)
  2445. {
  2446.     expressionS exp;
  2447.     register segT s;
  2448.     if ((s = expression(&exp)) != SEG_ABSOLUTE) {
  2449.         if (s != SEG_NONE) {
  2450.             InternalError(1096);
  2451.         }
  2452.         exp.X_add_number = 0;
  2453.     }
  2454.     return (exp.X_add_number);
  2455. }
  2456. static char get_absolute_expression_and_terminator(long int *val_pointer)
  2457. {
  2458.     *val_pointer = get_absolute_expression();
  2459.     return (*InputPointer++);
  2460. }
  2461.  
  2462. /* is_it_end_of_statement()
  2463.  * In:  InputPointer -> next character.
  2464.  * Do:  Skip InputPointer over all whitespace.
  2465.  * Out: TRUE if InputPointer -> end-of-line.
  2466.  */
  2467. static int is_it_end_of_statement(void)
  2468. {
  2469.     while (*InputPointer == ' ' || *InputPointer == '\t')
  2470.         InputPointer++;
  2471.     return (is_end_of_line[*InputPointer]);
  2472. }
  2473.  
  2474. /* lexical macros */
  2475. #define is_opcode_char(x) (opcode_chars[(unsigned char) x])
  2476. #define is_operand_char(x) (operand_chars[(unsigned char) x])
  2477. #define is_register_char(x) (register_chars[(unsigned char) x])
  2478. #define is_space_char(x) (space_chars[(unsigned char) x])
  2479. #define is_identifier_char(x) (identifier_chars[(unsigned char) x])
  2480. #define is_digit_char(x) (digit_chars[(unsigned char) x])
  2481. /* put here all non-digit non-letter charcters that may occur in an operand */
  2482. static char operand_special_chars[] = "%$-+(,)*._~/<>|&^!:";
  2483. /* Asm386Instruction() always leaves the strings it's passed unaltered.To
  2484.    effect this we maintain a stack of saved characters that we've smashed
  2485.    with '\0's (indicating end of strings for various sub-fields of the
  2486.    assembler instruction). */
  2487. static char save_stack[32];
  2488. static char *save_stack_p;  /* stack pointer */
  2489. #define END_STRING_AND_SAVE(s)      *save_stack_p++ = *s; *s = '\0'
  2490. #define RESTORE_END_STRING(s)       *s = *--save_stack_p
  2491. /* The instruction we're assembling.
  2492.    i, disp_expressions, and im_expressions should be continguous in memory */
  2493. static i386_insn i;
  2494. /* Per instruction expressionS buffers: 2 displacements & 2 immediate max. */
  2495. static expressionS disp_expressions[2], im_expressions[2];
  2496. /* pointers to ebp & esp entries in reg_hash hash table */
  2497. static reg_entry *ebp, *esp;
  2498. static int this_operand;/* current operand we are working on */
  2499. /* for interface with expression () */
  2500. extern char *InputPointer;
  2501. /* obstack for constructing various things in InitializeAsmTables */
  2502. static struct obstack o;
  2503. /* hash table for opcode lookup */
  2504. static struct hash_control *op_hash = (struct hash_control *) 0;
  2505.  
  2506. /* hash table for prefix lookup */
  2507. static struct hash_control *prefix_hash = (struct hash_control *) 0;
  2508. static void InitializeAsmTables(void)
  2509. {
  2510.     char *hash_err;
  2511.     template *optab;
  2512.     templates *core_optab;
  2513.     char *prev_name;
  2514.     reg_entry *regtab;
  2515.     prefix_entry *prefixtab;
  2516.     unsigned int c,j,k;
  2517.     symbolS *symbolP;
  2518.     pseudo_typeS *pop;
  2519.  
  2520.     obstack_begin(&o, 4096);
  2521.     /* initialize op_hash hash table */
  2522.     op_hash = hash_new();   /* xmalloc handles error */
  2523.     optab = i386_optab; /* setup for loop */
  2524.     prev_name = optab->name;
  2525.     obstack_grow(&o, optab, sizeof(template));
  2526.     core_optab = (templates *) xmalloc(sizeof(templates));
  2527.     for (optab++; optab < i386_optab_end; optab++) {
  2528.         if (!strcmp(optab->name, prev_name)) {
  2529.             /* same name as before --> append to current template list */
  2530.             obstack_grow(&o, optab, sizeof(template));
  2531.         }
  2532.         else {
  2533.             /* different name --> ship out current template list; add to hash
  2534.             table; & begin anew Note: end must be set before start! since
  2535.             obstack_next_free changes upon opstack_finish */
  2536.             core_optab->end = (template *) obstack_next_free(&o);
  2537.             core_optab->start = (template *) obstack_finish(&o);
  2538.             hash_err = hash_insert(op_hash, prev_name, (char *) core_optab);
  2539.             if (hash_err && *hash_err) {
  2540.         hash_error:
  2541.                 InternalError(1009);
  2542.             }
  2543.             prev_name = optab->name;
  2544.             core_optab = (templates *) xmalloc(sizeof(templates));
  2545.             obstack_grow(&o, optab, sizeof(template));
  2546.         }
  2547.     }
  2548.     // This should be tested each time a new instruction is added
  2549.     // We suppose that we have no two operands with a name that
  2550.     // has the same length and the same first two letters.
  2551. #if 0
  2552.     for (c=0; c<HASHSIZE;c++) {
  2553.         register struct HASH_LIST *rvp;
  2554.         char tab[70000];
  2555.         printf("[%3d] ",c);
  2556.  
  2557.         rvp = ((struct HASH_LIST **)op_hash->Data)[c & (HASHSIZE-1)];
  2558.         memset(tab,0,66000);
  2559.         while (rvp) {
  2560.             if (tab[*(unsigned short *)rvp->Name]) {
  2561.                 printf("*****\nTotal collision char %c\n",rvp->Name[1]);
  2562.             }
  2563.             tab[*(unsigned short *)rvp->Name] = 1;
  2564.             printf("%s ",rvp->Name);
  2565.             rvp = rvp->Next;
  2566.         }
  2567.         printf("\n");
  2568.     }
  2569. #endif
  2570.     /* initialize reg_hash hash table */
  2571.     c = j = 0;
  2572.     for (regtab = i386_regtab; regtab < i386_regtab_end; regtab++) {
  2573.         for (k=0;k<4;k++) {
  2574.             if (regtab->reg_name[k] == 0) {
  2575.                 while (k < 4) {
  2576.                     RegisterNames[j++] = 0; k++;
  2577.                 }
  2578.                 break;
  2579.             }
  2580.             RegisterNames[j++] = regtab->reg_name[k];
  2581.         }
  2582.         if (!strncmp(regtab->reg_name,"esp",3)) {
  2583.             esp = regtab;
  2584.         }
  2585.         else if (!strncmp(regtab->reg_name,"ebp",3)) {
  2586.             ebp = regtab;
  2587.         }
  2588.         c++;
  2589.     }
  2590. //    printf("number of registers: %d\n",c);
  2591.     /* initialize reg_hash hash table */
  2592.     prefix_hash = hash_new();
  2593.     for (prefixtab = i386_prefixtab;
  2594.             prefixtab < i386_prefixtab_end; prefixtab++) {
  2595.         hash_err = hash_insert(prefix_hash, prefixtab->prefix_name, (char *) prefixtab);
  2596.         if (hash_err && *hash_err)
  2597.             goto hash_error;
  2598.     }
  2599.     /* fill in lexical tables:  opcode_chars, operand_chars, space_chars */
  2600.     memset(opcode_chars,0, sizeof(opcode_chars));
  2601.     memset(operand_chars,0, sizeof(operand_chars));
  2602.     memset(space_chars,0, sizeof(space_chars));
  2603.     memset(identifier_chars,0, sizeof(identifier_chars));
  2604.     memset(digit_chars,0, sizeof(digit_chars));
  2605.     for (c = 0; c < 256; c++) {
  2606.         if (islower(c) || isdigit(c)) {
  2607.             opcode_chars[c] = c;
  2608.             register_chars[c] = c;
  2609.         }
  2610.         else if (isupper(c)) {
  2611.             opcode_chars[c] = tolower(c);
  2612.             register_chars[c] = opcode_chars[c];
  2613.         }
  2614.         else if (c == PREFIX_SEPERATOR) {
  2615.             opcode_chars[c] = c;
  2616.         }
  2617.         else if (c == ')' || c == '(') {
  2618.             register_chars[c] = c;
  2619.         }
  2620.         if (isupper(c) || islower(c) || isdigit(c))
  2621.             operand_chars[c] = c;
  2622.         else if (c && index(operand_special_chars, c))
  2623.             operand_chars[c] = c;
  2624.         if (isdigit(c) || c == '-')
  2625.             digit_chars[c] = c;
  2626.         if (isalpha(c) || c == '_' || c == '.' || isdigit(c))
  2627.             identifier_chars[c] = c;
  2628.         if (c == ' ' || c == '\t')
  2629.             space_chars[c] = c;
  2630.     }
  2631.     operand_chars['@'] = '@'; /* This is needed to support the stdcall feature */
  2632.     symbolP = symbol_new(".text",N_TEXT,0,NULL);
  2633.     symbol_table_insert(symbolP);
  2634.     symbolP->SectionNumber = SECTION_TEXT;
  2635.     symbolP->Flags = IS_TEXT;
  2636.     symbolP->StorageClass = 3;
  2637.     symbolP->NumberOfAuxSymbols = 1;
  2638.  
  2639.     symbolP = symbol_new(".data",N_DATA,0,NULL);
  2640.     symbol_table_insert(symbolP);
  2641.     symbolP->SectionNumber = SECTION_DATA;
  2642.     symbolP->Flags = IS_DATA;
  2643.     symbolP->StorageClass = 3;
  2644.     symbolP->NumberOfAuxSymbols = 1;
  2645.  
  2646.     symbolP = symbol_new(".bss",N_BSS,0,NULL);
  2647.     symbol_table_insert(symbolP);
  2648.     symbolP->SectionNumber = SECTION_BSS;
  2649.     symbolP->StorageClass = 3;
  2650.     symbolP->NumberOfAuxSymbols = 1;
  2651.     symbolP->Flags = IS_BSS;
  2652.     /* Initialize the pseudo operations table */
  2653.     po_hash = hash_new();
  2654.     hash_err = "";        /* OK so far */
  2655.     for (pop = potable; pop->poc_name && !*hash_err; pop++) {
  2656.         hash_err = hash_insert(po_hash, pop->poc_name, (char *) pop);
  2657.     }
  2658.     if (*hash_err) {
  2659.         InternalError(1007);
  2660.     }
  2661. }
  2662.  
  2663. /*
  2664.   This is the guts of the machine-dependent assembler.  LINE points to a
  2665.   i386 instruction.  This function emits the bytes it assembles to.
  2666.  */
  2667. static void Asm386Instruction(char *line)
  2668. {
  2669.     /* Holds template once we've found it. */
  2670.     register template *t;
  2671. //    register char *p;
  2672.     int h,lasth;
  2673.     register struct HASH_LIST *rvp;
  2674.     register unsigned int overlap0, overlap1;
  2675.     expressionS *exp;
  2676.     unsigned int overlap2;
  2677.     unsigned int found_reverse_match;
  2678.     char *q;
  2679.     register char *l = line;    /* Fast place to put LINE. */
  2680.     /* TRUE if operand is pending after ','. */
  2681.     unsigned int expecting_operand = 0;
  2682.     /* TRUE if we found a prefix only acceptable with string insns. */
  2683.     unsigned int expecting_string_instruction = 0;
  2684.     /* Non-zero if operand parens not balenced. */
  2685.     unsigned int paren_not_balanced;
  2686.     unsigned short first_two_chars;
  2687.     char *token_start = l;
  2688.     /* Possible templates for current insn */
  2689.     templates *current_templates = (templates *) 0;
  2690.     /* Initialize globals. */
  2691.     memset(&i,0, sizeof(i));
  2692.     memset(disp_expressions,0, sizeof(disp_expressions));
  2693.     memset(im_expressions,0, sizeof(im_expressions));
  2694.     save_stack_p = save_stack;  /* reset stack pointer */
  2695.     /* Fist parse an opcode & call i386_operand for the operands. We assume
  2696.     that the scrubber has arranged it so that line[0] is the valid start of
  2697.     a (possibly prefixed) opcode. */
  2698. //    We assume that there is no opcode shorter than two bytes
  2699.     lasth = 0 ^ *l++;
  2700.     h = (lasth << 2) ^ *l++;
  2701.     while (is_opcode_char(*l)) {
  2702.         lasth = h;
  2703.         h = (h << 2) ^ *l++;
  2704.     }
  2705.     /* Lookup insn in hash; try intel & att naming conventions if
  2706.     appropriate; that is:  we only use the opcode suffix 'b' 'w' or 'l' if
  2707.     we need to. */
  2708.     rvp = ((struct HASH_LIST **)op_hash->Data)[h & (HASHSIZE-1)];
  2709.     h = l - token_start;
  2710.     first_two_chars = *(unsigned short *)token_start;
  2711.     while (rvp) {
  2712.         if ((rvp->len == h) && first_two_chars == *(unsigned short *)rvp->Name) {
  2713.             current_templates = (templates *)rvp->Data;
  2714.             goto suite;
  2715.         }
  2716.         rvp = rvp->Next;
  2717.     }
  2718.  
  2719.     h--;
  2720.     switch (token_start[h]) {
  2721.         case DWORD_OPCODE_SUFFIX:
  2722.         case WORD_OPCODE_SUFFIX:
  2723.         case BYTE_OPCODE_SUFFIX:
  2724.             rvp = ((struct HASH_LIST **)op_hash->Data)[lasth & (HASHSIZE-1)];
  2725.             while (rvp) {
  2726.                 if ((rvp->len == h) &&
  2727.                     first_two_chars == *(unsigned short *)rvp->Name) {
  2728.                     current_templates = (templates *)rvp->Data;
  2729.                     i.suffix = token_start[h];
  2730.                     goto suite;
  2731.                 }
  2732.             rvp = rvp->Next;
  2733.         }
  2734.     }
  2735.     printf("No such instruction %s\n",token_start);
  2736.     InternalError(1024);
  2737. suite:
  2738.     /* check for rep/repne without a string instruction */
  2739.     if (expecting_string_instruction &&
  2740.             !IS_STRING_INSTRUCTION(current_templates->
  2741.                                 start->base_opcode)) {
  2742.         InternalError(1025);
  2743.     }
  2744.     /* There may be operands to parse. */
  2745.     if (*l != END_OF_INSN //&&
  2746.     /* For string instructions, we ignore any operands if given.  This
  2747.     kludges, for example, 'rep/movsb %ds:(%esi), %es:(%edi)' where the
  2748.     operands are always going to be the same, and are not really encoded in
  2749.     machine code.
  2750.             !IS_STRING_INSTRUCTION(current_templates->
  2751.                                 start->base_opcode)
  2752.     Since lcc never generates those arguments this test has been dropped
  2753. */
  2754.         ) {
  2755.         /* parse operands */
  2756.         do {
  2757.             /* skip optional white space before operand */
  2758.             while (is_space_char(*l))
  2759.                 l++;
  2760.             token_start = l;    /* after white space */
  2761.             paren_not_balanced = 0;
  2762.             while (paren_not_balanced || *l != ',') {
  2763.                 if (*l == END_OF_INSN) {
  2764.                     if (paren_not_balanced) {
  2765.                         InternalError(1027);
  2766.                     }
  2767.                     else
  2768.                         break;  /* we are done */
  2769.                 }
  2770.                 else if (!is_operand_char(*l)) {
  2771.                     while (*l == ' ' || *l == '\t') l++;
  2772.                     if (*l == ';' || *l == END_OF_INSN) {
  2773.                         break;
  2774.                     }
  2775.                     else {
  2776.                         printf("incorrect char %c\n",*l);
  2777.                         h = 0;
  2778.                         while (line[h] != '\n') {
  2779.                             printf("%c",line[h++]);
  2780.                         }
  2781.                         printf("\n");
  2782.                         InternalError(1028);
  2783.                     }
  2784.                 }
  2785.                 if (*l == '(')
  2786.                     ++paren_not_balanced;
  2787.                 if (*l == ')')
  2788.                     --paren_not_balanced;
  2789.                 l++;
  2790.             }
  2791.             if (l != token_start) { /* yes, we've read in another operand */
  2792.                 this_operand = i.operands++;
  2793.                 if (i.operands > MAX_OPERANDS) {
  2794.                     InternalError(1029);
  2795.                 }
  2796.                 /* now parse operand adding info to 'i' as we go along */
  2797.                 END_STRING_AND_SAVE(l);
  2798.                 h = i386_operand(token_start,l);
  2799.                 RESTORE_END_STRING(l);  /* restore old contents */
  2800.                 if (!h)
  2801.                     return;
  2802.             }
  2803.             else {
  2804.                 if (expecting_operand) {
  2805.             expecting_operand_after_comma:
  2806.                     InternalError(1030);
  2807.                 }
  2808.                 if (*l == ',') {
  2809.                     InternalError(1031);
  2810.                 }
  2811.             }
  2812.             /* now *l must be either ',' or END_OF_INSN */
  2813.             if (*l == ',') {
  2814.                 if (*++l == END_OF_INSN) {  /* just skip it, if it's \n
  2815.                         complain */
  2816.                     goto expecting_operand_after_comma;
  2817.                 }
  2818.                 expecting_operand = TRUE;
  2819.             }
  2820.         } while (*l != END_OF_INSN);    /* until we get end of insn */
  2821.     }
  2822.     /* Now we've parsed the opcode into a set of templates, and have the
  2823.     operands at hand. Next, we find a template that matches the given insn,
  2824.     making sure the overlap of the given operands types is consistent with
  2825.     the template operand types. */
  2826. #define MATCH(overlap,given_type) \
  2827.   (overlap && \
  2828.    (overlap & (JumpAbsolute|BaseIndex|Mem8)) \
  2829.    == (given_type & (JumpAbsolute|BaseIndex|Mem8)))
  2830.     /* If m0 and m1 are register matches they must be consistent with the
  2831.     expected operand types t0 and t1. That is, if both m0 & m1 are register
  2832.     matches i.e. ( ((m0 & (Reg)) && (m1 & (Reg)) ) ? then, either 1. or 2.
  2833.     must be true: 1. the expected operand type register overlap is null:
  2834.     (t0 & t1 & Reg) == 0 AND the given register overlap is null: (m0 & m1 &
  2835.     Reg) == 0 2. the expected operand type register overlap == the given
  2836.     operand type overlap:  (t0 & t1 & m0 & m1 & Reg). */
  2837. #define CONSISTENT_REGISTER_MATCH(m0, m1, t0, t1) \
  2838.     ( ((m0 & (Reg)) && (m1 & (Reg))) ? \
  2839.     ( ((t0 & t1 & (Reg)) == 0 && (m0 & m1 & (Reg)) == 0) || \
  2840.         ((t0 & t1) & (m0 & m1) & (Reg)) \
  2841.     ) : 1)
  2842.     overlap0 = overlap1 = overlap2 = found_reverse_match = 0;
  2843.     for (t = current_templates->start;
  2844.             t < current_templates->end;
  2845.             t++) {
  2846.         /* must have right number of operands */
  2847.         if (i.operands != t->operands)
  2848.             continue;
  2849.         else if (!t->operands)
  2850.             break;      /* 0 operands always matches */
  2851.         overlap0 = i.types[0] & t->operand_types[0];
  2852.         switch (t->operands) {
  2853.         case 1:
  2854.             if (!MATCH(overlap0, i.types[0]))
  2855.                 continue;
  2856.             break;
  2857.         case 2:
  2858.         case 3:
  2859.             overlap1 = i.types[1] & t->operand_types[1];
  2860.             if (!MATCH(overlap0, i.types[0]) ||
  2861.                     !MATCH(overlap1, i.types[1]) ||
  2862.                     !CONSISTENT_REGISTER_MATCH(overlap0, overlap1,
  2863.                                             t->operand_types[0],
  2864.                                             t->operand_types[1])) {
  2865.                 /* check if other direction is valid ... */
  2866.                 if (!(t->opcode_modifier & COMES_IN_BOTH_DIRECTIONS))
  2867.                     continue;
  2868.                 /* try reversing direction of operands */
  2869.                 overlap0 = i.types[0] & t->operand_types[1];
  2870.                 overlap1 = i.types[1] & t->operand_types[0];
  2871.                 if (!MATCH(overlap0, i.types[0]) ||
  2872.                         !MATCH(overlap1, i.types[1]) ||
  2873.                         !CONSISTENT_REGISTER_MATCH(overlap0, overlap1,
  2874.                                                 t->operand_types[0],
  2875.                                                 t->operand_types[1])) {
  2876.                     /* does not match either direction */
  2877.                     continue;
  2878.                 }
  2879.                 /* found a reverse match here -- slip through */
  2880.                 /* found_reverse_match holds which of D or FloatD we've found */
  2881.                 found_reverse_match = t->opcode_modifier & COMES_IN_BOTH_DIRECTIONS;
  2882.             }           /* endif: not forward match */
  2883.             /* found either forward/reverse 2 operand match here */
  2884.             if (t->operands == 3) {
  2885.                 overlap2 = i.types[2] & t->operand_types[2];
  2886.                 if (!MATCH(overlap2, i.types[2]) ||
  2887.                         !CONSISTENT_REGISTER_MATCH(overlap0, overlap2,
  2888.                                                 t->operand_types[0],
  2889.                                                 t->operand_types[2]) ||
  2890.                         !CONSISTENT_REGISTER_MATCH(overlap1, overlap2,
  2891.                                                 t->operand_types[1],
  2892.                                                 t->operand_types[2]))
  2893.                     continue;
  2894.             }
  2895.             /* found either forward/reverse 2 or 3 operand match here: slip
  2896.             through to break */
  2897.         }
  2898.         break;          /* we've found a match; break out of loop */
  2899.     }                   /* for (t = ... */
  2900.     if (t == current_templates->end) {  /* we found no match */
  2901.         InternalError(1032);
  2902.     }
  2903.     /* Copy the template we found (we may change it!). */
  2904.     bcopy(t, &i.tm, sizeof(template));
  2905.     t = &i.tm;          /* alter new copy of template */
  2906.     /* If there's no opcode suffix we try to invent one based on register
  2907.     operands. */
  2908.     if (!i.suffix && i.reg_operands) {
  2909.         /* We take i.suffix from the LAST register operand specified. This
  2910.         assumes that the last register operands is the destination register
  2911.         operand. */
  2912.         for (h = 0; h < MAX_OPERANDS; h++)
  2913.             if (i.types[h] & Reg) {
  2914.                 i.suffix = (i.types[h] == Reg8) ? BYTE_OPCODE_SUFFIX :
  2915.                     (i.types[h] == Reg16) ? WORD_OPCODE_SUFFIX :
  2916.                     DWORD_OPCODE_SUFFIX;
  2917.             }
  2918.     }
  2919.     /* Make still unresolved immediate matches conform to size of immediate
  2920.     given in i.suffix. Note:  overlap2 cannot be an immediate! We assume
  2921.     this. */
  2922.     if ((overlap0 & (Imm8 | Imm8S | Imm16 | Imm32))
  2923.             && overlap0 != Imm8 && overlap0 != Imm8S
  2924.             && overlap0 != Imm16 && overlap0 != Imm32) {
  2925.         if (!i.suffix) {
  2926.             InternalError(1033);
  2927.         }
  2928.         overlap0 &= (i.suffix == BYTE_OPCODE_SUFFIX ? (Imm8 | Imm8S) :
  2929.                     (i.suffix == WORD_OPCODE_SUFFIX ? Imm16 : Imm32));
  2930.     }
  2931.     if ((overlap1 & (Imm8 | Imm8S | Imm16 | Imm32))
  2932.             && overlap1 != Imm8 && overlap1 != Imm8S
  2933.             && overlap1 != Imm16 && overlap1 != Imm32) {
  2934.         if (!i.suffix) {
  2935.             InternalError(1034);
  2936.         }
  2937.         overlap1 &= (i.suffix == BYTE_OPCODE_SUFFIX ? (Imm8 | Imm8S) :
  2938.                     (i.suffix == WORD_OPCODE_SUFFIX ? Imm16 : Imm32));
  2939.     }
  2940.     i.types[0] = overlap0;
  2941.     i.types[1] = overlap1;
  2942.     i.types[2] = overlap2;
  2943.     if (overlap0 & ImplicitRegister)
  2944.         i.reg_operands--;
  2945.     if (overlap1 & ImplicitRegister)
  2946.         i.reg_operands--;
  2947.     if (overlap2 & ImplicitRegister)
  2948.         i.reg_operands--;
  2949.     if (overlap0 & Imm1)
  2950.         i.imm_operands = 0; /* kludge for shift insns */
  2951.     if (found_reverse_match) {
  2952.         h = t->operand_types[0];
  2953.         t->operand_types[0] = t->operand_types[1];
  2954.         t->operand_types[1] = h;
  2955.     }
  2956.     if (i.tm.base_opcode == 136 && i.operands == 2 && i.mem_operands == 0 &&
  2957.         i.regs[0] == i.regs[1]) {
  2958. /*        printf("%s %s,%s\n",i.tm.name,i.regs[0]->reg_name,i.regs[1]->reg_name); */
  2959.         return;
  2960.     }
  2961.     if (!i.suffix && (t->opcode_modifier & W)) {
  2962.         InternalError(1035);
  2963.     }
  2964.     /* Finalize opcode.  First, we change the opcode based on the operand
  2965.     size given by i.suffix: we never have to change things for byte insns,
  2966.     or when no opcode suffix is need to size the operands. */
  2967.     if (i.suffix && i.suffix != BYTE_OPCODE_SUFFIX) {
  2968.         /* Select between byte and word/dword operations. */
  2969.         if (t->opcode_modifier & W)
  2970.             t->base_opcode |= W;
  2971.         /* Now select between word & dword operations via the operand size
  2972.         prefix. */
  2973.         if (i.suffix == WORD_OPCODE_SUFFIX) {
  2974.             if (i.prefixes == MAX_PREFIXES) {
  2975.                 InternalError(1036);
  2976.             }
  2977.             i.prefix[i.prefixes++] = WORD_PREFIX_OPCODE;
  2978.         }
  2979.     }
  2980.     /* For insns with operands there are more diddles to do to the opcode. */
  2981.     if (i.operands) {
  2982.         /* If we found a reverse match we must alter the opcode direction bit
  2983.         found_reverse_match holds bit to set (different for int & float
  2984.         insns). */
  2985.         if (found_reverse_match) {
  2986.             t->base_opcode |= found_reverse_match;
  2987.         }
  2988.         /* The imul $imm, %reg instruction is converted into imul $imm, %reg,
  2989.         %reg. */
  2990.         if (t->opcode_modifier & imulKludge) {
  2991.             i.regs[2] = i.regs[1];  /* Pretend we saw the 3 operand case. */
  2992.             i.reg_operands = 2;
  2993.         }
  2994.         /* Certain instructions expect the destination to be in the i.rm.reg
  2995.         field. They are:
  2996.         "movzb","movzwl","imul","imul","imul","bsf","bsr","lar","lsl"
  2997.         For these instructions, if the source operand is a register, we must
  2998.         reverse the i.rm.reg and i.rm.regmem fields.  We accomplish this by faking
  2999.         that the two register operands were given in the reverse order. */
  3000.         if ((t->opcode_modifier & ReverseRegRegmem) && i.reg_operands == 2) {
  3001.             unsigned int first_reg_operand = (i.types[0] & Reg) ? 0 : 1;
  3002.             unsigned int second_reg_operand = first_reg_operand + 1;
  3003.             reg_entry *tmp = i.regs[first_reg_operand];
  3004.             i.regs[first_reg_operand] = i.regs[second_reg_operand];
  3005.             i.regs[second_reg_operand] = tmp;
  3006.         }
  3007.         if (t->opcode_modifier & ShortForm) {
  3008.             /* The register or float register operand is in operand 0 or 1. */
  3009.             unsigned int o = (i.types[0] & (Reg | FloatReg)) ? 0 : 1;
  3010.             /* Register goes in low 3 bits of opcode. */
  3011.             t->base_opcode |= i.regs[o]->reg_num;
  3012.         }
  3013.         else if (t->opcode_modifier & ShortFormW) {
  3014.             /* Short form with 0x8 width bit.  Register is always dest.
  3015.             operand */
  3016.             t->base_opcode |= i.regs[1]->reg_num;
  3017.             if (i.suffix == WORD_OPCODE_SUFFIX ||
  3018.                     i.suffix == DWORD_OPCODE_SUFFIX)
  3019.                 t->base_opcode |= 0x8;
  3020.         }
  3021.         else if (t->opcode_modifier & Seg2ShortForm) {
  3022.             if (t->base_opcode == POP_SEG_SHORT && i.regs[0]->reg_num == 1) {
  3023.                 InternalError(1037);
  3024.             }
  3025.             t->base_opcode |= (i.regs[0]->reg_num << 3);
  3026.         }
  3027.         else if (t->opcode_modifier & Seg3ShortForm) {
  3028.             /* 'push %fs' is 0x0fa0; 'pop %fs' is 0x0fa1. 'push %gs' is
  3029.             0x0fa8; 'pop %fs' is 0x0fa9. So, only if i.regs[0]->reg_num ==
  3030.             5 (%gs) do we need to change the opcode. */
  3031.             if (i.regs[0]->reg_num == 5)
  3032.                 t->base_opcode |= 0x08;
  3033.         }
  3034.         else if (t->opcode_modifier & Modrm) {
  3035.             /* The opcode is completed (modulo t->extension_opcode which must
  3036.             be put into the modrm byte. Now, we make the modrm & index base
  3037.             bytes based on all the info we've collected. */
  3038.             /* i.reg_operands MUST be the number of real register operands;
  3039.             implicit registers do not count. */
  3040.             if (i.reg_operands == 2) {
  3041.                 unsigned int source, dest;
  3042.                 source = (i.types[0] & (Reg | SReg2 | SReg3 | Control | Debug | Test | MmxReg)) ? 0 : 1;
  3043.                 dest = source + 1;
  3044.                 i.rm.mode = 3;
  3045.                 /* We must be careful to make sure that all
  3046.                 segment/control/test/ debug registers go into the i.rm.reg
  3047.                 field (despite the whether they are source or destination
  3048.                 operands). */
  3049.                 if (i.regs[dest]->reg_type & (SReg2 | SReg3 | Control | Debug | Test | MmxReg)) {
  3050.                     i.rm.reg = i.regs[dest]->reg_num;
  3051.                     i.rm.regmem = i.regs[source]->reg_num;
  3052.                 }
  3053.                 else {
  3054.                     i.rm.reg = i.regs[source]->reg_num;
  3055.                     i.rm.regmem = i.regs[dest]->reg_num;
  3056.                 }
  3057.             }
  3058.             else {      /* if it's not 2 reg operands... */
  3059.                 if (i.mem_operands) {
  3060.                     unsigned int fake_zero_displacement = FALSE;
  3061.                     unsigned int o = (i.types[0] & Mem) ? 0 : ((i.types[1] & Mem) ? 1 : 2);
  3062.                     /* Encode memory operand into modrm byte and base index
  3063.                     byte. */
  3064.                     if (i.base_reg == esp && !i.index_reg) {
  3065.                         /* <disp>(%esp) becomes two byte modrm with no index
  3066.                         register. */
  3067.                         i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
  3068.                         i.rm.mode = MODE_FROM_DISP_SIZE(i.types[o]);
  3069.                         i.bi.base = ESP_REG_NUM;
  3070.                         i.bi.index = NO_INDEX_REGISTER;
  3071.                         i.bi.scale = 0; /* Must be zero! */
  3072.                     }
  3073.                     else if (i.base_reg == ebp && !i.index_reg) {
  3074.                         if (!(i.types[o] & Disp)) {
  3075.                             /* Must fake a zero byte displacement. There is
  3076.                             no direct way to code '(%ebp)' directly. */
  3077.                             fake_zero_displacement = TRUE;
  3078.                             /* fake_zero_displacement code does not set this. */
  3079.                             i.types[o] |= Disp8;
  3080.                         }
  3081.                         i.rm.mode = MODE_FROM_DISP_SIZE(i.types[o]);
  3082.                         i.rm.regmem = EBP_REG_NUM;
  3083.                     }
  3084.                     else if (!i.base_reg && (i.types[o] & BaseIndex)) {
  3085.                         /* There are three cases here. Case 1:  '<32bit
  3086.                         disp>(,1)' -- indirect absolute. (Same as cases 2 &
  3087.                         3 with NO index register) Case 2: <32bit disp>
  3088.                         (,<index>) -- no base register with disp Case 3: (,
  3089.                         <index>)       --- no base register; no disp (must
  3090.                         add 32bit 0 disp). */
  3091.                         i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
  3092.                         i.rm.mode = 0;  /* 32bit mode */
  3093.                         i.bi.base = NO_BASE_REGISTER;
  3094.                         i.types[o] &= ~Disp;
  3095.                         i.types[o] |= Disp32;   /* Must be 32bit! */
  3096.                         if (i.index_reg) {  /* case 2 or case 3 */
  3097.                             i.bi.index = i.index_reg->reg_num;
  3098.                             i.bi.scale = i.log2_scale_factor;
  3099.                             if (i.disp_operands == 0)
  3100.                                 fake_zero_displacement = TRUE;  /* case 3 */
  3101.                         }
  3102.                         else {
  3103.                             i.bi.index = NO_INDEX_REGISTER;
  3104.                             i.bi.scale = 0;
  3105.                         }
  3106.                     }
  3107.                     else if (i.disp_operands && !i.base_reg && !i.index_reg) {
  3108.                         /* Operand is just <32bit disp> */
  3109.                         i.rm.regmem = EBP_REG_NUM;
  3110.                         i.rm.mode = 0;
  3111.                         i.types[o] &= ~Disp;
  3112.                         i.types[o] |= Disp32;
  3113.                     }
  3114.                     else {
  3115.                         /* It's not a special case; rev'em up. */
  3116.                         i.rm.regmem = i.base_reg->reg_num;
  3117.                         i.rm.mode = MODE_FROM_DISP_SIZE(i.types[o]);
  3118.                         if (i.index_reg) {
  3119.                             i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
  3120.                             i.bi.base = i.base_reg->reg_num;
  3121.                             i.bi.index = i.index_reg->reg_num;
  3122.                             i.bi.scale = i.log2_scale_factor;
  3123.                             if (i.base_reg == ebp && i.disp_operands == 0) {
  3124.                                 /* p ace */
  3125.                                 fake_zero_displacement = TRUE;
  3126.                                 i.types[o] |= Disp8;
  3127.                                 i.rm.mode = MODE_FROM_DISP_SIZE(i.types[o]);
  3128.                             }
  3129.                         }
  3130.                     }
  3131.                     if (fake_zero_displacement) {
  3132.                         /* Fakes a zero displacement assuming that i.types[o]
  3133.                         holds the correct displacement size. */
  3134.                         exp = &disp_expressions[i.disp_operands++];
  3135.                         i.disps[o] = exp;
  3136.                         exp->X_seg = SEG_ABSOLUTE;
  3137.                         exp->X_add_number = 0;
  3138.                         exp->X_add_symbol = (symbolS *) 0;
  3139.                         exp->X_subtract_symbol = (symbolS *) 0;
  3140.                     }
  3141.                     /* Select the correct segment for the memory operand. */
  3142.                     if (i.seg) {
  3143.                         unsigned int seg_index;
  3144.                         seg_entry *default_seg;
  3145.                         if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING) {
  3146.                             seg_index = (i.rm.mode << 3) | i.bi.base;
  3147.                             default_seg = two_byte_segment_defaults[seg_index];
  3148.                         }
  3149.                         else {
  3150.                             seg_index = (i.rm.mode << 3) | i.rm.regmem;
  3151.                             default_seg = one_byte_segment_defaults[seg_index];
  3152.                         }
  3153.                         /* If the specified segment is not the default, use
  3154.                         an opcode prefix to select it */
  3155.                         if (i.seg != default_seg) {
  3156.                             if (i.prefixes == MAX_PREFIXES) {
  3157.                                 InternalError(1038);
  3158.                             }
  3159.                             i.prefix[i.prefixes++] = (char)(i.seg->seg_prefix);
  3160.                         }
  3161.                     }
  3162.                 }
  3163.                 /* Fill in i.rm.reg or i.rm.regmem field with register
  3164.                 operand (if any) based on t->extension_opcode. Again, we
  3165.                 must be careful to make sure that
  3166.                 segment/control/debug/test registers are coded into the
  3167.                 i.rm.reg field. */
  3168.                 if (i.reg_operands) {
  3169.                     unsigned int o =
  3170.                     (i.types[0] & (Reg | SReg2 | SReg3 | Control | Debug | Test | MmxReg)) ? 0 :
  3171.                     (i.types[1] & (Reg | SReg2 | SReg3 | Control | Debug | Test | MmxReg)) ? 1 : 2;
  3172.                     /* If there is an extension opcode to put here, the
  3173.                     register number must be put into the regmem field. */
  3174.                     if (t->extension_opcode != None)
  3175.                         i.rm.regmem = i.regs[o]->reg_num;
  3176.                     else
  3177.                         i.rm.reg = i.regs[o]->reg_num;
  3178.                     /* Now, if no memory operand has set i.rm.mode = 0, 1, 2
  3179.                     we must set it to 3 to indicate this is a register
  3180.                     operand int the regmem field */
  3181.                     if (!i.mem_operands)
  3182.                         i.rm.mode = 3;
  3183.                 }
  3184.                 /* Fill in i.rm.reg field with extension opcode (if any). */
  3185.                 if (t->extension_opcode != None)
  3186.                     i.rm.reg = t->extension_opcode;
  3187.             }
  3188.         }
  3189.     }
  3190.     /* Handle conversion of 'int $3' --> special int3 insn. */
  3191.     if (t->base_opcode == INT_OPCODE && i.imms[0]->X_add_number == 3) {
  3192.         t->base_opcode = INT3_OPCODE;
  3193.         i.imm_operands = 0;
  3194.     }
  3195.     if (obstack_room(&frags) <= 14) {
  3196.         frag_wane(frag_now);
  3197.         frag_new(0);
  3198.     }
  3199.     /* We are ready to output the insn. */
  3200.     /* Output jumps. */
  3201.     if (t->opcode_modifier & Jump) {
  3202.         h = i.disps[0]->X_add_number;
  3203.         if (i.disps[0]->X_seg != SEG_ABSOLUTE) {
  3204.             char *p;
  3205.             /* It's a symbol; end frag & setup for relax. Make sure there are
  3206.             6 chars left in the current frag; if not we'll have to start a
  3207.             new one. I caught it failing with obstack_room == 6, so I changed to <=
  3208.             pace */
  3209.             p = frag_more(1);
  3210.             *p = (char)(t->base_opcode);
  3211.  
  3212.             frag_var(rs_machine_dependent,
  3213.                     6, /* 2 opcode/prefix + 4 displacement */
  3214.                     1,
  3215.                     ((uchar) * p == JUMP_PC_RELATIVE
  3216.                     ? ENCODE_RELAX_STATE(UNCOND_JUMP, BYTE)
  3217.                     : ENCODE_RELAX_STATE(COND_JUMP, BYTE)),
  3218.                     i.disps[0]->X_add_symbol,
  3219.                     h, p);
  3220.         }
  3221.         else {
  3222.             if (FITS_IN_SIGNED_BYTE(h)) {
  3223.                 *frags.next_free++ = (char)(t->base_opcode);
  3224.                 *frags.next_free++ = (char)h;
  3225.             }
  3226.             else {      /* It's an absolute dword displacement. */
  3227.                 if (t->base_opcode == JUMP_PC_RELATIVE) {   /* pace */
  3228.                     /* unconditional jump */
  3229.                     *frags.next_free++ = (unsigned char) 0xe9;
  3230.                     *(unsigned long *)(frags.next_free) = h;
  3231.                     frags.next_free += 4;
  3232.                 }
  3233.                 else {
  3234.                     /* conditional jump */
  3235.                     *frags.next_free++ = (char)TWO_BYTE_OPCODE_ESCAPE;
  3236.                     *frags.next_free++ = t->base_opcode + 0x10;
  3237.                     *(unsigned long *)(frags.next_free) = h;
  3238.                     frags.next_free += 4;
  3239.                 }
  3240.             }
  3241.         }
  3242.         return;
  3243.     }
  3244.     else if (t->opcode_modifier & (JumpByte | JumpDword)) {
  3245.         int size = (t->opcode_modifier & JumpByte) ? 1 : 4;
  3246.         h = i.disps[0]->X_add_number;
  3247.         if (t->base_opcode <= 255) {
  3248.             *frags.next_free++ = t->base_opcode;
  3249.         }
  3250.         else {
  3251.             /* put out high byte first */
  3252.             *frags.next_free++ = (char)((t->base_opcode >> 8) & 0xff);
  3253.             *frags.next_free++ = (char)(t->base_opcode & 0xff);
  3254.         }
  3255.         if (i.disps[0]->X_seg == SEG_ABSOLUTE) {
  3256.             if (size == 1) {
  3257.                 if (!FITS_IN_SIGNED_BYTE(h))
  3258.                     InternalError(1039);
  3259.                 *frags.next_free = h;
  3260.             }
  3261.             else
  3262.                 *(unsigned long *)frags.next_free = h;
  3263.         }
  3264.         else {
  3265.             /* Fixup. Here comes the fixup for the call instructions for
  3266.             instance  */
  3267.             newFixup(frag_now, frags.next_free - frag_now->fr_literal, (short int) size,
  3268.                     i.disps[0]->X_add_symbol, i.disps[0]->X_subtract_symbol,
  3269.                     h, 1);
  3270.         }
  3271.         frags.next_free += size;
  3272.         return;
  3273.     }
  3274.     else if (t->opcode_modifier & JumpInterSegment) {
  3275.         /* lcall and ljmp instructions */
  3276.         *frags.next_free++ = (char)(t->base_opcode);
  3277.         if (i.imms[1]->X_seg == SEG_ABSOLUTE) {
  3278.             *(unsigned long *)(frags.next_free) = i.imms[1]->X_add_number;
  3279.             frags.next_free += 4;
  3280.         }
  3281.         else {
  3282.             newFixup(frag_now, frags.next_free - frag_now->fr_literal, (short int) 4,
  3283.                     i.imms[1]->X_add_symbol,
  3284.                     i.imms[1]->X_subtract_symbol,
  3285.                     i.imms[1]->X_add_number, 0);
  3286.             frags.next_free += 4;
  3287.         }
  3288.         if (i.imms[0]->X_seg != SEG_ABSOLUTE) {
  3289.             InternalError(1040);
  3290.         }
  3291.         *(unsigned short *)(frags.next_free) = (unsigned short)(i.imms[0]->X_add_number);
  3292.         frags.next_free += 2;
  3293.         return;
  3294.     }
  3295.     /* Output normal instructions here. */
  3296.     /* First the prefix bytes. */
  3297.     for (q = i.prefix; q < i.prefix + i.prefixes; q++) {
  3298.         *frags.next_free++ = (unsigned char )*q;
  3299.     }
  3300.     /* Now the opcode; be careful about word order here! */
  3301.     if (t->base_opcode <= 255) {
  3302.         *frags.next_free++ = t->base_opcode;
  3303.     }
  3304.     else if (t->base_opcode <= 65535) {
  3305.         /* put out high byte first */
  3306.         *frags.next_free = (char)((t->base_opcode >> 8) & 0xff);
  3307.         frags.next_free[1] = (char)(t->base_opcode & 0xff);
  3308.         frags.next_free += 2;
  3309.     }
  3310.     else {              /* opcode is either 3 or 4 bytes */
  3311.         if (t->base_opcode & 0xff000000) {
  3312.             *frags.next_free++ = (char)((t->base_opcode >> 24) & 0xff);
  3313.         }
  3314.         *frags.next_free = (char)((t->base_opcode >> 16) & 0xff);
  3315.         frags.next_free[1] = (char)((t->base_opcode >> 8) & 0xff);
  3316.         frags.next_free[2] = (char)((t->base_opcode) & 0xff);
  3317.         frags.next_free += 3;
  3318.     }
  3319.     /* Now the modrm byte and base index byte (if present). */
  3320.     if (t->opcode_modifier & Modrm) {
  3321.         *frags.next_free++ = (char)(0xFF & (i.rm.regmem << 0 | i.rm.reg << 3 | i.rm.mode << 6));
  3322.         /* If i.rm.regmem == ESP (4) && i.rm.mode != Mode 3 (Register mode)
  3323.         ==> need second modrm byte. */
  3324.         if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING && i.rm.mode != 3) {
  3325.             *frags.next_free++ = (char)(0xFF & (i.bi.base << 0 | i.bi.index << 3 | i.bi.scale << 6));
  3326.         }
  3327.     }
  3328.     if (i.disp_operands) {
  3329.         int number;
  3330.         for (h = 0; h < (int)i.operands; h++) {
  3331.             if (i.disps[h]) {
  3332.                 if (i.disps[h]->X_seg == SEG_ABSOLUTE) {
  3333.                     number = (i.disps[h]->X_add_number);
  3334.                     if (i.types[h] & (Disp8 | Abs8)) {
  3335.                         *frags.next_free++ = (char)(0xFF & number);
  3336.                     }
  3337.                     else if (i.types[h] & (Disp16 | Abs16)) {
  3338.                         *(unsigned short *)(frags.next_free) = (unsigned short)number;
  3339.                         frags.next_free += 2;
  3340.                     }
  3341.                     else {  /* Disp32|Abs32 */
  3342.                         *(unsigned long *)(frags.next_free) = number;
  3343.                         frags.next_free += 4;
  3344.                     }
  3345.                 }
  3346.                 else {  /* not SEG_ABSOLUTE */
  3347.                     /* need a 32-bit fixup (don't support 8bit non-absolute
  3348.                     disps) */
  3349.                     newFixup(frag_now, frags.next_free - frag_now->fr_literal, 4,
  3350.                     i.disps[h]->X_add_symbol, i.disps[h]->X_subtract_symbol,
  3351.                             i.disps[h]->X_add_number, 0);
  3352.                     frags.next_free += 4;
  3353.                 }
  3354.             }
  3355.         }
  3356.     }                   /* end displacement output */
  3357.     /* output immediate */
  3358.     if (i.imm_operands) {
  3359.         int number;
  3360.         for (h = 0; h < (int)i.operands; h++) {
  3361.             if (i.imms[h]) {
  3362.                 if (i.imms[h]->X_seg == SEG_ABSOLUTE) {
  3363.                     number = i.imms[h]->X_add_number;
  3364.                     if (i.types[h] & (Imm8 | Imm8S)) {
  3365.                         *frags.next_free++ = (char)(0xFF & number);
  3366.                     }
  3367.                     else if (i.types[h] & Imm16) {
  3368.                         *(unsigned short *)(frags.next_free) = (unsigned short)number;
  3369.                         frags.next_free += 2;
  3370.                     }
  3371.                     else {
  3372.                         *(unsigned long *)(frags.next_free) = number;
  3373.                         frags.next_free += 4;
  3374.  
  3375.                     }
  3376.                 }
  3377.                 else {  /* not SEG_ABSOLUTE */
  3378.                     /* need a 32-bit fixup (don't support 8bit non-absolute
  3379.                     ims) */
  3380.                     int size;
  3381.                     if (i.types[h] & (Imm8 | Imm8S))
  3382.                         size = 1;
  3383.                     else if (i.types[h] & Imm16)
  3384.                         size = 2;
  3385.                     else
  3386.                         size = 4;
  3387.                     /* FIXUPS This just fills the fieds of the fixup
  3388.                     structure */
  3389.                     newFixup(frag_now, frags.next_free - frag_now->fr_literal, (short int) size,
  3390.                         i.imms[h]->X_add_symbol, i.imms[h]->X_subtract_symbol,
  3391.                             i.imms[h]->X_add_number, 0);
  3392.                     frags.next_free += size;
  3393.                 }
  3394.             }
  3395.         }
  3396.     }                   /* end immediate output */
  3397. }
  3398. /* Parse OPERAND_STRING into the i386_insn structure I.  Returns non-zero
  3399.    on error. */
  3400. static int i386_operand(char *operand_string,char *end_of_operand_string)
  3401. {
  3402.     register char *op_string;
  3403.     /* Start and end of displacement string expression (if found). */
  3404.     char *displacement_string_start = 0;
  3405.     char *displacement_string_end;
  3406.     if (*operand_string == '0' && operand_string[1] == '(') {
  3407.         operand_string++;
  3408.     }
  3409. #if 1
  3410.     if (OptimizeFlag && *operand_string == '(' && operand_string[1] == ',' &&
  3411.         operand_string[2] == '%' && operand_string[6] == ')') {
  3412.         char *p = &operand_string[2];
  3413.         char *q = &operand_string[1];
  3414.  
  3415.         while (*p) {
  3416.             *q++ = *p++;
  3417.         }
  3418.         *q = 0;
  3419.         end_of_operand_string = q;
  3420.     }
  3421. #endif
  3422.     op_string = operand_string;
  3423.     /* We check for an absolute prefix (differentiating, for example, 'jmp
  3424.     pc_relative_label' from 'jmp *absolute_label'. */
  3425.     if (*op_string == ABSOLUTE_PREFIX) {
  3426.         op_string++;
  3427.         i.types[this_operand] |= JumpAbsolute;
  3428.     }
  3429.     /* Check if operand is a register. */
  3430.     if (*op_string == REGISTER_PREFIX) {
  3431.         register reg_entry *r;
  3432.         if (!(r = parse_register(op_string))) {
  3433.             InternalError(1041);
  3434.         }
  3435.         /* Check for segment override, rather than segment register by
  3436.         searching for ':' after %<x>s where <x> = s, c, d, e, f, g. */
  3437.         if ((r->reg_type & (SReg2 | SReg3)) && op_string[3] == ':') {
  3438.             switch (r->reg_num) {
  3439.             case 0:
  3440.                 i.seg = &es;
  3441.                 break;
  3442.             case 1:
  3443.                 i.seg = &cs;
  3444.                 break;
  3445.             case 2:
  3446.                 i.seg = &ss;
  3447.                 break;
  3448.             case 3:
  3449.                 i.seg = &ds;
  3450.                 break;
  3451.             case 4:
  3452.                 i.seg = &fs;
  3453.                 break;
  3454.             case 5:
  3455.                 i.seg = &gs;
  3456.                 break;
  3457.             }
  3458.             op_string += 4; /* skip % <x> s : */
  3459.             operand_string = op_string; /* Pretend given string starts here. */
  3460.             if (!is_digit_char(*op_string) && !is_identifier_char(*op_string)
  3461.                     && *op_string != '(' && *op_string != ABSOLUTE_PREFIX) {
  3462.                 InternalError(1042);
  3463.             }
  3464.             /* Handle case of %es:*foo. */
  3465.             if (*op_string == ABSOLUTE_PREFIX) {
  3466.                 op_string++;
  3467.                 i.types[this_operand] |= JumpAbsolute;
  3468.             }
  3469.             goto do_memory_reference;
  3470.         }
  3471.         i.types[this_operand] |= r->reg_type;
  3472.         i.regs[this_operand] = r;
  3473.         i.reg_operands++;
  3474.     }
  3475.     else if (*op_string == IMMEDIATE_PREFIX) {  /* ... or an immediate */
  3476.         char *save_InputPointer;
  3477.         register expressionS *exp;
  3478.         segT exp_seg;
  3479.         if (i.imm_operands == MAX_IMMEDIATE_OPERANDS) {
  3480.             InternalError(1043);
  3481.         }
  3482.         exp = &im_expressions[i.imm_operands++];
  3483.         i.imms[this_operand] = exp;
  3484.         save_InputPointer = InputPointer;
  3485.         InputPointer = ++op_string;   /* must advance op_string! */
  3486.         exp_seg = expression(exp);
  3487.         InputPointer = save_InputPointer;
  3488.         switch (exp_seg) {
  3489.         case SEG_NONE: /* missing or bad expr becomes absolute 0 */
  3490.             InternalError(1044);
  3491.             break;
  3492.         case SEG_ABSOLUTE:
  3493.             i.types[this_operand] |= SMALLEST_IMM_TYPE(exp->X_add_number);
  3494.             break;
  3495.         case SEG_TEXT:
  3496.         case SEG_DATA:
  3497.         case SEG_BSS:
  3498.         case SEG_UNKNOWN:
  3499.             i.types[this_operand] |= Imm32; /* this is an address ==> 32bit */
  3500.             break;
  3501.         default:
  3502.     seg_unimplemented:
  3503.             InternalError(1045);
  3504.         }
  3505.         /* shorten this type of this operand if the instruction wants fewer
  3506.         bits than are present in the immediate.*/
  3507.         switch (i.suffix) {
  3508.         case WORD_OPCODE_SUFFIX:
  3509.             i.types[this_operand] |= Imm16;
  3510.             break;
  3511.         case BYTE_OPCODE_SUFFIX:
  3512.             i.types[this_operand] |= Imm16 | Imm8 | Imm8S;
  3513.             break;
  3514.         }
  3515.     }
  3516.     else if (is_digit_char(*op_string) || is_identifier_char(*op_string)
  3517.             || *op_string == '(') {
  3518.         /* This is a memory reference of some sort. */
  3519.         register char *base_string;
  3520.         unsigned int found_base_index_form;
  3521. do_memory_reference:
  3522.         if (i.mem_operands == MAX_MEMORY_OPERANDS) {
  3523.             InternalError(1046);
  3524.         }
  3525.         i.mem_operands++;
  3526.         /* Determine type of memory operand from opcode_suffix; no opcode
  3527.         suffix implies general memory references. */
  3528.         switch (i.suffix) {
  3529.         case BYTE_OPCODE_SUFFIX:
  3530.             i.types[this_operand] |= Mem8;
  3531.             break;
  3532.         case WORD_OPCODE_SUFFIX:
  3533.             i.types[this_operand] |= Mem16;
  3534.             break;
  3535.         case DWORD_OPCODE_SUFFIX:
  3536.         default:
  3537.             i.types[this_operand] |= Mem32;
  3538.         }
  3539.         /* Check for base index form.  We detect the base index form by
  3540.         looking for an ')' at the end of the operand, searching for the '('
  3541.         matching it, and finding a REGISTER_PREFIX or ',' after it. */
  3542.         base_string = end_of_operand_string - 1;
  3543.         while (*base_string == ' ') base_string--;
  3544.         found_base_index_form = FALSE;
  3545.         if (*base_string == ')') {
  3546.             /* We've already checked that the number of left & right ()'s are
  3547.             equal, so this loop will not be infinite. */
  3548.             do {
  3549.                 base_string--;
  3550.                 if (*base_string == '(')
  3551.                     break;
  3552.             } while(1);
  3553.             base_string++;  /* Skip past '('. */
  3554.             if (*base_string == REGISTER_PREFIX || *base_string == ',')
  3555.                 found_base_index_form = TRUE;
  3556.         }
  3557.         /* If we can't parse a base index register expression, we've found a
  3558.         pure displacement expression.  We set up displacement_string_start
  3559.         and displacement_string_end for the code below. */
  3560.         if (!found_base_index_form) {
  3561.             displacement_string_start = op_string;
  3562.             displacement_string_end = end_of_operand_string;
  3563.         }
  3564.         else {
  3565.             char *base_reg_name, *index_reg_name;
  3566.             i.types[this_operand] |= BaseIndex;
  3567.             /* If there is a displacement set-up for it to be parsed later. */
  3568.             if (base_string != op_string + 1) {
  3569.                 displacement_string_start = op_string;
  3570.                 displacement_string_end = base_string - 1;
  3571.             }
  3572.             /* Find base register (if any). */
  3573.             if (*base_string != ',') {
  3574.                 base_reg_name = base_string++;
  3575.                 /* skip past register name & parse it */
  3576.                 while (isalpha(*base_string))
  3577.                     base_string++;
  3578.                 if (base_string == base_reg_name + 1) {
  3579.                     InternalError(1047);
  3580.                 }
  3581.                 END_STRING_AND_SAVE(base_string);
  3582.                 if (!(i.base_reg = parse_register(base_reg_name))) {
  3583.                     InternalError(1048);
  3584.                 }
  3585.                 RESTORE_END_STRING(base_string);
  3586.             }
  3587.             /* Now check seperator; must be ',' ==> index reg OR num ==> no
  3588.             index reg. just scale factor OR ')' ==> end. (scale factor = 1) */
  3589.             if (*base_string != ',' && *base_string != ')') {
  3590.                 InternalError(1049);
  3591.             }
  3592.             /* There may index reg here; and there may be a scale factor. */
  3593.             if (*base_string == ',' && *(base_string + 1) == REGISTER_PREFIX) {
  3594.                 index_reg_name = ++base_string;
  3595.                 while (isalpha(*++base_string));
  3596.                 END_STRING_AND_SAVE(base_string);
  3597.                 if (!(i.index_reg = parse_register(index_reg_name))) {
  3598.                     InternalError(1050);
  3599.                 }
  3600.                 RESTORE_END_STRING(base_string);
  3601.             }
  3602.             /* Check for scale factor. */
  3603.             if (*base_string == ',' && isdigit(*(base_string + 1))) {
  3604.                 switch (*++base_string) {  /* must be 1 digit scale */
  3605.                 case '1':
  3606.                     i.log2_scale_factor = 0;
  3607.                     break;
  3608.                 case '2':
  3609.                     i.log2_scale_factor = 1;
  3610.                     break;
  3611.                 case '4':
  3612.                     i.log2_scale_factor = 2;
  3613.                     break;
  3614.                 case '8':
  3615.                     i.log2_scale_factor = 3;
  3616.                     break;
  3617.                 default:
  3618.                     InternalError(1053);
  3619.                 }
  3620.             }
  3621.             else {
  3622.                 if (!i.index_reg && *base_string == ',') {
  3623.                     InternalError(1054);
  3624.                 }
  3625.             }
  3626.         }
  3627.         /* If there's an expression begining the operand, parse it, assuming
  3628.         displacement_string_start and displacement_string_end are
  3629.         meaningful. */
  3630.         if (displacement_string_start) {
  3631.             register expressionS *exp;
  3632.             segT exp_seg;
  3633.             char *save_InputPointer;
  3634.             exp = &disp_expressions[i.disp_operands];
  3635.             i.disps[this_operand] = exp;
  3636.             i.disp_operands++;
  3637.             save_InputPointer = InputPointer;
  3638.             InputPointer = displacement_string_start;
  3639.             END_STRING_AND_SAVE(displacement_string_end);
  3640.             exp_seg = expression(exp);
  3641.             if (*InputPointer) {
  3642.                 InternalError(2055);
  3643.             }
  3644.             RESTORE_END_STRING(displacement_string_end);
  3645.             InputPointer = save_InputPointer;
  3646.             switch (exp_seg) {
  3647.             case SEG_NONE:
  3648.                 /* missing expr becomes absolute 0 */
  3649.                 InternalError(1056);
  3650.                 break;
  3651.             case SEG_ABSOLUTE:    /*!!!!*/
  3652.                 i.types[this_operand] |= SMALLEST_DISP_TYPE(exp->X_add_number);
  3653.                 break;
  3654.             case SEG_TEXT:
  3655.             case SEG_DATA:
  3656.             case SEG_BSS:
  3657.             case SEG_UNKNOWN:  /* must be 32 bit displacement (i.e. address) */
  3658.                 i.types[this_operand] |= Disp32;
  3659.                 break;
  3660.             default:
  3661.                 goto seg_unimplemented;
  3662.             }
  3663.         }
  3664.         /* Make sure the memory operand we've been dealt is valid. */
  3665.         if (i.base_reg && i.index_reg &&
  3666.                 !(i.base_reg->reg_type & i.index_reg->reg_type & Reg)) {
  3667.             InternalError(1057);
  3668.         }
  3669.         if ((i.base_reg && (i.base_reg->reg_type & Reg32) == 0) ||
  3670.                 (i.index_reg && (i.index_reg->reg_type & Reg32) == 0)) {
  3671.             InternalError(1058);
  3672.         }
  3673.         if (i.index_reg && i.index_reg == esp) {
  3674.             InternalError(1059);
  3675.         }
  3676.     }
  3677.     else {              /* it's not a memory operand; argh! */
  3678.         InternalError(1060);
  3679.     }
  3680.     return 1;           /* normal return */
  3681. }
  3682. /* md_estimate_size_before_relax()
  3683.  * Called just before relax().
  3684.  * Any symbol that is now undefined will not become defined.
  3685.  * Return the correct fr_subtype in the frag.
  3686.  * Return the initial "guess for fr_var" to caller.
  3687.  * The guess for fr_var is ACTUALLY the growth beyond fr_fix.
  3688.  * Whatever we do to grow fr_fix or fr_var contributes to our returned value.
  3689.  * Although it may not be explicit in the frag, pretend fr_var starts with a
  3690.  * 0 value.
  3691.  */
  3692. static int md_estimate_size_before_relax(register fragS *fragP,
  3693.                     register int segment_type) /* N_DATA or N_TEXT. */
  3694. {
  3695.     register uchar *opcode;
  3696.     register int old_fr_fix;
  3697.     old_fr_fix = fragP->fr_fix;
  3698.     opcode = (uchar *) fragP->fr_opcode;
  3699.     /* We've already got fragP->fr_subtype right;  all we have to do is check
  3700.     for un-relaxable symbols. */
  3701.     if ((fragP->fr_symbol->sy_type & N_TYPE) != segment_type) {
  3702.         /* symbol is undefined in this segment */
  3703.         switch (opcode[0]) {
  3704.         case JUMP_PC_RELATIVE: /* make jmp (0xeb) a dword displacement jump */
  3705.             opcode[0] = 0xe9;   /* dword disp jmp */
  3706.             fragP->fr_fix += 4;
  3707.             newFixup(fragP, old_fr_fix, 4,
  3708.                     fragP->fr_symbol,
  3709.                     (symbolS *) 0,
  3710.                     fragP->fr_offset, 1);
  3711.             break;
  3712.         default:
  3713.             /* This changes the byte-displacement jump 0x7N --> the
  3714.             dword-displacement jump 0x0f8N */
  3715.             opcode[1] = opcode[0] + 0x10;
  3716.             opcode[0] = TWO_BYTE_OPCODE_ESCAPE; /* two-byte escape */
  3717.             fragP->fr_fix += 1 + 4; /* we've added an opcode byte */
  3718.             newFixup(fragP, old_fr_fix + 1, 4,
  3719.                     fragP->fr_symbol,
  3720.                     (symbolS *) 0,
  3721.                     fragP->fr_offset, 1);
  3722.             break;
  3723.         }
  3724.         frag_wane(fragP);
  3725.     }
  3726.     return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
  3727. }                       /* md_estimate_size_before_relax() */
  3728. /* md_convert_frag();
  3729.  * Called after relax() is finished.
  3730.  * In:  Address of frag.
  3731.  *  fr_type == rs_machine_dependent.
  3732.  *  fr_subtype is what the address relaxed to.
  3733.  * Out: Any fixSs and constants are set up. Caller will turn frag into a ".space 0".
  3734.  */
  3735. static void md_convert_frag(register fragS *fragP)
  3736. {
  3737.     register uchar *opcode;
  3738.     uchar *where_to_put_displacement;
  3739.     unsigned int target_address, opcode_address;
  3740.     unsigned int extension,subtype;
  3741.     int displacement_from_opcode_start;
  3742.     opcode = (uchar *) fragP->fr_opcode;
  3743.     /* Address we want to reach in file space. */
  3744.     target_address = fragP->fr_symbol->SymbolValue + fragP->fr_offset;
  3745.     /* Address opcode resides at in file space. */
  3746.     opcode_address = fragP->fr_address + fragP->fr_fix;
  3747.     /* Displacement from opcode start to fill into instruction. */
  3748.     displacement_from_opcode_start = target_address - opcode_address;
  3749.     subtype = fragP->fr_subtype;
  3750.     switch (subtype) {
  3751.     case ENCODE_RELAX_STATE(COND_JUMP, BYTE):
  3752.     case ENCODE_RELAX_STATE(UNCOND_JUMP, BYTE):
  3753.         /* don't have to change opcode */
  3754.         extension = 1;  /* 1 opcode + 1 displacement */
  3755.         where_to_put_displacement = &opcode[1];
  3756.         break;
  3757.     case ENCODE_RELAX_STATE(COND_JUMP, WORD):
  3758.         opcode[1] = TWO_BYTE_OPCODE_ESCAPE;
  3759.         opcode[2] = opcode[0] + 0x10;
  3760.         opcode[0] = WORD_PREFIX_OPCODE;
  3761.         extension = 4;  /* 3 opcode + 2 displacement */
  3762.         where_to_put_displacement = &opcode[3];
  3763.         break;
  3764.     case ENCODE_RELAX_STATE(UNCOND_JUMP, WORD):
  3765.         opcode[1] = 0xe9;
  3766.         opcode[0] = WORD_PREFIX_OPCODE;
  3767.         extension = 3;  /* 2 opcode + 2 displacement */
  3768.         where_to_put_displacement = &opcode[2];
  3769.         break;
  3770.     case ENCODE_RELAX_STATE(COND_JUMP, DWORD):
  3771.         opcode[1] = opcode[0] + 0x10;
  3772.         opcode[0] = TWO_BYTE_OPCODE_ESCAPE;
  3773.         extension = 5;  /* 2 opcode + 4 displacement */
  3774.         where_to_put_displacement = &opcode[2];
  3775.         break;
  3776.     case ENCODE_RELAX_STATE(UNCOND_JUMP, DWORD):
  3777.         opcode[0] = 0xe9;
  3778.         extension = 4;  /* 1 opcode + 4 displacement */
  3779.         where_to_put_displacement = &opcode[1];
  3780.         break;
  3781.     default:
  3782.         InternalError(1108);
  3783.         break;
  3784.     }
  3785.     /* now put displacement after opcode */
  3786.     displacement_from_opcode_start  -= extension;
  3787.     memcpy(where_to_put_displacement,&displacement_from_opcode_start,
  3788.             SIZE_FROM_RELAX_STATE(fragP->fr_subtype));
  3789.  
  3790.     fragP->fr_fix += extension;
  3791. }
  3792. #ifndef ASM_LIB
  3793. /* reg_string starts *before* REGISTER_PREFIX */
  3794. static reg_entry *parse_register(char *reg_string)
  3795. {
  3796.     register char *s = reg_string;
  3797.     register char *p;
  3798.     char reg_name_given[MAX_REG_NAME_SIZE+2];
  3799.     unsigned long l,*pl;
  3800.     int i;
  3801.  
  3802.     *((unsigned long *)reg_name_given) = 0;
  3803.     s++;                /* skip REGISTER_PREFIX */
  3804.     p = reg_name_given;
  3805.     *p++ = *s++;
  3806.     *p++ = *s++;
  3807.     if (is_register_char (*s)) {
  3808.         *p++ = *s++;
  3809.         if (is_register_char(*s))
  3810.             *p = *s;
  3811.     }
  3812.     l = *((unsigned long *)reg_name_given);
  3813.     pl = (unsigned long *)RegisterNames;
  3814.     for (i=0; i<MAX_REG_NAMES; i++) {
  3815.         if (pl[i] == l) return(&i386_regtab[i]);
  3816.     }
  3817.     return(NULL);
  3818. }
  3819. #endif
  3820. static int NrOfTextFixups = 0, NrOfDataFixups = 0, NrOfLineNumbers = 0;
  3821. static long int CodeSize, DataSize, NrOfCoffSymbols;
  3822. static int PosCodeSection, PosDataSection, PosBssSection,
  3823.         PosRawData,PosDebugSymbolsSection,PosDebugTypesSection,
  3824.         PosDebugSSpecialSymbol,PosDebugTSpecialSymbol;
  3825. static FILE *CoffFile;
  3826. static void WriteCoffHeader(void)
  3827. {                       /* Number of symbols ns */
  3828.     unsigned char Header[20];
  3829.     unsigned short *pus;
  3830.     unsigned long *pul;
  3831.     symbolS *coffS;
  3832.     int count;
  3833.     memset(Header, 0, 20);
  3834.     /* Write the machine type: I386 */
  3835.     pus = (unsigned short *) (&Header[0]);
  3836.     *pus = 0x14c;
  3837.     /* Write the number of sections */
  3838.     pus = (unsigned short *) (&Header[2]);
  3839.     *pus = 3 + NumberOfDebugSections + NumberOfSpecialSections;
  3840.     /* Write the time stamp */
  3841.     pul = (unsigned long *) (&Header[4]);
  3842.     *pul = time(NULL);
  3843.     /* Write the pointer to the symbol table */
  3844.     /* null for now */
  3845.     /* Write the number of symbols */
  3846.     pul = (unsigned long *) (&Header[12]);
  3847.     coffS = symbol_rootP;
  3848.     count = 0;
  3849.     while (coffS) {
  3850.         count++;
  3851.         coffS = coffS->Next;
  3852.     }
  3853.     *pul = count;
  3854.     if (20 != fwrite(Header, 1, 20, CoffFile)) {
  3855.         WriteError();
  3856.     }
  3857.     /* the optional header and the characteristics fields are zero for object
  3858.     files */
  3859. }
  3860. static long WriteTextSection(long siz, long nfixups)
  3861. {
  3862.     unsigned char Section[40];
  3863.     unsigned long *pul;
  3864.     unsigned short *pus;
  3865.     unsigned long result;
  3866.     memset(Section, 0, 40);
  3867.     strcpy((char *)Section, ".text");
  3868.     /* Write the virtual size */
  3869.     pul = (unsigned long *) (&Section[8]);
  3870.     /* Write the RVA Offset. Should be zero */
  3871.     /* Write the size of the raw data */
  3872.     pul = (unsigned long *) (&Section[16]);
  3873.     *pul = siz;
  3874.     /* Write a pointer to the raw data position in the file. 0 for now */
  3875.     /* Write a pointer to the location of the relocs. 0 for now */
  3876.     /* Write a pointer to the line numbers. Zero for now */
  3877.     /* Write the number of relocations */
  3878.     pus = (unsigned short *) (&Section[32]);
  3879.     *pus = (unsigned short) nfixups;
  3880.     /* the number of linenumbers is left to zero for now */
  3881.     /* the flags field is left empty */
  3882.     pul = (unsigned long *) (&Section[36]);
  3883.     /* CODE MEM_EXECUTE MEM_READ */
  3884.     *pul = 0x00000020L | 0x20000000L | 0x40000000L;
  3885.     result = ftell(CoffFile);
  3886.     if (40 != fwrite(Section, 1, 40, CoffFile)) {
  3887.         WriteError();
  3888.     }
  3889.     return (result);
  3890. }
  3891. static long WriteDataSection(long siz, long nfixups, int addr)
  3892. {
  3893.     unsigned char Section[40];
  3894.     unsigned long *pul;
  3895.     unsigned short *pus;
  3896.     unsigned long result;
  3897.     memset(Section, 0, 40);
  3898.     strcpy((char *)Section, ".data");
  3899.     /* Write the virtual size */
  3900.     pul = (unsigned long *) (&Section[8]);
  3901.     *pul = CodeSize;
  3902.     /* Write the RVA Offset. */
  3903.     pul = (unsigned long *) (&Section[12]);
  3904.     *pul = addr;
  3905.     /* Write the size of the raw data */
  3906.     pul = (unsigned long *) (&Section[16]);
  3907.     *pul = siz;
  3908.     /* Write a pointer to the raw data position in the file. 0 for now */
  3909.     /* Write a pointer to the location of the relocs. 0 for now */
  3910.     /* Write a pointer to the line numbers. Zero for now */
  3911.     /* Write the number of relocations */
  3912.     pus = (unsigned short *) (&Section[32]);
  3913.     *pus = (unsigned short) nfixups;
  3914.     /* the number of linenumbers is left to zero for now */
  3915.     /* the flags field is left empty */
  3916.     pul = (unsigned long *) (&Section[36]);
  3917.     /* INITIALIZED_DATA MEM_WRITE MEM_READ */
  3918.     *pul = 0x00000040L | 0x80000000L | 0x40000000L;
  3919.     result = ftell(CoffFile);
  3920.     if (40 != fwrite(Section, 1, 40, CoffFile)) {
  3921.         WriteError();
  3922.     }
  3923.     return (result);
  3924. }
  3925. static long WriteDebugSection(int typesFlag)
  3926. {
  3927.     unsigned char Section[40];
  3928.     unsigned long *pul;
  3929.     unsigned long result;
  3930.  
  3931.     memset(Section, 0, 40);
  3932.     if (typesFlag) strcpy((char *)Section,".debug$T");
  3933.     else strcpy((char *)Section, ".debug$S");
  3934.     /* Write the virtual size */
  3935.     /* Write the RVA Offset. */
  3936.     /* Write the size of the raw data */
  3937.     /* Write a pointer to the raw data position in the file. 0 for now */
  3938.     /* Write a pointer to the location of the relocs. 0 for now */
  3939.     /* Write a pointer to the line numbers. Zero for now */
  3940.     /* Write the number of relocations */
  3941.     /* the number of linenumbers is left to zero for now */
  3942.     /* the flags field is left empty */
  3943.     pul = (unsigned long *) (&Section[36]);
  3944.     /* INITIALIZED_DATA MEM_READ MEM_DISCARDABLE ALIGN 1 byte no padding*/
  3945.     *pul = 0x00000040L | 0x40000000L|0x02000000|0x00100000|0x8;
  3946.     result = ftell(CoffFile);
  3947.     if (40 != fwrite(Section, 1, 40, CoffFile)) {
  3948.         WriteError();
  3949.     }
  3950.     return (result);
  3951. }
  3952.  
  3953. static long WriteBssSection(long siz)
  3954. {
  3955.     unsigned char Section[40];
  3956.     unsigned long *pul;
  3957.     unsigned short *pus;
  3958.     unsigned long result;
  3959.     memset(Section, 0, 40);
  3960.     strcpy((char *)Section, ".bss");
  3961.     /* Write the virtual size */
  3962.     pul = (unsigned long *) (&Section[8]);
  3963.     *pul = CodeSize+DataSize;
  3964.     /* Write the RVA Offset. Should be zero */
  3965.     /* Write the size of the raw data */
  3966.     pul = (unsigned long *) (&Section[16]);
  3967.     *pul = siz;
  3968.     /* Write a pointer to the raw data position in the file. 0 for now */
  3969.     /* Write a pointer to the location of the relocs. 0 for now */
  3970.     /* Write a pointer to the line numbers. Zero for now */
  3971.     /* Write the number of relocations */
  3972.     pus = (unsigned short *) (&Section[32]);
  3973.     *pus = (unsigned short) 0;
  3974.     /* the number of linenumbers is left to zero for now */
  3975.     pul = (unsigned long *) (&Section[36]);
  3976.     /* UNINITIALIZED_DATA MEM_WRITE MEM_READ */
  3977.     *pul = 0x00000080L| 0x80000000L | 0x40000000L;
  3978.     result = ftell(CoffFile);
  3979.     if (40 != fwrite(Section, 1, 40, CoffFile)) {
  3980.         WriteError();
  3981.     }
  3982.     return (result);
  3983. }
  3984.  
  3985. static void WriteSpecialSectionHeaders(void)
  3986. {
  3987.     unsigned char Section[40];
  3988.     unsigned long *pul;
  3989.     unsigned short *pus;
  3990.     unsigned long result;
  3991.     NewSection *rvp;
  3992.     int ssectionSize;
  3993.  
  3994.     rvp = SectionList;
  3995.     ssectionSize = 0;
  3996.     while (rvp) {
  3997.         memset(Section, 0, 40);
  3998.         strcpy((char *)Section, rvp->Name);
  3999.         /* Write the virtual size */
  4000.         pul = (unsigned long *) (&Section[8]);
  4001.         *pul = CodeSize+DataSize+local_bss_counter+ssectionSize;
  4002.         /* Write the RVA Offset. Should be zero */
  4003.         /* Write the size of the raw data */
  4004.         pul = (unsigned long *) (&Section[16]);
  4005.         *pul = rvp->DataSize;
  4006.         ssectionSize += rvp->DataSize;
  4007.         /* Write a pointer to the raw data position in the file. 0 for now */
  4008.         /* Write a pointer to the location of the relocs. 0 for now */
  4009.         /* Write a pointer to the line numbers. Zero for now */
  4010.         /* Write the number of relocations */
  4011.         pus = (unsigned short *) (&Section[32]);
  4012.         *pus = (unsigned short) 0;
  4013.         /* the number of linenumbers is left to zero for now */
  4014.         pul = (unsigned long *) (&Section[36]);
  4015.         /* INITIALIZED_DATA MEM_WRITE MEM_READ */
  4016.         /* guess the section flags */
  4017.         if (!strcmp(rvp->Name,".rdata"))
  4018.             /* Initialized data, mem_read */
  4019.             *pul = 0x40000040;
  4020.         else    /* initialized data mem_read mem_write */
  4021.             *pul = 0x00000040L | 0x80000000L | 0x40000000L;
  4022.         result = ftell(CoffFile);
  4023.         if (40 != fwrite(Section, 1, 40, CoffFile)) {
  4024.             WriteError();
  4025.         }
  4026.         rvp->HeaderPosition = result;
  4027.         rvp = rvp->Next;
  4028.     }
  4029. }
  4030.  
  4031. void WriteSpecialSectionData(void)
  4032. {
  4033.     NewSection *rvp;
  4034.     int PosNow;
  4035.  
  4036.     rvp = SectionList;
  4037.     while (rvp) {
  4038.         if (rvp->data) {
  4039.             fseek(CoffFile,0,SEEK_END);
  4040.             PosNow = ftell(CoffFile);
  4041.             fwrite(rvp->data,1,rvp->DataSize,CoffFile);
  4042.             fseek(CoffFile,rvp->HeaderPosition+20,SEEK_SET);
  4043.             fwrite(&PosNow, 1, 4, CoffFile);
  4044.         }
  4045.         rvp = rvp->Next;
  4046.     }
  4047.     fseek(CoffFile,0,SEEK_END);
  4048. }
  4049.  
  4050. static int ArrangeDataSection(int ordinal)
  4051. {
  4052.     symbolS *coffS;
  4053.     symbolS *symbolP;
  4054.  
  4055.     symbolP = symbol_table_lookup(".data");
  4056.     symbolP->OrdinalNumber = ordinal;
  4057.     ordinal++;
  4058.     ordinal++;          /* count the auxiliary symbol */
  4059.     symbolP->Flags |= COUNTED;
  4060.     symbolP = symbol_table_lookup(".bss");
  4061.     symbolP->Flags |= COUNTED;
  4062.     coffS = symbol_rootP;
  4063.     while (coffS) {
  4064.         if ((coffS->Flags & COUNTED) == 0) {
  4065.             if (coffS->Flags & IS_DATA) {
  4066.                 coffS->OrdinalNumber = ordinal;
  4067.                 ordinal++;
  4068.                 coffS->Flags |= COUNTED;
  4069.             }
  4070.         }
  4071.         coffS = coffS->Next;
  4072.     }
  4073.     symbolP = symbol_table_lookup(".bss");
  4074.     symbolP->OrdinalNumber = ordinal;
  4075.     symbolP->Flags |= COUNTED;
  4076.     ordinal++;
  4077.     ordinal++;
  4078.     coffS = symbol_rootP;
  4079.     while (coffS) {
  4080.         if ((coffS->Flags & COUNTED) == 0) {
  4081.             if (coffS->Flags & IS_BSS) {
  4082.                 coffS->OrdinalNumber = ordinal;
  4083.                 ordinal++;
  4084.                 coffS->Flags |= COUNTED;
  4085.             }
  4086.         }
  4087.         coffS = coffS->Next;
  4088.     }
  4089.     symbolP = symbol_table_lookup(".text");
  4090.     symbolP->Flags |= COUNTED;
  4091.     symbolP->OrdinalNumber = ordinal;
  4092.     ordinal++;
  4093.     ordinal++;
  4094.     return (ordinal);
  4095. }
  4096. static int ArrangeOrdinalNumbers(char *name)
  4097. {
  4098.     int ordinal,len;
  4099.     symbolS *coffS,*lastS;
  4100.  
  4101.     len = strlen(name);
  4102.     ordinal = (len / 18);
  4103.     if (len % 18) ordinal++;
  4104.     ordinal++;
  4105.     ordinal = ArrangeDataSection(ordinal);
  4106.     coffS = symbol_rootP;
  4107.     lastS = NULL;
  4108.     while (coffS) {
  4109.         if ((coffS->Flags & COUNTED) == 0) {
  4110.             coffS->OrdinalNumber = ordinal;
  4111.             ordinal++;
  4112.             if (glevel && coffS->Flags & IS_FUNCTION) {   /* Function */
  4113.                 if (lastS) {
  4114.                     lastS->FnInfo->NextFnIdx = coffS->OrdinalNumber;
  4115.                 }
  4116.                 lastS = coffS;
  4117.                 ordinal++;  /* count the auxiliary symbol */
  4118.                 coffS->NumberOfAuxSymbols = 1;
  4119.                 ordinal += 3;   /* count the .bf .lf and .ef records */
  4120.                 ordinal += 2;   /* .bf and .ef have aux. symbols */
  4121.             }
  4122.             else {
  4123.                 if (coffS->NumberOfAuxSymbols)
  4124.                     ordinal++;
  4125.             }
  4126.         }
  4127.         coffS = coffS->Next;
  4128.     }
  4129.     coffS = symbol_rootP;
  4130.     while (coffS) {
  4131.         coffS->Flags &= ~COUNTED;
  4132.         coffS = coffS->Next;
  4133.     }
  4134.     return (ordinal);
  4135. }
  4136. static int SortFun(const void *f1, const void *f2)
  4137. {
  4138.     COFF_RELOC *s1, *s2;
  4139.     s1 = *(COFF_RELOC **) f1;
  4140.     s2 = *(COFF_RELOC **) f2;
  4141.     if (s1->Offset > s2->Offset)
  4142.         return (1);
  4143.     else if (s1->Offset < s2->Offset)
  4144.         return (-1);
  4145.     else
  4146.         return (0);
  4147. }
  4148. static int WriteRelocations(int which)
  4149. {
  4150.     symbolS *coffS;
  4151.     int count, ordinal, i;
  4152.     char reloc[10];
  4153.     unsigned long *pul;
  4154.     unsigned short *pus;
  4155.     COFF_RELOC *rvp, **table;
  4156.     fixS *fixP;
  4157.  
  4158.     coffS = symbol_rootP;
  4159.     count = 0;
  4160.     while (coffS) {
  4161.         rvp = coffS->Relocations;
  4162.         while (rvp) {
  4163.             fixP = rvp->pfixS;
  4164.             if (coffS->Flags & (IS_DATA | IS_BSS))
  4165.                 rvp->Offset = fixP->fx_frag->fr_address + fixP->fx_where;
  4166.             if (rvp->TargetSegment & which)
  4167.                 count++;
  4168.             rvp = rvp->Next;
  4169.         }
  4170.         coffS = coffS->Next;
  4171.     }
  4172.     table = (COFF_RELOC **) xmalloc(sizeof(COFF_RELOC *) * count);
  4173.     coffS = symbol_rootP;
  4174.     count = 0;
  4175.     while (coffS) {
  4176.         rvp = coffS->Relocations;
  4177.         while (rvp) {
  4178.             if (rvp->TargetSegment & which) {
  4179.                 table[count++] = rvp;
  4180.             }
  4181.             rvp = rvp->Next;
  4182.         }
  4183.         coffS = coffS->Next;
  4184.     }
  4185.     qsort(table, count, sizeof(COFF_RELOC *), SortFun);
  4186.     for (i = 0; i < count; i++) {
  4187.         memset(reloc, 0, 10);
  4188.         coffS = table[i]->Symbol;
  4189.         if (table[i]->TargetSegment & which) {
  4190.             pul = (unsigned long *) reloc;
  4191.             *pul++ = table[i]->Offset;
  4192.             ordinal = coffS->OrdinalNumber;
  4193.             *pul++ = ordinal;
  4194.             pus = (unsigned short *) pul;
  4195.             if (table[i]->TargetSegment & IS_DATA)
  4196.                 *pus = 0x6;
  4197.             else
  4198.                 *pus = table[i]->Type;
  4199.             if (10 != fwrite(reloc, 1, 10, CoffFile)) {
  4200.                 WriteError();
  4201.             }
  4202.         }
  4203.     }
  4204.     free(table);
  4205.     return (count);
  4206. }
  4207.  
  4208. static STRING *NewString(char *s, int len)
  4209. {
  4210.     STRING *result;
  4211.  
  4212.     result = (STRING *) xmalloc(sizeof(STRING));
  4213.     result->len = len;
  4214.     result->String = xmalloc(len);
  4215.     strcpy(result->String, s);
  4216.     return (result);
  4217. }
  4218. static int AddStringToStringTable(char *str)
  4219. {
  4220.     STRING *s;
  4221.     int len, pos;
  4222.     if (StringTable == NULL) {
  4223.         StringTable = (STRING_TABLE *) xmalloc(sizeof(STRING_TABLE));
  4224.     }
  4225.     s = StringTable->Strings;
  4226.     len = strlen(str) + 1;
  4227.     pos = 4;
  4228.     while (s && s->Next) {
  4229.         if (s->len == len && !strcmp(str, s->String)) {
  4230.             return (pos);
  4231.         }
  4232.         pos += s->len;
  4233.         s = s->Next;
  4234.     }
  4235.     if (s == NULL) {
  4236.         s = NewString(str, len);
  4237.         StringTable->Strings = s;
  4238.         StringTable->Size = len;
  4239.     }
  4240.     else {
  4241.         pos += s->len;
  4242.         s->Next = NewString(str, len);
  4243.         StringTable->Size += len;
  4244.     }
  4245.     return (pos);
  4246. }
  4247. static long WriteStringTable(void)
  4248. {
  4249.     long pos, total;
  4250.     STRING *s;
  4251.     pos = ftell(CoffFile);
  4252.     /* Contrary to the documentation of microsoft the length of the string
  4253.     table header IS included in the total length of the string table. */
  4254.     total = 4;
  4255.     fwrite(&total, 1, 4, CoffFile);
  4256.     if (StringTable == NULL)
  4257.         return (pos + 4);
  4258.     s = StringTable->Strings;
  4259.     while (s) {
  4260.         if (s->len != (int) fwrite(s->String, 1, s->len, CoffFile)) {
  4261.             WriteError();
  4262.         }
  4263.         total += s->len;
  4264.         s = s->Next;
  4265.     }
  4266.     fseek(CoffFile, pos, SEEK_SET);
  4267.     fwrite(&total, 1, 4, CoffFile);
  4268.     fseek(CoffFile, 0, SEEK_END);
  4269.     return (pos);
  4270. }
  4271.  
  4272. void WriteFunctionsDebugRelocations(int *offsets,symbolS **table,int n)
  4273. {
  4274.     unsigned char reloc[10],*p;
  4275.     int i,relocPos;
  4276.  
  4277.     relocPos = ftell(CoffFile);
  4278.     for (i=0; i<n;i++) {
  4279.         memset(reloc,0,10);
  4280.         p = reloc;
  4281.         *(unsigned long *)p = offsets[i];
  4282.         p += sizeof(int);
  4283.         *(unsigned long *)p = table[i]->OrdinalNumber;
  4284.         p += sizeof(int);
  4285.         *(unsigned short *)p = 0xB;
  4286.         fwrite(reloc,1,10,CoffFile);
  4287.         *(unsigned short *)p = 0xA;
  4288.         p = reloc;
  4289.         *(unsigned long *)p = 4 + offsets[i];
  4290.         fwrite(reloc,1,10,CoffFile);
  4291.     }
  4292.     fseek(CoffFile,PosDebugSymbolsSection+24,SEEK_SET);
  4293.     fwrite(&relocPos,1,4,CoffFile);
  4294.     fseek(CoffFile,PosDebugSymbolsSection+32,SEEK_SET);
  4295.     n = n + n;
  4296.     fwrite(&n,1,4,CoffFile);
  4297.     fseek(CoffFile,0,SEEK_END);
  4298. }
  4299. static int GetDebugDataSymbolsLength(int *n)
  4300. {
  4301.     DataList *rvp;
  4302.     int result,c;
  4303.  
  4304.     rvp = DataSymbolsInfo;
  4305.     result = 0;
  4306.     *n = 0;
  4307.     c = 0;
  4308.     while (rvp) {
  4309.         if (symbol_table_lookup(rvp->Name)) {
  4310.             result += rvp->len;
  4311.             c++;
  4312.         }
  4313.         rvp = rvp->Next;
  4314.     }
  4315.     *n = c;
  4316.     return(result);
  4317. }
  4318.  
  4319. static char *PutDebugDataSymbols(char *where,int *offsets,symbolS **table,int start,int startoffset)
  4320. {
  4321.     char *p = where;
  4322.     DataList *rvp;
  4323.  
  4324.     rvp = DataSymbolsInfo;
  4325.     while (rvp) {
  4326.         table[start] = symbol_table_lookup(rvp->Name);
  4327.         if (table[start] != NULL) {
  4328.             memcpy(p,rvp->data,rvp->len);
  4329.             offsets[start] = (p - where) + 4 + startoffset;
  4330.             start++;
  4331.             p += rvp->len;
  4332.         }
  4333.         rvp = rvp->Next;
  4334.     }
  4335.     return(p);
  4336. }
  4337. void WriteDebugTypes(void)
  4338. {
  4339.     int len;
  4340.     unsigned char *data,*p;
  4341.     int pos;
  4342.     DataList *dl;
  4343.  
  4344.     dl = DataTypesInfo;
  4345.     len = 0;
  4346.     while (dl) {
  4347.         len += dl->len;
  4348.         dl = dl->Next;
  4349.     }
  4350.     len += 4;
  4351.     data = (unsigned char *)xmalloc(len);
  4352.     p = data;
  4353.     *(unsigned long *)p = 1;
  4354.     p += 4;
  4355.     dl = DataTypesInfo;
  4356.     while (dl) {
  4357.         memcpy(p,dl->data,dl->len);
  4358.         p += dl->len;
  4359.         dl = dl->Next;
  4360.     }
  4361.     pos = ftell(CoffFile);
  4362.     fwrite(data,1,len,CoffFile);
  4363.     fseek(CoffFile,PosDebugTypesSection+16,SEEK_SET);
  4364.     fwrite(&len,1,4,CoffFile);
  4365.     fwrite(&pos,1,4,CoffFile);
  4366.     /* Fix the data size in the .debug$T symbol */
  4367.     fseek(CoffFile,PosDebugTSpecialSymbol,SEEK_SET);
  4368.     fwrite(&len,1,4,CoffFile);
  4369.     fseek(CoffFile,0,SEEK_END);
  4370.     free(data);
  4371. }
  4372.  
  4373. static char *wccSignature = "Logiciels/Informatique lcc-win32 version 1.1";
  4374. void WriteDebugData(void)
  4375. {
  4376.     int len=0,nameLen,debugdataPos,proclen,nrOfFunctions,*relocAddr;
  4377.     unsigned short nrOfRelocations;
  4378.     int dataSymbolsLen,nrOfDataSymbols;
  4379.     int objNameRecordLen;
  4380.     ProcList *pl;
  4381.     char *data,*p,*n;
  4382.     symbolS *coffS,**table;
  4383.  
  4384.     pl = ProceduresList;
  4385.     nrOfFunctions = 0;
  4386.     while (pl) {
  4387.         len += pl->len + sizeof(struct procInfo)+2+2;
  4388.         len -= 4;
  4389.         len += strlen(pl->procInfo.u.Name)+1;
  4390.         pl = pl->Next;
  4391.         nrOfFunctions++;
  4392.     }
  4393.     len += 4; /* 1 signature as a long */
  4394.     /* Count the length of the object record name */
  4395.     p = strrchr(OutputFileName,'\\');
  4396.     if (p) p++;
  4397.     else p = OutputFileName;
  4398.     nameLen = strlen(p);
  4399.     n = p;
  4400.     objNameRecordLen = nameLen + 1 + 2 + 2 + 4;
  4401.     len += objNameRecordLen;
  4402.     /* Add the block end record for each function */
  4403.     len += 4 * nrOfFunctions;
  4404.     /* add the compiler info */
  4405.     len += 8 + strlen(wccSignature)+1;
  4406.  
  4407.     dataSymbolsLen = GetDebugDataSymbolsLength(&nrOfDataSymbols);
  4408.     len += dataSymbolsLen;
  4409.     data = xmalloc(len);
  4410.     relocAddr = (int *)xmalloc(sizeof(int)*(nrOfFunctions+nrOfDataSymbols));
  4411.     table = (symbolS **)xmalloc(sizeof(symbolS *)*(nrOfFunctions+nrOfDataSymbols));
  4412.     *(unsigned long *)data = 1;
  4413.     p = data + 4;
  4414.     *(unsigned short *)p = objNameRecordLen - 2;
  4415.     p += 2;
  4416.     *(unsigned short *)p = 0x9;
  4417.     p += 2;
  4418.     *(unsigned long *)p = 0;
  4419.     p += 4;
  4420.     *p++ = nameLen;
  4421.     while (*n) {
  4422.         *p++ = *n++;
  4423.     }
  4424.     pl = ProceduresList;
  4425.     nrOfFunctions = 0;
  4426.     while (pl) {
  4427.         proclen = 2 + sizeof(struct procInfo)-4;
  4428.         n = pl->procInfo.u.Name;
  4429.         nameLen = strlen(n);
  4430.         proclen += nameLen +1;
  4431.         *(unsigned short *)p = proclen;
  4432.         p += 2;
  4433.         if (pl->Sym->sclass == STATIC) {
  4434.             *(unsigned short *)p = 0x204; /* Local procedure */
  4435.         }
  4436.         else
  4437.             *(unsigned short *)p = 0x205; /* Global procedure */
  4438.  
  4439.         p += 2;
  4440.         coffS = symbol_table_lookup(n);
  4441.         assert(coffS->FnInfo);
  4442.         pl->procInfo.procLength = coffS->FnInfo->End->SymbolValue - coffS->FnInfo->Start->SymbolValue;
  4443.         pl->procInfo.debugStart = pl->Sym->x.PrologueEnd;
  4444.         if (pl->procInfo.procLength > 4)
  4445.             pl->procInfo.debugEnd = pl->procInfo.procLength - 5;
  4446.         else
  4447.             pl->procInfo.debugEnd = pl->procInfo.debugStart;
  4448.         memcpy(p,&pl->procInfo,sizeof(struct procInfo)-4);
  4449.         table[nrOfFunctions] = coffS;
  4450.         relocAddr[nrOfFunctions] = (p - data) + 24;
  4451.         p += sizeof(struct procInfo) - 4;
  4452.         p = PutLengthPrefixedName(p,n);
  4453.         memcpy(p,pl->data,pl->len);
  4454.         p += pl->len;
  4455.         *(unsigned short *)p = 2;
  4456.         p += 2;
  4457.         *(unsigned short *)p = 0x06; /* S_END */
  4458.         p += 2;
  4459.         pl = pl->Next;
  4460.         nrOfFunctions++;
  4461.     }
  4462.     p = PutDebugDataSymbols(p,relocAddr,table,nrOfFunctions,p - data);
  4463.     *(unsigned short *)p = 8 + strlen(wccSignature) + 1 - 2;
  4464.     p += 2;
  4465.     *(unsigned short *)p = 0x1; /* S_COMPILE */
  4466.     p += 2;
  4467.     *p++ = 4; /* Processor 80486 for now */
  4468.     p += 3; /* Flags empty for now */
  4469.     p = PutLengthPrefixedName(p,wccSignature);
  4470.     debugdataPos = ftell(CoffFile);
  4471.     fwrite(data,1,len,CoffFile);
  4472.     fseek(CoffFile,PosDebugSymbolsSection+16,SEEK_SET);
  4473.     fwrite(&len,1,4,CoffFile);
  4474.     fwrite(&debugdataPos,1,4,CoffFile);
  4475.     fseek(CoffFile,0,SEEK_END);
  4476.     nrOfRelocations = nrOfFunctions+nrOfDataSymbols;
  4477.     WriteFunctionsDebugRelocations(relocAddr,table,nrOfRelocations);
  4478.     /* Fix the .debug$S special symbol */
  4479.     fseek(CoffFile,PosDebugSSpecialSymbol,SEEK_SET);
  4480.     fwrite(&len,1,4,CoffFile);
  4481.     nrOfRelocations *= 2;
  4482.     fwrite(&nrOfRelocations,1,2,CoffFile);
  4483.     fseek(CoffFile,0,SEEK_END);
  4484.     WriteDebugTypes();
  4485.     free(data);
  4486.     free(relocAddr);
  4487. }
  4488.  
  4489.  
  4490. static int SortSymbols(const void *f1, const void *f2)
  4491. {
  4492.     symbolS *s1, *s2;
  4493.     s1 = *(symbolS **) f1;
  4494.     s2 = *(symbolS **) f2;
  4495.     if (s1->SymbolValue > s2->SymbolValue)
  4496.         return (1);
  4497.     else if (s1->SymbolValue < s2->SymbolValue)
  4498.         return (-1);
  4499.     else
  4500.         return (0);
  4501. }
  4502. static int WriteLineNumbers(int PosCodeSection)
  4503. {
  4504.     symbolS *coffS, **coffSTable;
  4505.     unsigned long *pul;
  4506.     unsigned short *pus;
  4507.     int count, functions, size, totalCount, i;
  4508.     long pos;
  4509.     unsigned short LineNumbers;
  4510.     char *table, *p;
  4511.     unsigned short Short;
  4512.     COFF_LINE *coffL;
  4513.  
  4514.     coffS = symbol_rootP;
  4515.     count = 0;
  4516.     functions = 0;
  4517.     while (coffS) {
  4518.         if ((coffS->Flags & IS_FUNCTION) && coffS->Lines) {
  4519.             functions++;
  4520.             coffL = coffS->Lines;
  4521.             while (coffL) {
  4522.                 count++;
  4523.                 coffL = coffL->Next;
  4524.             }
  4525.         }
  4526.         coffS = coffS->Next;
  4527.     }
  4528.     if (functions == 0) return(0);
  4529.     coffSTable = (symbolS **) xmalloc(functions * sizeof(symbolS *));
  4530.     coffS = symbol_rootP;
  4531.     i = 0;
  4532.     while (coffS) {
  4533.         if ((coffS->Flags & IS_FUNCTION) && coffS->Lines) {
  4534.             coffSTable[i++] = coffS;
  4535.         }
  4536.         coffS = coffS->Next;
  4537.     }
  4538.     qsort(coffSTable, functions, sizeof(symbolS *), SortSymbols);
  4539.     pos = ftell(CoffFile);
  4540.     size = 6 * (functions + count);
  4541.     totalCount = functions + count;
  4542.     table = xmalloc(size);
  4543.     p = table;
  4544.     coffS = symbol_rootP;
  4545.     LineNumbers = 0;
  4546.     for (i = 0; i < functions; i++) {
  4547.         coffS = coffSTable[i];
  4548.         if ((coffS->Flags & IS_FUNCTION) && coffS->Lines) {
  4549.             pul = (unsigned long *) p;
  4550.             *pul = coffS->OrdinalNumber;
  4551.             pus = (unsigned short *) (&p[4]);
  4552.             *pus = 0;
  4553.             coffL = coffS->Lines;
  4554.             if (coffS->FnInfo)
  4555.                 coffS->FnInfo->LineNumbersFileOffset = pos + (p - table);
  4556.             else
  4557.                 InternalError(1113);
  4558.             p += 6;
  4559.             LineNumbers++;
  4560.             while (coffL) {
  4561.                 pul = (unsigned long *) p;
  4562.                 *pul = coffL->Frag->fr_address + coffL->fragOffset;
  4563.                 pus = (unsigned short *) (&p[4]);
  4564.                 *pus = (unsigned short)coffL->Line;
  4565.                 p += 6;
  4566.                 LineNumbers++;
  4567.                 coffL = coffL->Next;
  4568.             }
  4569.         }
  4570.     }
  4571.     if (size != (int) fwrite(table, 1, size, CoffFile)) {
  4572.         WriteError();
  4573.     }
  4574.     free(table);
  4575.     free(coffSTable);
  4576.     fseek(CoffFile, PosCodeSection + 28, SEEK_SET);
  4577.     fwrite(&pos, 1, 4, CoffFile);
  4578.     fseek(CoffFile, PosCodeSection + 34, SEEK_SET);
  4579.     Short = (unsigned short) LineNumbers;
  4580.     fwrite(&Short, 1, 2, CoffFile);
  4581.  
  4582.     if (glevel > 1) {
  4583.         fseek(CoffFile,PosDebugSymbolsSection + 28,SEEK_SET);
  4584.         fwrite(&pos, 1, 4, CoffFile);
  4585.         fseek(CoffFile, PosDebugSymbolsSection + 34, SEEK_SET);
  4586.         fwrite(&Short,1,2,CoffFile);
  4587.     }
  4588.     fseek(CoffFile, 0, SEEK_END);
  4589.     return (totalCount);
  4590. }
  4591. static int WriteOneSymbol(char *p)
  4592. {
  4593.     if (18 != (int) fwrite(p, 1, 18, CoffFile)) {
  4594.         WriteError();
  4595.     }
  4596.     return (1);
  4597. }
  4598. static int WriteFunctionRecords(symbolS * coffS)
  4599. {
  4600.     char AuxSymbol[18];
  4601.     unsigned long *pul;
  4602.     unsigned short *pus;
  4603.     int size, count;
  4604.     symbolS *start, *end;
  4605.     COFF_LINE *rvpCL;
  4606.  
  4607.     /* 1. Write the auxiliary symbol for the function */
  4608.     memset(AuxSymbol, 0, 18);
  4609.     /* 1.A Tag index */
  4610.     pul = (unsigned long *) AuxSymbol;
  4611.     *pul++ = coffS->FnInfo->Tag;
  4612.     start = coffS->FnInfo->Start;
  4613.     end = coffS->FnInfo->End;
  4614.     size = 0;
  4615.     if (start && end) {
  4616.         size = end->SymbolValue - start->SymbolValue;
  4617.     }
  4618.     *pul++ = size;
  4619.     /* 1.B write the linenumbers record. */
  4620.     if (coffS->FnInfo)
  4621.         *pul++ = coffS->FnInfo->LineNumbersFileOffset;
  4622.     else
  4623.         *pul++ = 0;
  4624.     /* 1.C Write the pointer to the next function */
  4625.     *pul = coffS->FnInfo->NextFnIdx;
  4626.     WriteOneSymbol(AuxSymbol);
  4627.     /* Write the .bf record */
  4628.     memset(AuxSymbol, 0, 18);
  4629.     strcpy(AuxSymbol, ".bf");
  4630.     pul = (unsigned long *) (&AuxSymbol[8]);
  4631.     *pul = coffS->SymbolValue;
  4632.     pus = (unsigned short *) (&AuxSymbol[12]);
  4633.     *pus = SECTION_TEXT;
  4634.     pus = (unsigned short *) (&AuxSymbol[14]);
  4635.     *pus++ = 0;         /* function */
  4636.     *pus = 101;
  4637.     AuxSymbol[17] = 1;
  4638.     WriteOneSymbol(AuxSymbol);
  4639.     /* Write the auxiliary record for the .bf symbol */
  4640.     memset(AuxSymbol, 0, 18);
  4641.     /* Write the linenumbers */
  4642.     pus = (unsigned short *) (&AuxSymbol[4]);
  4643.     *pus = (unsigned short)coffS->StartLine;
  4644.     pul = (unsigned long *) (&AuxSymbol[12]);
  4645.     *pul = coffS->FnInfo->NextFnIdx;
  4646.     WriteOneSymbol(AuxSymbol);
  4647.     /* Write the .lf record */
  4648.     memset(AuxSymbol, 0, 18);
  4649.     strcpy(AuxSymbol, ".lf");
  4650.     pul = (unsigned long *) (&AuxSymbol[8]);
  4651.     rvpCL = coffS->Lines;
  4652.     count = 0;
  4653.     while (rvpCL) {
  4654.         count++;
  4655.         rvpCL = rvpCL->Next;
  4656.     }
  4657.     *pul = count + 1;
  4658.     pus = (unsigned short *) (&AuxSymbol[12]);
  4659.     *pus = SECTION_TEXT;
  4660.     pus = (unsigned short *) (&AuxSymbol[14]);
  4661.     *pus++ = 0x0;
  4662.     *pus = 101;
  4663.     WriteOneSymbol(AuxSymbol);
  4664.     /* Write .ef record */
  4665.     memset(AuxSymbol, 0, 18);
  4666.     strcpy(AuxSymbol, ".ef");
  4667.     pul = (unsigned long *) (&AuxSymbol[8]);
  4668.     *pul = coffS->SymbolValue + size;
  4669.     pus = (unsigned short *) (&AuxSymbol[12]);
  4670.     *pus = SECTION_TEXT;
  4671.     pus = (unsigned short *) (&AuxSymbol[14]);
  4672.     *pus++ = 0;
  4673.     *pus = 101;
  4674.     AuxSymbol[17] = 1;
  4675.     WriteOneSymbol(AuxSymbol);
  4676.     /* Write the auxiliary record for the .ef symbol */
  4677.     memset(AuxSymbol, 0, 18);
  4678.     /* Write the linenumbers */
  4679.     pus = (unsigned short *) (&AuxSymbol[4]);
  4680.     *pus = (unsigned short)coffS->EndLine;
  4681.     return (WriteOneSymbol(AuxSymbol));
  4682. }
  4683. static int SymbolToChars(symbolS * coffS)
  4684. {
  4685.     char Symbol[18];
  4686.     unsigned long *pul, Pos;
  4687.     unsigned short *pus;
  4688.     unsigned char *puc;
  4689.     char *temp;
  4690.  
  4691.     memset(Symbol, 0, 18);
  4692.     temp = coffS->Name;
  4693.     if (strlen(temp) > 8) {
  4694.         Pos = AddStringToStringTable(temp);
  4695.         pul = (unsigned long *) (&Symbol[4]);
  4696.         *pul = Pos;
  4697.     }
  4698.     else {
  4699.         strncpy(Symbol, temp, 8);
  4700.     }
  4701.     /* Write the value */
  4702.     pul = (unsigned long *) (&Symbol[8]);
  4703.     *pul = coffS->SymbolValue;
  4704.     /* Write the section One based index */
  4705.     pus = (unsigned short *) (&Symbol[12]);
  4706.     *pus = (unsigned short)coffS->SectionNumber;
  4707.     /* Write the type */
  4708.     pus = (unsigned short *) (&Symbol[14]);
  4709.     *pus = (unsigned short)coffS->Type; /* static */
  4710.     /* Write the storage class */
  4711.     puc = (unsigned char *) (&Symbol[16]);
  4712.     *puc = (unsigned char)coffS->StorageClass;
  4713.     puc = (unsigned char *) (&Symbol[17]);
  4714.     *puc = (unsigned char)coffS->NumberOfAuxSymbols;
  4715.     return (WriteOneSymbol(Symbol));
  4716. }
  4717. static int WriteDataSymbols(int count)
  4718. {
  4719.     symbolS *coffS,*sdata,*sbss;
  4720.     char AuxSymbol[18];
  4721.     unsigned long *pul;
  4722.  
  4723.     sdata = symbol_table_lookup(".data");
  4724.     sbss = symbol_table_lookup(".bss");
  4725.     coffS = symbol_rootP;
  4726.     while (coffS) {
  4727.         if (coffS->Flags & IS_DATA) {
  4728.             if (coffS != sdata) {
  4729.                 if (coffS != sbss) {
  4730.                     if (coffS->Flags & (IS_TEXT|IS_BSS)) {
  4731.                         fprintf(stderr,"Symbol %s has all flags\n",coffS->Name);
  4732.                         coffS->Flags &= ~(IS_TEXT|IS_BSS);
  4733.                     }
  4734.                     SymbolToChars(coffS);
  4735.                     count++;
  4736.                 }
  4737.             }
  4738.         }
  4739.         coffS = coffS->Next;
  4740.     }
  4741.     SymbolToChars(symbol_table_lookup(".bss"));
  4742.     memset(AuxSymbol, 0, 18);
  4743.     pul = (unsigned long *) AuxSymbol;
  4744.     *pul = local_bss_counter;
  4745.     WriteOneSymbol(AuxSymbol);
  4746.     count += 2;
  4747.     coffS = symbol_rootP;
  4748.     while (coffS) {
  4749.         if (coffS->Flags & IS_BSS) {
  4750.             if (coffS != sdata) {
  4751.                 if (coffS != sbss) {
  4752.                     if (coffS->Flags & (IS_TEXT|IS_DATA)) {
  4753.                         fprintf(stderr,"Symbol %s has all flags\n",coffS->Name);
  4754.                         coffS->Flags &= ~(IS_TEXT|IS_DATA);
  4755.                     }
  4756.                     SymbolToChars(coffS);
  4757.                     count++;
  4758.                 }
  4759.             }
  4760.         }
  4761.         coffS = coffS->Next;
  4762.     }
  4763.  
  4764.     return (count);
  4765. }
  4766. static int WriteSpecialSymbols(int result)
  4767. {
  4768.     symbolS *coffS;
  4769.     char AuxSymbol[18];
  4770.     unsigned long *pul;
  4771.     unsigned short *pus;
  4772.  
  4773.     /* Write the special ".data" symbol */
  4774.     SymbolToChars(symbol_table_lookup(".data"));
  4775.     memset(AuxSymbol, 0, 18);
  4776.     pul = (unsigned long *) AuxSymbol;
  4777.     *pul = DataSize;
  4778.     pus = (unsigned short *) (&AuxSymbol[4]);
  4779.     *pus = (unsigned short)NrOfDataFixups;
  4780.     pus = (unsigned short *) (&AuxSymbol[6]);
  4781.     *pus = 0;
  4782.     pus = (unsigned short *) (&AuxSymbol[12]);
  4783.     /* The section number should be zero. If it is not, the line numbers
  4784.     will not be recognized. Please, do not ask why is this so */
  4785.     *pus = 0;
  4786.     WriteOneSymbol(AuxSymbol);
  4787.     result = WriteDataSymbols(result + 2);
  4788.  
  4789.     /* Write the special ".text" symbol */
  4790.     coffS = symbol_table_lookup(".text");
  4791.     SymbolToChars(coffS);
  4792.     memset(AuxSymbol, 0, 18);
  4793.     pul = (unsigned long *) AuxSymbol;
  4794.     *pul = CodeSize;
  4795.     pus = (unsigned short *) (&AuxSymbol[4]);
  4796.     *pus = (unsigned short)NrOfTextFixups;
  4797.     pus = (unsigned short *) (&AuxSymbol[6]);
  4798.     *pus = (unsigned short)NrOfLineNumbers;
  4799.     pus = (unsigned short *) (&AuxSymbol[12]);
  4800.     *pus = 0;
  4801.     WriteOneSymbol(AuxSymbol);
  4802.     result += 2;
  4803.     return (result);
  4804. }
  4805. static int WriteDebugSpecialSymbols(int result)
  4806. {
  4807.     symbolS coffS;
  4808.     char AuxSymbol[18];
  4809.  
  4810.     if (glevel < 2) return(0);
  4811.     memset(&coffS,0,sizeof(coffS));
  4812.     coffS.Name = ".debug$S";
  4813.     coffS.SectionNumber = NumberOfSpecialSections + 4;
  4814.     coffS.OrdinalNumber = result++;
  4815.     coffS.NumberOfAuxSymbols = 1;
  4816.     coffS.StorageClass = 3;
  4817.     /* Write the special ".debug$S" symbol */
  4818.     SymbolToChars(&coffS);
  4819.     PosDebugSSpecialSymbol = ftell(CoffFile);
  4820.     memset(AuxSymbol, 0, 18);
  4821.     WriteOneSymbol(AuxSymbol);
  4822.     result++;
  4823.     /* Write the special ".debug$T" symbol */
  4824.     memset(&coffS,0,sizeof(coffS));
  4825.     coffS.Name = ".debug$T";
  4826.     coffS.SectionNumber = NumberOfSpecialSections + 5;
  4827.     coffS.OrdinalNumber = result++;
  4828.     coffS.NumberOfAuxSymbols = 1;
  4829.     coffS.StorageClass = 3;
  4830.     SymbolToChars(&coffS);
  4831.     PosDebugTSpecialSymbol = ftell(CoffFile);
  4832.     memset(AuxSymbol, 0, 18);
  4833.     WriteOneSymbol(AuxSymbol);
  4834.     result++;
  4835.     return (4);
  4836. }
  4837. static int WriteSpecialSectionSymbols(int startCount)
  4838. {
  4839.     symbolS coffS;
  4840.     char AuxSymbol[18];
  4841.     int symbolsWritten = 0;
  4842.     NewSection *rvp;
  4843.  
  4844.     rvp = SectionList;
  4845.     while (rvp) {
  4846.         memset(&coffS,0,sizeof(coffS));
  4847.         coffS.Name = rvp->Name;
  4848.         coffS.SectionNumber = rvp->Number;
  4849.         coffS.OrdinalNumber = startCount++;
  4850.         coffS.NumberOfAuxSymbols = 1;
  4851.         coffS.StorageClass = 3;
  4852.         SymbolToChars(&coffS);
  4853.         symbolsWritten++;
  4854.         memset(AuxSymbol, 0, 18);
  4855.         *(unsigned long *)AuxSymbol = rvp->DataSize;
  4856.         WriteOneSymbol(AuxSymbol);
  4857.         symbolsWritten++;
  4858.         startCount++;
  4859.         rvp = rvp->Next;
  4860.     }
  4861.     return (symbolsWritten);
  4862. }
  4863. static int WriteAllCoffSymbols(int startCount)
  4864. {
  4865.     symbolS *coffS;
  4866.     int count;
  4867.  
  4868.     count = startCount;
  4869.     count = WriteSpecialSymbols(count);
  4870.     coffS = symbol_rootP;
  4871.     while (coffS) {
  4872.         if (coffS->Flags & IS_TEXT) {
  4873.             if (strncmp(coffS->Name, ".text", 5)) {
  4874.                 SymbolToChars(coffS);
  4875.                 count++;
  4876.             }
  4877.         }
  4878.         if (glevel && coffS->Flags & IS_FUNCTION) {
  4879.             coffS->FnInfo->Tag = count + 1;
  4880.             WriteFunctionRecords(coffS);
  4881.             count += 6;
  4882.         }
  4883.         coffS = coffS->Next;
  4884.     }
  4885.     count += WriteDebugSpecialSymbols(count);
  4886.     count += WriteSpecialSectionSymbols(count);
  4887.     return (count);
  4888. }
  4889. static int WriteFileName(char *name)
  4890. {
  4891.     char Symbol[18], AuxSymbol[18];
  4892.     unsigned short *pus;
  4893.     int AuxSym, i, len, j,c;
  4894.  
  4895.     memset(Symbol, 0, 18);
  4896.     strcpy(Symbol, ".file");
  4897.     /* Write the section */
  4898.     pus = (unsigned short *) (&Symbol[12]);
  4899.     *pus = (unsigned short) -2; /* used for .file symbols */
  4900.     /* Write the storage class (103) */
  4901.     pus = (unsigned short *) (&Symbol[16]);
  4902.     *pus = 103;
  4903.     /* Write the number of auxiliary symbols */
  4904.     len = strlen(name);
  4905.     AuxSym = (len / 18);
  4906.     if (len % 18) AuxSym++;
  4907.     Symbol[17] = (char)AuxSym;
  4908.     if (18 != fwrite(Symbol, 1, 18, CoffFile)) {
  4909.         WriteError();
  4910.     }
  4911.     i = 0;
  4912.     while (i < len) {
  4913.         memset(AuxSymbol, 0, 18);
  4914.         for (j = 0; j < 18; j++) {
  4915.             if (i < len) {
  4916.                 c = name[i];
  4917.                 if (c >= 'a' && c <= 'z') c -= ' ';
  4918.                 AuxSymbol[j] = c;
  4919.                 i++;
  4920.             }
  4921.         }
  4922.         if (18 != fwrite(AuxSymbol, 1, 18, CoffFile)) {
  4923.             WriteError();
  4924.         }
  4925.     }
  4926.     return (AuxSym+1);
  4927. }
  4928.  
  4929. #ifdef DOT_LABEL_PREFIX
  4930. #define LOCAL_LABEL(name) (name[0] =='.' \
  4931.                         && ( name [1] == 'L' || name [1] == '.' ))
  4932. #else                   /* not defined DOT_LABEL_PREFIX */
  4933. #define LOCAL_LABEL(name) (name [0] == 'L' )
  4934. #endif                  /* not defined DOT_LABEL_PREFIX */
  4935. static struct frag *text_frag_root;
  4936. static struct frag *data_frag_root;
  4937. static struct frag *text_last_frag; /* Last frag in segment. */
  4938. static struct frag *data_last_frag; /* Last frag in segment. */
  4939. static COFF_RELOC *AddCoffRelocation(symbolS * coffS, int where, int pcrel)
  4940. {
  4941.     COFF_RELOC *coffR;
  4942.  
  4943.     coffR = coffS->Relocations;
  4944.     while (coffR && coffR->Next)
  4945.         coffR = coffR->Next;
  4946.     if (coffR == NULL) {
  4947.         coffS->Relocations = coffR = (COFF_RELOC *) xmalloc(sizeof(COFF_RELOC));
  4948.     }
  4949.     else {
  4950.         coffR->Next = (COFF_RELOC *) xmalloc(sizeof(COFF_RELOC));
  4951.         coffR = coffR->Next;
  4952.     }
  4953.     coffR->Offset = where;
  4954.     coffR->Symbol = coffS;
  4955.     if (pcrel) {
  4956.         coffR->Type = 0x14; /* Program counter relative relocation */
  4957.     }
  4958.     else
  4959.         coffR->Type = 6;
  4960.     return (coffR);
  4961. }
  4962. /* newFixup()
  4963.  * Create a fixS in obstack 'notes'.
  4964.  */
  4965. static void newFixup(fragS * frag,   /* Which frag? */
  4966.                     int where, /* Where in that frag? */
  4967.                     short int size,    /* 1, 2  or 4 usually. */
  4968.                     symbolS * add_symbol,  /* X_add_sym bol. */
  4969.                     symbolS * sub_symbol,  /* X_subtract_symbol. */
  4970.                     long int offset,   /* X_add_number. */
  4971.                     int pcrel)
  4972. {                       /* TRUE if PC-relative relocation. */
  4973.     register fixS *fixP;
  4974.     COFF_RELOC *coffR;
  4975.  
  4976.     fixP = (fixS *) obstack_alloc(¬es, sizeof(fixS));
  4977.     fixP->fx_frag = frag;
  4978.     fixP->fx_where = where;
  4979.     fixP->fx_size = size;
  4980.     fixP->fx_addsy = add_symbol;
  4981.     fixP->fx_subsy = sub_symbol;
  4982.     fixP->fx_offset = offset;
  4983.     fixP->fx_pcrel = (char)pcrel;
  4984.     fixP->fx_next = *seg_fix_rootP;
  4985.     *seg_fix_rootP = fixP;
  4986.     /* --------------------------------------------- */
  4987.     /* add the relocations to the symbol */
  4988.     coffR = AddCoffRelocation(add_symbol, where, pcrel);
  4989.     coffR->pfixS = fixP;
  4990.     coffR->TargetSegment = (now_seg == SEG_TEXT)? IS_TEXT : IS_DATA;
  4991.     fixP->CoffReloc = coffR;
  4992. }
  4993. int WriteCoffFile(void)
  4994. {
  4995.     register struct frchain *frchainP;  /* Track along all frchains. */
  4996.     register fragS *fragP;  /* Track along all frags. */
  4997.     register struct frchain *next_frchainP;
  4998.     register fragS **prev_fragPP;
  4999.     register char *name;
  5000.     register symbolS *symbolP;
  5001.     int PosNow;
  5002.     register symbolS **symbolPP;
  5003.     unsigned TextSize, data_siz;
  5004.     char *CodeBuffer, *CodeBufferP;
  5005.     int EndOfTextSeen;
  5006.     char *DataBuffer;
  5007.     char Nop[50];
  5008.     char Filler[50];
  5009.     unsigned short Short;
  5010.  
  5011.     if (bad_error) return(0);
  5012.     memset(Nop, 0x90, 50);
  5013.     memset(Filler,0,50);
  5014.     /* After every sub-segment, we fake an ".align ...". This conforms to
  5015.     BSD4.2 brane-damage. We then fake ".fill 0" because that is the kind of
  5016.     frag that requires least thought. ".align" frags like to have a
  5017.     following frag since that makes calculating their intended length
  5018.     trivial. */
  5019. #define SUB_SEGMENT_ALIGN (2)
  5020.     for (frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next) {
  5021.         subseg_new(frchainP->frch_seg, frchainP->frch_subseg);
  5022.         frag_align(SUB_SEGMENT_ALIGN, 0);
  5023.         /* frag_align will have left a new frag. */
  5024.         /* Use this last frag for an empty ".fill". */
  5025.         /* For this segment ... Create a last frag. Do not leave a "being
  5026.         filled in frag". */
  5027.         frag_wane(frag_now);
  5028.         frag_now->fr_fix = 0;
  5029.         know(frag_now->fr_next == NULL);
  5030.     }
  5031.     /* From now on, we don't care about sub-segments. Build one frag chain
  5032.     for each segment. Linked thru fr_next. We know that there is at least 1
  5033.     text frchain & at least 1 data frchain. */
  5034.     prev_fragPP = &text_frag_root;
  5035.     for (frchainP = frchain_root; frchainP; frchainP = next_frchainP) {
  5036.         know(frchainP->frch_root);
  5037.         *prev_fragPP = frchainP->frch_root;
  5038.         prev_fragPP = &frchainP->frch_last->fr_next;
  5039.         if (((next_frchainP = frchainP->frch_next) == NULL)
  5040.                 || next_frchainP == data0_frchainP) {
  5041.             prev_fragPP = &data_frag_root;
  5042.             if (next_frchainP) {
  5043.                 text_last_frag = frchainP->frch_last;
  5044.             }
  5045.             else {
  5046.                 data_last_frag = frchainP->frch_last;
  5047.             }
  5048.         }
  5049.     }                   /* for(each struct frchain) */
  5050.     relax_segment(text_frag_root, SEG_TEXT);
  5051.     relax_segment(data_frag_root, SEG_DATA);
  5052.     /* Now the addresses of frags are correct within the segment. */
  5053.     know(text_last_frag->fr_type == rs_fill && text_last_frag->fr_offset == 0);
  5054.     TextSize = text_last_frag->fr_address;
  5055.     /* Join the 2 segments into 1 huge segment. To do this, re-compute every
  5056.     rn_address in the SEG_DATA frags. Then join the data frags after the
  5057.     text frags.
  5058.  
  5059.     Determine a_data [length of data segment]. */
  5060.     if (data_frag_root) {
  5061.         know(text_last_frag->fr_type == rs_fill && text_last_frag->fr_offset == 0);
  5062.         data_siz = data_last_frag->fr_address;
  5063.         know(text_last_frag);
  5064.         text_last_frag->fr_next = data_frag_root;
  5065.         data_siz = data_last_frag->fr_address;
  5066.         text_last_frag->fr_next = data_frag_root;
  5067.     }
  5068.     else {
  5069.         data_siz = 0;
  5070.     }
  5071.     bss_address_frag.fr_address = TextSize + data_siz;
  5072.     /* Crawl the symbol chain. For each symbol whose value depends on a frag,
  5073.     take the address of that frag and subsume it into the value of the
  5074.     symbol. After this, there is just one way to lookup a symbol value.
  5075.     Values are left in their final state for object file emission. We
  5076.     adjust the values of 'L' local symbols, even if we do not intend to
  5077.     emit them to the object file, because their values are needed for
  5078.     fix-ups.
  5079.  
  5080.     Count the (length of the nlists of the) (remaining) symbols. Assign a
  5081.     symbol number to each symbol. Count the number of string-table chars we
  5082.     will emit. */
  5083.     know(zero_address_frag.fr_address == 0);
  5084.     /* JF deal with forward references first. . . */
  5085.     for (symbolP = symbol_rootP; symbolP; symbolP = symbolP->Next) {
  5086.         if (symbolP->sy_forward) {
  5087.             symbolP->SymbolValue += symbolP->sy_forward->SymbolValue + symbolP->sy_forward->sy_frag->fr_address;
  5088.             symbolP->sy_forward = 0;
  5089.         }
  5090.     }
  5091.     symbolPP = &symbol_rootP;   /* -> last symbol chain link. */
  5092.     while ((symbolP = *symbolPP) != NULL) {
  5093.         name = symbolP->Name;
  5094.         if (symbolP->sy_frag)
  5095.             symbolP->SymbolValue += symbolP->sy_frag->fr_address;
  5096.         if (!name || (symbolP->sy_type & N_STAB) || (name[2] != '\001' )) {
  5097.             symbolPP = &(symbolP->Next);
  5098.         }
  5099.         else
  5100.             *symbolPP = symbolP->Next;
  5101.     }                   /* for each symbol */
  5102.     /* Addresses of frags now reflect addresses we use in the object file.
  5103.     Symbol values are correct. Scan the frags, converting any ".org"s and
  5104.     ".align"s to ".fill"s. Also converting any machine-dependent frags
  5105.     using md_convert_frag(); */
  5106.     subseg_change(SEG_TEXT, 0);
  5107.     for (fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
  5108.         switch (fragP->fr_type) {
  5109.         case rs_align:
  5110.         case rs_org:
  5111.             fragP->fr_type = rs_fill;
  5112.             know(fragP->fr_var == 1);
  5113.             know(fragP->fr_next);
  5114.             fragP->fr_offset
  5115.                 = fragP->fr_next->fr_address
  5116.                 - fragP->fr_address
  5117.                 - fragP->fr_fix;
  5118.             break;
  5119.         case rs_fill:
  5120.             break;
  5121.         case rs_machine_dependent:
  5122.             md_convert_frag(fragP);
  5123.             /* After md_convert_frag, we make the frag into a ".space 0".
  5124.             Md_convert_frag() should set up any fixSs and constants
  5125.             required. */
  5126.             frag_wane(fragP);
  5127.             break;
  5128.         default:
  5129.             InternalError(1109);
  5130.             break;
  5131.         }               /* switch (fr_type) */
  5132.     }                   /* for each frag. */
  5133.     /* Scan every FixS performing fixups. We had to wait until now to do this
  5134.     because md_convert_frag() may have made some fixSs. */
  5135.     NrOfTextFixups = fixup_segment(text_fix_root, N_TEXT);
  5136.     NrOfDataFixups = fixup_segment(data_fix_root, N_DATA);
  5137.  
  5138.     /* ------------------Create and initialize the coff file */
  5139.     CoffFile = fopen(OutputFileName, "wb");
  5140.     if (CoffFile == NULL) {
  5141.         fprintf(stderr,"Can't create the output file %s", OutputFileName);
  5142.         return(0);
  5143.     }
  5144.     WriteCoffHeader();
  5145.     CodeSize = 0;
  5146.     DataSize = 0;
  5147.     EndOfTextSeen = 0;
  5148.     /* Emit code. */
  5149.     for (fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
  5150.         register long int count;
  5151.         register long int fill_size;
  5152.         know(fragP->fr_type == rs_fill);
  5153.         if (!EndOfTextSeen)
  5154.             CodeSize += fragP->fr_fix;
  5155.         else
  5156.             DataSize += fragP->fr_fix;
  5157.         fill_size = fragP->fr_var;
  5158.         know(fragP->fr_offset >= 0);
  5159.         for (count = fragP->fr_offset; count; count--) {
  5160.             if (!EndOfTextSeen)
  5161.                 CodeSize += fill_size;
  5162.             else
  5163.                 DataSize += fill_size;
  5164.         }
  5165.         if (text_last_frag == fragP)
  5166.             EndOfTextSeen = 1;
  5167.     }                   /* for each code frag. */
  5168.     /* allocate the code buffer */
  5169.     CodeBuffer = xmalloc(CodeSize);
  5170.     CodeBufferP = CodeBuffer;
  5171.     DataBuffer = xmalloc(DataSize);
  5172.     /* Append code to CodeBuffer */
  5173.     for (fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
  5174.         register long int count;
  5175.         register long int fill_size;
  5176.         know(fragP->fr_type == rs_fill);
  5177.         StringAppend(&CodeBufferP, fragP->fr_literal, (unsigned long) fragP->fr_fix);
  5178.         fill_size = fragP->fr_var;
  5179.         know(fragP->fr_offset >= 0);
  5180.         for (count = fragP->fr_offset; count; count--) {
  5181.             StringAppend(&CodeBufferP, Filler, (unsigned long) fill_size);
  5182.         }
  5183.         if (text_last_frag == fragP)
  5184.             CodeBufferP = DataBuffer;
  5185.     }                   /* for each code frag. */
  5186.     /* Emit relocations. */
  5187.     NrOfTextFixups = FixRelocations(text_fix_root);
  5188.     PosCodeSection = WriteTextSection(CodeSize, NrOfTextFixups);
  5189.     NrOfDataFixups = FixRelocations(data_fix_root);
  5190.     PosDataSection = WriteDataSection(data_siz, NrOfDataFixups, 0);
  5191.     PosBssSection = WriteBssSection(local_bss_counter);
  5192.     WriteSpecialSectionHeaders();
  5193.     if (glevel > 1) {
  5194.         PosDebugSymbolsSection = WriteDebugSection(0);
  5195.         PosDebugTypesSection = WriteDebugSection(1);
  5196.     }
  5197.     /* Now we can write the raw data sections We begin by the text section
  5198.     raw data */
  5199.     PosRawData = ftell(CoffFile);
  5200.     if ((unsigned) CodeSize != fwrite(CodeBuffer, 1, CodeSize, CoffFile)) {
  5201.         WriteError();
  5202.     }
  5203.     PosNow = ftell(CoffFile);
  5204.     fseek(CoffFile, PosCodeSection + 20, SEEK_SET);
  5205.     fwrite(&PosRawData, 1, 4, CoffFile);
  5206.     fseek(CoffFile, PosNow, SEEK_SET);
  5207.     /* We write the data section */
  5208.     PosRawData = ftell(CoffFile);
  5209.     if ((unsigned) DataSize != fwrite(DataBuffer, 1, DataSize, CoffFile)) {
  5210.         WriteError();
  5211.     }
  5212.     PosNow = ftell(CoffFile);
  5213.     fseek(CoffFile, PosDataSection + 20, SEEK_SET);
  5214.     fwrite(&PosRawData, 1, 4, CoffFile);
  5215.     fseek(CoffFile, PosNow, SEEK_SET);
  5216.     for (symbolP = symbol_rootP; symbolP; symbolP = symbolP->Next) {
  5217.         register char *temp;
  5218.         temp = symbolP->Name;
  5219.         if (symbolP->sy_type == N_UNDF) {
  5220.             symbolP->SectionNumber = 0;
  5221.         }
  5222.         if (symbolP->sy_type == N_UNDF) {
  5223.             symbolP->sy_type |= N_EXT;  /* Any undefined symbols become    N_EXT. */
  5224.         }
  5225.         symbolP->Name = temp;
  5226.     }                   /* for each symbol */
  5227.     ArrangeOrdinalNumbers(SourceFileName);
  5228.     /* Write the relocations for the code section */
  5229.     fseek(CoffFile, 0, SEEK_END);
  5230.     PosNow = ftell(CoffFile);   /* save the position */
  5231.     NrOfTextFixups = WriteRelocations(IS_TEXT);
  5232.     /* Write the file pointer to the relocations of the text section */
  5233.     fseek(CoffFile, PosCodeSection + 24, SEEK_SET);
  5234.     fwrite(&PosNow, 1, 4, CoffFile);
  5235.     /* Write the number of relocations into the section header */
  5236.     fseek(CoffFile, PosCodeSection + 32, SEEK_SET);
  5237.     Short = (unsigned short) NrOfTextFixups;
  5238.     fwrite(&Short, 1, 2, CoffFile);
  5239.     fseek(CoffFile, 0, SEEK_END);   /* position again at EOF */
  5240.  
  5241.     /* Write the relocations for the data section */
  5242.     PosNow = ftell(CoffFile);   /* save the position */
  5243.     NrOfDataFixups = WriteRelocations(IS_DATA);
  5244.     /* Write the file pointer to the relocations of the text section */
  5245.     fseek(CoffFile, PosDataSection + 24, SEEK_SET);
  5246.     fwrite(&PosNow, 1, 4, CoffFile);
  5247.     /* Write the number of relocations */
  5248.     fseek(CoffFile, PosDataSection + 32, SEEK_SET);
  5249.     Short = (unsigned short) NrOfDataFixups;
  5250.     fwrite(&Short, 1, 2, CoffFile);
  5251.     fseek(CoffFile, 0, SEEK_END);   /* position again at EOF */
  5252.  
  5253.     if (glevel)
  5254.         NrOfLineNumbers = WriteLineNumbers(PosCodeSection);
  5255.     else
  5256.         NrOfLineNumbers = 0;
  5257.     WriteSpecialSectionData();
  5258.     /* Emit all symbols left in the symbol chain. Any symbol still undefined
  5259.     is made N_EXT. */
  5260.     PosNow = ftell(CoffFile);
  5261.     PosRawData = PosNow;
  5262.     NrOfCoffSymbols = WriteFileName(SourceFileName);
  5263.     NrOfCoffSymbols = WriteAllCoffSymbols(NrOfCoffSymbols);
  5264.     /* Write the pointer to the symbol table */
  5265.     PosNow = ftell(CoffFile);
  5266.     fseek(CoffFile, 8L, SEEK_SET);
  5267.     fwrite(&PosRawData, 1, 4, CoffFile);
  5268.     /* Update the number of symbols written */
  5269.     fseek(CoffFile, 12L, SEEK_SET);
  5270.     fwrite(&NrOfCoffSymbols, 1, 4, CoffFile);
  5271.     fseek(CoffFile, 0, SEEK_END);
  5272.     /* Write the String Table */
  5273.     WriteStringTable();
  5274.     if (glevel > 1) WriteDebugData();
  5275.     free(CodeBuffer);
  5276.     fclose(CoffFile);
  5277.     return(1);
  5278. }                       /* WriteCoffFile() */
  5279. /* relax_segment()
  5280.  * Now we have a segment, not a crowd of sub-segments, we can make fr_address
  5281.  * values.
  5282.  * Relax the frags.
  5283.  * After this, all frags in this segment have addresses that are correct
  5284.  * within the segment. Since segments live in different file addresses,
  5285.  * these frag addresses may not be the same as final object-file addresses.
  5286.   segment_type:  N_DATA or N_TEXT
  5287.  */
  5288. static void relax_segment(struct frag * segment_frag_root, segT segment_type)
  5289. {
  5290.     register struct frag *fragP;
  5291.     register relax_addressT address;
  5292.     register long int stretch;  /* May be any size, 0 or negative. */
  5293.     /* Cumulative number of addresses we have relaxed this pass. */
  5294.     /* We may have relaxed more than one address. */
  5295.     register long int stretched;    /* Have we stretched on this pass? */
  5296.     /* This is 'cuz stretch may be zero, when, in fact some piece of code
  5297.     grew, and another shrank.  If a branch instruction doesn't fit anymore,
  5298.     we could be scrod */
  5299.     know(segment_type == SEG_DATA || segment_type == SEG_TEXT);
  5300.     /* In case md_estimate_size_before_relax() wants to make fixSs. */
  5301.     subseg_change(segment_type, 0);
  5302.     /* For each frag in segment: count and store  (a 1st guess of)
  5303.     fr_address. */
  5304.     address = 0;
  5305.     for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next) {
  5306.         fragP->fr_address = address;
  5307.         address += fragP->fr_fix;
  5308.         switch (fragP->fr_type) {
  5309.         case rs_fill:
  5310.             address += fragP->fr_offset * fragP->fr_var;
  5311.             break;
  5312.         case rs_align:
  5313.             address += relax_align(address, fragP->fr_offset);
  5314.             break;
  5315.         case rs_org:
  5316.             /* Assume .org is nugatory. It will grow with 1st relax. */
  5317.             break;
  5318.         case rs_machine_dependent:
  5319.             address += md_estimate_size_before_relax(fragP, seg_N_TYPE[(int) segment_type]);
  5320.             break;
  5321.         default:
  5322.             InternalError(1110);
  5323.             break;
  5324.         }               /* switch(fr_type) */
  5325.     }                   /* for each frag in the segment */
  5326.     /* Do relax(). */
  5327.     do {
  5328.         stretch = stretched = 0;
  5329.         for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next) {
  5330.             register long int growth=0;
  5331.             register unsigned long int was_address;
  5332.             /* register long int    var; */
  5333.             register long int offset;
  5334.             register symbolS *symbolP;
  5335.             register long int target;
  5336.             register long int after;
  5337.             register long int aim;
  5338.             was_address = fragP->fr_address;
  5339.             address = fragP->fr_address += stretch;
  5340.             symbolP = fragP->fr_symbol;
  5341.             offset = fragP->fr_offset;
  5342.             /* var = fragP -> fr_var; */
  5343.             switch (fragP->fr_type) {
  5344.             case rs_fill:  /* .fill never relaxes. */
  5345.                 growth = 0;
  5346.                 break;
  5347.             case rs_align:
  5348.                 growth = relax_align((relax_addressT) (address + fragP->fr_fix), offset)
  5349.                     - relax_align((relax_addressT) (was_address + fragP->fr_fix), offset);
  5350.                 break;
  5351.             case rs_org:
  5352.                 target = offset;
  5353.                 if (symbolP) {
  5354.                     know(((symbolP->sy_type & N_TYPE) == N_ABS) || ((symbolP->sy_type & N_TYPE) == N_DATA) || ((symbolP->sy_type & N_TYPE) == N_TEXT));
  5355.                     know(symbolP->sy_frag);
  5356.                     know((symbolP->sy_type & N_TYPE) != N_ABS || symbolP->sy_frag == &zero_address_frag);
  5357.                     target +=
  5358.                         symbolP->SymbolValue
  5359.                         + symbolP->sy_frag->fr_address;
  5360.                 }
  5361.                 know(fragP->fr_next);
  5362.                 after = fragP->fr_next->fr_address;
  5363.                 growth = ((target - after) > 0) ? (target - after) : 0;
  5364.                 /* Growth may be -ve, but variable part */
  5365.                 /* of frag cannot have < 0 chars. */
  5366.                 /* That is, we can't .org backwards. */
  5367.                 growth -= stretch;  /* This is an absolute growth factor */
  5368.                 break;
  5369.             case rs_machine_dependent:
  5370.                 {
  5371.                     register const relax_typeS *this_type;
  5372.                     register const relax_typeS *start_type;
  5373.                     register relax_substateT next_state;
  5374.                     register relax_substateT this_state;
  5375.                     start_type = this_type
  5376.                         = md_relax_table + (this_state = fragP->fr_subtype);
  5377.                     target = offset;
  5378.                     if (symbolP) {
  5379.                         know(((symbolP->sy_type & N_TYPE) == N_ABS) || ((symbolP->sy_type &
  5380.                                                                         N_TYPE) == N_DATA) || ((symbolP->sy_type & N_TYPE) == N_TEXT));
  5381.                         know(symbolP->sy_frag);
  5382.                         know((symbolP->sy_type & N_TYPE) != N_ABS || symbolP->sy_frag == &zero_address_frag);
  5383.                         target +=
  5384.                             symbolP->SymbolValue
  5385.                             + symbolP->sy_frag->fr_address;
  5386.                         if (symbolP->sy_frag->fr_address >= was_address && is_dnrange(fragP, symbolP->sy_frag))
  5387.                             target += stretch;
  5388.                     }
  5389.                     aim = target - address - fragP->fr_fix;
  5390.                     if (aim < 0) {
  5391.                         /* Look backwards. */
  5392.                         for (next_state = this_type->rlx_more; next_state;) {
  5393.                             if (aim >= this_type->rlx_backward)
  5394.                                 next_state = 0;
  5395.                             else {  /* Grow to next state. */
  5396.                                 this_type = md_relax_table + (this_state = next_state);
  5397.                                 next_state = this_type->rlx_more;
  5398.                             }
  5399.                         }
  5400.                     }
  5401.                     else {
  5402.                         /* Look forwards. */
  5403.                         for (next_state = this_type->rlx_more; next_state;) {
  5404.                             if (aim <= this_type->rlx_forward)
  5405.                                 next_state = 0;
  5406.                             else {  /* Grow to next state. */
  5407.                                 this_type = md_relax_table + (this_state = next_state);
  5408.                                 next_state = this_type->rlx_more;
  5409.                             }
  5410.                         }
  5411.                     }
  5412.                     if ((growth = this_type->rlx_length - start_type->rlx_length) != 0)
  5413.                         fragP->fr_subtype = this_state;
  5414.                 }
  5415.                 break;
  5416.             default:
  5417.                 InternalError(1111);
  5418.                 break;
  5419.             }
  5420.             if (growth) {
  5421.                 stretch += growth;
  5422.                 stretched++;
  5423.             }
  5424.         }               /* For each frag in the segment. */
  5425.     } while (stretched);/* Until nothing further to relax. */
  5426.     /* We now have valid fr_address'es for each frag. */
  5427.     /* All fr_address's are correct, relative to their own segment. We have
  5428.     made all the fixS we will ever make. */
  5429. }                       /* relax_segment() */
  5430. /* Relax_align. Advance location counter to next address that has 'alignment'
  5431.  * lowest order bits all 0s.result is how many addresses does the .align take?
  5432.  */
  5433. static relax_addressT relax_align(register relax_addressT address, /* Address now. */
  5434.                                 register long int alignment)
  5435. {                       /* Alignment (binary). */
  5436.     relax_addressT mask;
  5437.     relax_addressT new_address;
  5438.     mask = ~((~0) << alignment);
  5439.     new_address = (address + mask) & (~mask);
  5440.     return (new_address - address);
  5441. }
  5442. /* fixup_segment() */
  5443. static long int fixup_segment(fixS * fixP, int this_segment_type)
  5444. {
  5445.     register long int seg_reloc_count;
  5446.     register symbolS *add_symbolP;
  5447.     register symbolS *sub_symbolP;
  5448.     long int add_number;
  5449.     register int size;
  5450.     register char *place;
  5451.     register long int where;
  5452.     register char pcrel;
  5453.     register fragS *fragP;
  5454.     register int add_symbol_N_TYPE;
  5455.     int wasPcRel;
  5456.     COFF_RELOC *coffR;
  5457.  
  5458.     seg_reloc_count = 0;
  5459.     for (; fixP; fixP = fixP->fx_next) {
  5460.         wasPcRel = 0;
  5461.         fragP = fixP->fx_frag;
  5462.         know(fragP);
  5463.         where = fixP->fx_where;
  5464.         place = fragP->fr_literal + where;
  5465.         size = fixP->fx_size;
  5466.         add_symbolP = fixP->fx_addsy;
  5467.         sub_symbolP = fixP->fx_subsy;
  5468.         add_number = fixP->fx_offset;
  5469.         pcrel = fixP->fx_pcrel;
  5470.         if (add_symbolP)
  5471.             add_symbol_N_TYPE = add_symbolP->sy_type & N_TYPE;
  5472.         if (sub_symbolP) {
  5473.             if (!add_symbolP) { /* Its just -sym */
  5474.                 if (sub_symbolP->sy_type != N_ABS) {
  5475.                     InternalError(1100);
  5476.                 }
  5477.                 add_number -= sub_symbolP->SymbolValue;
  5478.             }
  5479.             else if (((sub_symbolP->sy_type ^ add_symbol_N_TYPE) & N_TYPE) == 0
  5480.                     && (add_symbol_N_TYPE == N_DATA
  5481.                         || add_symbol_N_TYPE == N_TEXT
  5482.                         || add_symbol_N_TYPE == N_BSS
  5483.                         || add_symbol_N_TYPE == N_ABS)) {
  5484.                 /* Difference of 2 symbols from same segment. */
  5485.                 /* Can't make difference of 2 undefineds: 'value' means */
  5486.                 /* something different for N_UNDF. */
  5487.                 add_number += add_symbolP->SymbolValue - sub_symbolP->SymbolValue;
  5488.                 add_symbolP = NULL;
  5489.                 fixP->fx_addsy = NULL;
  5490.             }
  5491.             else {
  5492.                 /* Different segments in subtraction. */
  5493.                 know(sub_symbolP->sy_type != (N_ABS | N_EXT));
  5494.                 if (sub_symbolP->sy_type == N_ABS)
  5495.                     add_number -= sub_symbolP->SymbolValue;
  5496.                 else {
  5497.                     InternalError(1101);
  5498.                 }
  5499.             }
  5500.         }
  5501.         if (add_symbolP) {
  5502.             if (add_symbol_N_TYPE == this_segment_type && pcrel) {
  5503.                 /* This fixup was made when the symbol's segment was
  5504.                 SEG_UNKNOWN, but it is now in the local segment. So we know
  5505.                 how to do the address without relocation. Here arrive all
  5506.                 the calls to the functions in the same module for instance */
  5507.                 add_number += add_symbolP->SymbolValue;
  5508.                 add_number -=
  5509.                     size +
  5510.                     where + fragP->fr_address;
  5511.                 pcrel = 0;  /* Don't want further pcrel processing. */
  5512.                 fixP->fx_addsy = NULL;  /* No relocations please. */
  5513. #if 0
  5514.                 printf("relocation to %s eliminated\n",add_symbolP->Name);
  5515. #endif
  5516.                 coffR = add_symbolP->Relocations;
  5517.                 if (coffR == fixP->CoffReloc) {
  5518.                     add_symbolP->Relocations = coffR->Next;
  5519.                     free(coffR);
  5520.                     fixP->CoffReloc = NULL;
  5521.                 }
  5522.                 else {
  5523.                     while (coffR) {
  5524.                         if (coffR->Next == fixP->CoffReloc) {
  5525.                             coffR->Next = fixP->CoffReloc->Next;
  5526.                             free(fixP->CoffReloc);
  5527.                             fixP->CoffReloc = NULL;
  5528.                             break;
  5529.                         }
  5530.                         coffR = coffR->Next;
  5531.                     }
  5532.                 }
  5533.                 wasPcRel = 1;
  5534.                 /* It would be nice to check that the address does not
  5535.                 overflow. I didn't do this check because: +  It is machine
  5536.                 dependent in the general case (eg 32032) + Compiler output
  5537.                 will never need this checking, so why slow down the usual
  5538.                 case? */
  5539.             }
  5540.             else {
  5541.                 switch (add_symbol_N_TYPE) {
  5542.                 case N_ABS:
  5543.                     add_number += add_symbolP->SymbolValue;
  5544.                     fixP->fx_addsy = NULL;
  5545.                     add_symbolP = NULL;
  5546.                     break;
  5547.                 case N_DATA:
  5548.                 case N_BSS:
  5549.                     seg_reloc_count++;
  5550.                     break;
  5551.                 case N_TEXT:
  5552.                     seg_reloc_count++;
  5553.                     if (this_segment_type == N_TEXT)
  5554.                         add_number += add_symbolP->SymbolValue;
  5555.                     break;
  5556.                 case N_UNDF:
  5557.                     seg_reloc_count++;
  5558.                     break;
  5559.                 default:
  5560.                     InternalError(1112);
  5561.                     break;
  5562.                 }       /* switch on symbol seg */
  5563.             }           /* if not in local seg */
  5564.         }               /* if there was a + symbol */
  5565.         if (pcrel) {
  5566.             add_number -= size + where + fragP->fr_address;
  5567.             if (add_symbolP == 0) {
  5568.                 fixP->fx_addsy = &abs_symbol;
  5569.                 seg_reloc_count++;
  5570.             }
  5571.         }
  5572.         if (add_symbolP && add_symbol_N_TYPE == N_UNDF && pcrel) {
  5573.             pcrel = 0;
  5574.             add_number = 0;
  5575.         }
  5576.         if ((size == 1 &&
  5577.                 (add_number & ~0xFF) && (add_number & ~0xFF != (-1 & ~0xFF))) ||
  5578.                 (size == 2 &&
  5579.                 (add_number & ~0xFFFF) &&
  5580.                 (add_number & ~0xFFFF != (-1 & ~0xFFFF)))) {
  5581.                     InternalError(1102);
  5582.         }
  5583.         if (!(wasPcRel) &&
  5584.             add_number &&
  5585.             this_segment_type == N_TEXT && add_symbol_N_TYPE == N_TEXT) {
  5586. /*            printf("relocation to %s changed from %d to zero\n",add_symbolP->Name,add_number);*/
  5587.             add_number = 0;
  5588.         }
  5589.         memcpy(place,&add_number,size);
  5590.     }                   /* For each fixS in this segment. */
  5591.     return (seg_reloc_count);
  5592. }                       /* fixup_segment() */
  5593. /* FixRelocations() Crawl along a fixS chain. Fix the segment's relocations. */
  5594. static int FixRelocations(register fixS * fixP)
  5595. {
  5596.     int result;
  5597.     COFF_RELOC *rvpR;
  5598.  
  5599.     result = 0;
  5600.     for (; fixP; fixP = fixP->fx_next) {
  5601.         if (fixP->fx_addsy != NULL) {
  5602.             rvpR = fixP->CoffReloc;
  5603.             while (rvpR) {
  5604.                 if (rvpR->pfixS == fixP) {
  5605.                     rvpR->Offset = fixP->fx_frag->fr_address + fixP->fx_where;
  5606.                 }
  5607.                 rvpR = rvpR->Next;
  5608.             }
  5609.             result++;
  5610.         }
  5611.     }
  5612.     return (result);
  5613. }
  5614. #ifndef ASM_LIB
  5615. static int is_dnrange(struct frag * f1, struct frag * f2)
  5616. {
  5617.     while (f1) {
  5618.         if (f1->fr_next == f2)
  5619.             return 1;
  5620.         f1 = f1->fr_next;
  5621.     }
  5622.     return 0;
  5623. }
  5624. #endif
  5625. int AsmInit(char *fname)
  5626. {
  5627.     symbol_lastP = NULL;
  5628.     symbol_rootP = NULL;
  5629.     sy_hash = hash_new();
  5630.     memset((char *) (&abs_symbol),0, sizeof(abs_symbol));
  5631.     abs_symbol.sy_type = N_ABS;
  5632.     local_bss_counter = 0;
  5633.  
  5634.     subsegs_begin();
  5635.     obstack_begin(¬es, 5000);
  5636.  
  5637.     InitializeAsmTables();
  5638.     InitAsmInput();
  5639.  
  5640.     text_fix_root = NULL;
  5641.     data_fix_root = NULL;
  5642.     need_pass_2 = FALSE;
  5643.     SetObjFileName(fname);
  5644.     subseg_new(SEG_TEXT, 0);
  5645.     return (1);
  5646. }
  5647.  
  5648. int IsWithinSpecialSection(void)
  5649. {
  5650.     return (IsSpecialSection)? 1: 0;
  5651. }
  5652.