home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / binutils-2.7-src.tgz / tar.out / fsf / binutils / gas / gasp.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  76KB  |  3,704 lines

  1. /* gasp.c - Gnu assembler preprocessor main program.
  2.    Copyright (C) 1994, 1995 Free Software Foundation, Inc.
  3.  
  4.    Written by Steve and Judy Chamberlain of Cygnus Support,
  5.       sac@cygnus.com
  6.  
  7.    This file is part of GASP, the GNU Assembler Preprocessor.
  8.  
  9.    GASP is free software; you can redistribute it and/or modify
  10.    it under the terms of the GNU General Public License as published by
  11.    the Free Software Foundation; either version 2, or (at your option)
  12.    any later version.
  13.  
  14.    GASP is distributed in the hope that it will be useful,
  15.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.    GNU General Public License for more details.
  18.  
  19.    You should have received a copy of the GNU General Public License
  20.    along with GASP; see the file COPYING.  If not, write to the Free
  21.    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  22.    02111-1307, USA. */
  23.  
  24. /*
  25.  
  26. This program translates the input macros and stuff into a form
  27. suitable for gas to consume.
  28.  
  29.  
  30.   gasp [-sdhau] [-c char] [-o <outfile>] <infile>*
  31.  
  32.   -s copy source to output
  33.   -c <char> comments are started with <char> instead of !
  34.   -u allow unreasonable stuff
  35.   -p print line numbers
  36.   -d print debugging stats
  37.   -s semi colons start comments
  38.   -a use alternate syntax
  39.      Pseudo ops can start with or without a .
  40.      Labels have to be in first column.
  41.   -I specify include dir
  42.     Macro arg parameters subsituted by name, don't need the &.
  43.      String can start with ' too.
  44.      Strings can be surrounded by <..>
  45.      A %<exp> in a string evaluates the expression 
  46.      Literal char in a string with !
  47.  
  48.  
  49. */
  50.  
  51. #include "config.h"
  52.  
  53. #include <stdio.h>
  54. #include <string.h>
  55. #include <getopt.h>
  56. #include <ctype.h>
  57.  
  58. #ifdef HAVE_STDLIB_H
  59. #include <stdlib.h>
  60. #endif
  61.  
  62. #ifdef NEED_MALLOC_DECLARATION
  63. extern char *malloc ();
  64. #endif
  65.  
  66. #include "ansidecl.h"
  67. #include "libiberty.h"
  68. #include "sb.h"
  69. #include "macro.h"
  70.  
  71. char *program_version = "1.2";
  72.  
  73. #define MAX_INCLUDES 30        /* Maximum include depth */
  74. #define MAX_REASONABLE 1000    /* Maximum number of expansions */
  75.  
  76. int unreasonable;        /* -u on command line */
  77. int stats;            /* -d on command line */
  78. int print_line_number;        /* -p flag on command line */
  79. int copysource;            /* -c flag on command line */
  80. int warnings;            /* Number of WARNINGs generated so far. */
  81. int errors;            /* Number of ERRORs generated so far. */
  82. int fatals;            /* Number of fatal ERRORs generated so far (either 0 or 1). */
  83. int alternate = 0;              /* -a on command line */
  84. int mri = 0;            /* -M on command line */
  85. char comment_char = '!';
  86. int radix = 10;            /* Default radix */
  87.  
  88. int had_end; /* Seen .END */
  89.  
  90. /* The output stream */
  91. FILE *outfile;
  92.  
  93. /* the attributes of each character are stored as a bit pattern
  94.    chartype, which gives us quick tests. */
  95.  
  96.  
  97. #define FIRSTBIT 1
  98. #define NEXTBIT  2
  99. #define SEPBIT   4
  100. #define WHITEBIT 8
  101. #define COMMENTBIT 16
  102. #define BASEBIT  32
  103. #define ISCOMMENTCHAR(x) (chartype[(unsigned)(x)] & COMMENTBIT)
  104. #define ISFIRSTCHAR(x)  (chartype[(unsigned)(x)] & FIRSTBIT)
  105. #define ISNEXTCHAR(x)   (chartype[(unsigned)(x)] & NEXTBIT)
  106. #define ISSEP(x)        (chartype[(unsigned)(x)] & SEPBIT)
  107. #define ISWHITE(x)      (chartype[(unsigned)(x)] & WHITEBIT)
  108. #define ISBASE(x)       (chartype[(unsigned)(x)] & BASEBIT)
  109. static char chartype[256];
  110.  
  111.  
  112. /* Conditional assembly uses the `ifstack'.  Each aif pushes another
  113.    entry onto the stack, and sets the on flag if it should.  The aelse
  114.    sets hadelse, and toggles on.  An aend pops a level.  We limit to
  115.    100 levels of nesting, not because we're facists pigs with read
  116.    only minds, but because more than 100 levels of nesting is probably
  117.    a bug in the user's macro structure.  */
  118.  
  119. #define IFNESTING 100
  120. struct
  121.   {
  122.     int on;            /* is the level being output */
  123.     int hadelse;        /* has an aelse been seen */
  124.   }
  125. ifstack[IFNESTING];
  126. int ifi;
  127.  
  128. /* The final and intermediate results of expression evaluation are kept in
  129.    exp_t's.  Note that a symbol is not an sb, but a pointer into the input
  130.    line.  It must be coped somewhere safe before the next line is read in. */
  131.  
  132. typedef struct
  133.   {
  134.     char *name;
  135.     int len;
  136.   }
  137. symbol;
  138.  
  139. typedef struct
  140.   {
  141.     int value;            /* constant part */
  142.     symbol add_symbol;        /* name part */
  143.     symbol sub_symbol;        /* name part */
  144.   }
  145. exp_t;
  146.  
  147.  
  148. /* Hashing is done in a pretty standard way.  A hash_table has a
  149.    pointer to a vector of pointers to hash_entrys, and the size of the
  150.    vector.  A hash_entry contains a union of all the info we like to
  151.    store in hash table.  If there is a hash collision, hash_entries
  152.    with the same hash are kept in a chain. */
  153.  
  154. /* What the data in a hash_entry means */
  155. typedef enum
  156.   {
  157.     hash_integer,        /* name->integer mapping */
  158.     hash_string,        /* name->string mapping */
  159.     hash_macro,            /* name is a macro */
  160.     hash_formal            /* name is a formal argument */
  161.   } hash_type;
  162.  
  163. typedef struct hs
  164.   {
  165.     sb key;            /* symbol name */
  166.     hash_type type;        /* symbol meaning */
  167.     union
  168.       {
  169.     sb s;
  170.     int i;
  171.     struct macro_struct *m;
  172.     struct formal_struct *f;
  173.       } value;
  174.     struct hs *next;        /* next hash_entry with same hash key */
  175.   } hash_entry;
  176.  
  177. typedef struct
  178.   {
  179.     hash_entry **table;
  180.     int size;
  181.   } hash_table;
  182.  
  183.  
  184. /* Structures used to store macros. 
  185.  
  186.    Each macro knows its name and included text.  It gets built with a
  187.    list of formal arguments, and also keeps a hash table which points
  188.    into the list to speed up formal search.  Each formal knows its
  189.    name and its default value.  Each time the macro is expanded, the
  190.    formals get the actual values attatched to them. */
  191.  
  192. /* describe the formal arguments to a macro */
  193.  
  194. typedef struct formal_struct
  195.   {
  196.     struct formal_struct *next;    /* next formal in list */
  197.     sb name;            /* name of the formal */
  198.     sb def;            /* the default value */
  199.     sb actual;            /* the actual argument (changed on each expansion) */
  200.     int index;            /* the index of the formal 0..formal_count-1 */
  201.   }
  202. formal_entry;
  203.  
  204. /* describe the macro. */
  205.  
  206. typedef struct macro_struct
  207.   {
  208.     sb sub;            /* substitution text. */
  209.     int formal_count;        /* number of formal args. */
  210.     formal_entry *formals;    /* pointer to list of formal_structs */
  211.     hash_table formal_hash;    /* hash table of formals. */
  212.   }
  213. macro_entry;
  214.  
  215. /* how we nest files and expand macros etc.
  216.  
  217.    we keep a stack of of include_stack structs.  each include file
  218.    pushes a new level onto the stack.  we keep an sb with a pushback
  219.    too.  unget chars are pushed onto the pushback sb, getchars first
  220.    checks the pushback sb before reading from the input stream.
  221.  
  222.    small things are expanded by adding the text of the item onto the
  223.    pushback sb.  larger items are grown by pushing a new level and
  224.    allocating the entire pushback buf for the item.  each time
  225.    something like a macro is expanded, the stack index is changed. we
  226.    can then perform an exitm by popping all entries off the stack with
  227.    the same stack index.  if we're being reasonable, we can detect
  228.    recusive expansion by checking the index is reasonably small.
  229.  */
  230.  
  231. typedef enum
  232.   {
  233.     include_file, include_repeat, include_while, include_macro
  234.   } include_type;
  235.  
  236. struct include_stack
  237.   {
  238.     sb pushback;        /* current pushback stream */
  239.     int pushback_index;        /* next char to read from stream */
  240.     FILE *handle;        /* open file */
  241.     sb name;            /* name of file */
  242.     int linecount;        /* number of lines read so far */
  243.     include_type type;
  244.     int index;            /* index of this layer */
  245.   }
  246. include_stack[MAX_INCLUDES];
  247.  
  248. struct include_stack *sp;
  249. #define isp (sp - include_stack)
  250.  
  251. /* Include file list */
  252.  
  253. typedef struct include_path 
  254. {
  255.   struct include_path *next;
  256.   sb path;
  257. }  include_path;
  258.  
  259. include_path *paths_head;
  260. include_path *paths_tail;
  261.  
  262.  
  263. static void quit PARAMS ((void));
  264. static void hash_new_table PARAMS ((int, hash_table *));
  265. static int hash PARAMS ((sb *));
  266. static hash_entry *hash_create PARAMS ((hash_table *, sb *));
  267. static void hash_add_to_string_table PARAMS ((hash_table *, sb *, sb *, int));
  268. static void hash_add_to_int_table PARAMS ((hash_table *, sb *, int));
  269. static hash_entry *hash_lookup PARAMS ((hash_table *, sb *));
  270. static void checkconst PARAMS ((int, exp_t *));
  271. static int sb_strtol PARAMS ((int, sb *, int, int *));
  272. static int level_0 PARAMS ((int, sb *, exp_t *));
  273. static int level_1 PARAMS ((int, sb *, exp_t *));
  274. static int level_2 PARAMS ((int, sb *, exp_t *));
  275. static int level_3 PARAMS ((int, sb *, exp_t *));
  276. static int level_4 PARAMS ((int, sb *, exp_t *));
  277. static int level_5 PARAMS ((int, sb *, exp_t *));
  278. static int exp_parse PARAMS ((int, sb *, exp_t *));
  279. static void exp_string PARAMS ((exp_t *, sb *));
  280. static int exp_get_abs PARAMS ((const char *, int, sb *, int *));
  281. #if 0
  282. static void strip_comments PARAMS ((sb *));
  283. #endif
  284. static void unget PARAMS ((int));
  285. static void include_buf PARAMS ((sb *, sb *, include_type, int));
  286. static void include_print_where_line PARAMS ((FILE *));
  287. static void include_print_line PARAMS ((FILE *));
  288. static int get_line PARAMS ((sb *));
  289. static int grab_label PARAMS ((sb *, sb *));
  290. static void change_base PARAMS ((int, sb *, sb *));
  291. static void do_end PARAMS ((sb *));
  292. static void do_assign PARAMS ((int, int, sb *));
  293. static void do_radix PARAMS ((sb *));
  294. static int get_opsize PARAMS ((int, sb *, int *));
  295. static int eol PARAMS ((int, sb *));
  296. static void do_data PARAMS ((int, sb *, int));
  297. static void do_datab PARAMS ((int, sb *));
  298. static void do_align PARAMS ((int, sb *));
  299. static void do_res PARAMS ((int, sb *, int));
  300. static void do_export PARAMS ((sb *));
  301. static void do_print PARAMS ((int, sb *));
  302. static void do_heading PARAMS ((int, sb *));
  303. static void do_page PARAMS ((void));
  304. static void do_form PARAMS ((int, sb *));
  305. static int get_any_string PARAMS ((int, sb *, sb *, int, int));
  306. static int skip_openp PARAMS ((int, sb *));
  307. static int skip_closep PARAMS ((int, sb *));
  308. static int dolen PARAMS ((int, sb *, sb *));
  309. static int doinstr PARAMS ((int, sb *, sb *));
  310. static int dosubstr PARAMS ((int, sb *, sb *));
  311. static void process_assigns PARAMS ((int, sb *, sb *));
  312. static int get_and_process PARAMS ((int, sb *, sb *));
  313. static void process_file PARAMS ((void));
  314. static void free_old_entry PARAMS ((hash_entry *));
  315. static void do_assigna PARAMS ((int, sb *));
  316. static void do_assignc PARAMS ((int, sb *));
  317. static void do_reg PARAMS ((int, sb *));
  318. static int condass_lookup_name PARAMS ((sb *, int, sb *, int));
  319. static int whatcond PARAMS ((int, sb *, int *));
  320. static int istrue PARAMS ((int, sb *));
  321. static void do_aif PARAMS ((int, sb *));
  322. static void do_aelse PARAMS ((void));
  323. static void do_aendi PARAMS ((void));
  324. static int condass_on PARAMS ((void));
  325. static void do_if PARAMS ((int, sb *, int));
  326. static int get_mri_string PARAMS ((int, sb *, sb *, int));
  327. static void do_ifc PARAMS ((int, sb *, int));
  328. static void do_aendr PARAMS ((void));
  329. static void do_awhile PARAMS ((int, sb *));
  330. static void do_aendw PARAMS ((void));
  331. static void do_exitm PARAMS ((void));
  332. static void do_arepeat PARAMS ((int, sb *));
  333. static void do_endm PARAMS ((void));
  334. static void do_irp PARAMS ((int, sb *, int));
  335. static void do_local PARAMS ((int, sb *));
  336. static void do_macro PARAMS ((int, sb *));
  337. static int macro_op PARAMS ((int, sb *));
  338. static int getstring PARAMS ((int, sb *, sb *));
  339. static void do_sdata PARAMS ((int, sb *, int));
  340. static void do_sdatab PARAMS ((int, sb *));
  341. static int new_file PARAMS ((const char *));
  342. static void do_include PARAMS ((int, sb *));
  343. static void include_pop PARAMS ((void));
  344. static int get PARAMS ((void));
  345. static int linecount PARAMS ((void));
  346. static int include_next_index PARAMS ((void));
  347. static void chartype_init PARAMS ((void));
  348. static int process_pseudo_op PARAMS ((int, sb *, sb *));
  349. static void add_keyword PARAMS ((const char *, int));
  350. static void process_init PARAMS ((void));
  351. static void do_define PARAMS ((const char *));
  352. static void show_usage PARAMS ((FILE *, int));
  353. static void show_help PARAMS ((void));
  354.  
  355. #define FATAL(x) \
  356.   do { include_print_where_line (stderr); fprintf x ; fatals++; quit(); } while(0) 
  357. #define ERROR(x) \
  358.   do { include_print_where_line (stderr); fprintf x; errors++; } while(0)
  359. #define WARNING(x) \
  360.   do { include_print_where_line (stderr); fprintf x; warnings++;} while(0) 
  361.  
  362.  
  363.  
  364. /* exit the program and return the right ERROR code. */
  365. static void
  366. quit ()
  367. {
  368.   int exitcode;
  369.   if (fatals + errors)
  370.     exitcode = 1;
  371.   else
  372.     exitcode = 0;
  373.  
  374.   if (stats) 
  375.     {
  376.       int i;
  377.       for (i = 0; i < sb_max_power_two; i++) 
  378.     {
  379.       fprintf (stderr, "strings size %8d : %d\n", 1<<i, string_count[i]);
  380.     }
  381.     }
  382.   exit (exitcode);
  383. }
  384.  
  385. /* hash table maintenance. */
  386.  
  387. /* build a new hash table with size buckets, and fill in the info at ptr. */
  388.  
  389. static void
  390. hash_new_table (size, ptr)
  391.      int size;
  392.      hash_table *ptr;
  393. {
  394.   int i;
  395.   ptr->size = size;
  396.   ptr->table = (hash_entry **) xmalloc (size * (sizeof (hash_entry *)));
  397.   /* Fill with null-pointer, not zero-bit-pattern.  */
  398.   for (i = 0; i < size; i++)
  399.     ptr->table[i] = 0;
  400. }
  401.  
  402. /* calculate and return the hash value of the sb at key. */
  403.  
  404. static int
  405. hash (key)
  406.      sb *key;
  407. {
  408.   int k = 0x1234;
  409.   int i;
  410.   char *p = key->ptr;
  411.   for (i = 0; i < key->len; i++)
  412.     {
  413.       k ^= (k << 2) ^ *p;
  414.       p++;
  415.     }
  416.   return k & 0xf0fff;
  417. }
  418.  
  419. /* lookup key in hash_table tab, if present, then return it, otherwise
  420.    build a new one and fill it with hash_integer. */
  421.  
  422. static
  423. hash_entry *
  424. hash_create (tab, key)
  425.      hash_table *tab;
  426.      sb *key;
  427. {
  428.   int k = hash (key) % tab->size;
  429.   hash_entry *p;
  430.   hash_entry **table = tab->table;
  431.  
  432.   p = table[k];
  433.  
  434.   while (1)
  435.     {
  436.       if (!p)
  437.     {
  438.       hash_entry *n = (hash_entry *) xmalloc (sizeof (hash_entry));
  439.       n->next = table[k];
  440.       sb_new (&n->key);
  441.       sb_add_sb (&n->key, key);
  442.       table[k] = n;
  443.       n->type = hash_integer;
  444.       return n;
  445.     }
  446.       if (strncmp (table[k]->key.ptr, key->ptr, key->len) == 0)
  447.     {
  448.       return p;
  449.     }
  450.       p = p->next;
  451.     }
  452. }
  453.  
  454. /* add sb name with key into hash_table tab.  if replacing old value
  455.    and again, then ERROR. */
  456.  
  457. static
  458. void
  459. hash_add_to_string_table (tab, key, name, again)
  460.      hash_table *tab;
  461.      sb *key;
  462.      sb *name;
  463.      int again;
  464. {
  465.   hash_entry *ptr = hash_create (tab, key);
  466.   if (ptr->type == hash_integer)
  467.     {
  468.       sb_new (&ptr->value.s);
  469.     }
  470.   if (ptr->value.s.len)
  471.     {
  472.       if (!again)
  473.     ERROR ((stderr, "redefintion not allowed"));
  474.     }
  475.  
  476.   ptr->type = hash_string;
  477.   sb_reset (&ptr->value.s);
  478.   
  479.   sb_add_sb (&ptr->value.s, name);
  480. }
  481.  
  482. /* add integer name to hash_table tab with sb key. */
  483.  
  484. static
  485. void
  486. hash_add_to_int_table (tab, key, name)
  487.      hash_table *tab;
  488.      sb *key;
  489.      int name;
  490. {
  491.   hash_entry *ptr = hash_create (tab, key);
  492.   ptr->value.i = name;
  493. }
  494.  
  495. /* lookup sb key in hash_table tab.  if found return hash_entry result,
  496.    else 0. */
  497.    
  498. static
  499. hash_entry *
  500. hash_lookup (tab, key)
  501.      hash_table *tab;
  502.      sb *key;
  503. {
  504.   int k = hash (key) % tab->size;
  505.   hash_entry **table = tab->table;
  506.   hash_entry *p = table[k];
  507.   while (p)
  508.     {
  509.       if (p->key.len == key->len
  510.       && strncmp (p->key.ptr, key->ptr, key->len) == 0)
  511.     return p;
  512.       p = p->next;
  513.     }
  514.   return 0;
  515. }
  516.  
  517.  
  518. /* expressions
  519.  
  520.    are handled in a really simple recursive decent way. each bit of
  521.    the machine takes an index into an sb and a pointer to an exp_t,
  522.    modifies the *exp_t and returns the index of the first character
  523.    past the part of the expression parsed.
  524.  
  525.  expression precedence:
  526.   ( )
  527.  unary + - ~
  528.   * /
  529.   + -
  530.   &
  531.   | ~
  532.  
  533. */
  534.  
  535.  
  536. /* make sure that the exp_t at term is constant, if not the give the op ERROR. */
  537.  
  538. static
  539. void
  540. checkconst (op, term)
  541.      int op;
  542.      exp_t *term;
  543. {
  544.   if (term->add_symbol.len
  545.       || term->sub_symbol.len)
  546.     {
  547.       ERROR ((stderr, "the %c operator cannot take non-absolute arguments.\n", op));
  548.     }
  549. }
  550.  
  551. /* turn the number in string at idx into a number of base,
  552.    fill in ptr and return the index of the first character not in the
  553.    number. */
  554.  
  555. static
  556. int
  557. sb_strtol (idx, string, base, ptr)
  558.      int idx;
  559.      sb *string;
  560.      int base;
  561.      int *ptr;
  562. {
  563.   int value = 0;
  564.   idx = sb_skip_white (idx, string);
  565.  
  566.   while (idx < string->len)
  567.     {
  568.       int ch = string->ptr[idx];
  569.       int dig = 0;
  570.       if (isdigit (ch))
  571.     dig = ch - '0';
  572.       else if (ch >= 'a' && ch <= 'f')
  573.     dig = ch - 'a' + 10;
  574.       else if (ch >= 'A' && ch <= 'F')
  575.     dig = ch - 'A' + 10;
  576.       else
  577.     break;
  578.  
  579.       if (dig >= base)
  580.     break;
  581.  
  582.       value = value * base + dig;
  583.       idx++;
  584.     }
  585.   *ptr = value;
  586.   return idx;
  587. }
  588.  
  589. static int
  590. level_0 (idx, string, lhs)
  591.      int idx;
  592.      sb *string;
  593.      exp_t *lhs;
  594. {
  595.   lhs->add_symbol.len = 0;
  596.   lhs->add_symbol.name = 0;
  597.  
  598.   lhs->sub_symbol.len = 0;
  599.   lhs->sub_symbol.name = 0;
  600.  
  601.   idx = sb_skip_white (idx, string);
  602.  
  603.   lhs->value = 0;
  604.  
  605.   if (isdigit (string->ptr[idx]))
  606.     {
  607.       idx = sb_strtol (idx, string, 10, &lhs->value);
  608.     }
  609.   else if (ISFIRSTCHAR (string->ptr[idx]))
  610.     {
  611.       int len = 0;
  612.       lhs->add_symbol.name = string->ptr + idx;
  613.       while (idx < string->len && ISNEXTCHAR (string->ptr[idx]))
  614.     {
  615.       idx++;
  616.       len++;
  617.     }
  618.       lhs->add_symbol.len = len;
  619.     }
  620.   else if (string->ptr[idx] == '"')
  621.     {
  622.       sb acc;
  623.       sb_new (&acc);
  624.       ERROR ((stderr, "string where expression expected.\n"));
  625.       idx = getstring (idx, string, &acc);
  626.       sb_kill (&acc);
  627.     }
  628.   else
  629.     {
  630.       ERROR ((stderr, "can't find primary in expression.\n"));
  631.       idx++;
  632.     }
  633.   return sb_skip_white (idx, string);
  634. }
  635.  
  636.  
  637.  
  638. static int
  639. level_1 (idx, string, lhs)
  640.      int idx;
  641.      sb *string;
  642.      exp_t *lhs;
  643. {
  644.   idx = sb_skip_white (idx, string);
  645.  
  646.   switch (string->ptr[idx])
  647.     {
  648.     case '+':
  649.       idx = level_1 (idx + 1, string, lhs);
  650.       break;
  651.     case '~':
  652.       idx = level_1 (idx + 1, string, lhs);
  653.       checkconst ('~', lhs);
  654.       lhs->value = ~lhs->value;
  655.       break;
  656.     case '-':
  657.       {
  658.     symbol t;
  659.     idx = level_1 (idx + 1, string, lhs);
  660.     lhs->value = -lhs->value;
  661.     t = lhs->add_symbol;
  662.     lhs->add_symbol = lhs->sub_symbol;
  663.     lhs->sub_symbol = t;
  664.     break;
  665.       }
  666.     case '(':
  667.       idx++;
  668.       idx = level_5 (sb_skip_white (idx, string), string, lhs);
  669.       if (string->ptr[idx] != ')')
  670.     ERROR ((stderr, "misplaced closing parens.\n"));
  671.       else
  672.     idx++;
  673.       break;
  674.     default:
  675.       idx = level_0 (idx, string, lhs);
  676.       break;
  677.     }
  678.   return sb_skip_white (idx, string);
  679. }
  680.  
  681. static int
  682. level_2 (idx, string, lhs)
  683.      int idx;
  684.      sb *string;
  685.      exp_t *lhs;
  686. {
  687.   exp_t rhs;
  688.  
  689.   idx = level_1 (idx, string, lhs);
  690.  
  691.   while (idx < string->len && (string->ptr[idx] == '*'
  692.                    || string->ptr[idx] == '/'))
  693.     {
  694.       char op = string->ptr[idx++];
  695.       idx = level_1 (idx, string, &rhs);
  696.       switch (op)
  697.     {
  698.     case '*':
  699.       checkconst ('*', lhs);
  700.       checkconst ('*', &rhs);
  701.       lhs->value *= rhs.value;
  702.       break;
  703.     case '/':
  704.       checkconst ('/', lhs);
  705.       checkconst ('/', &rhs);
  706.       if (rhs.value == 0)
  707.         ERROR ((stderr, "attempt to divide by zero.\n"));
  708.       else
  709.         lhs->value /= rhs.value;
  710.       break;
  711.     }
  712.     }
  713.   return sb_skip_white (idx, string);
  714. }
  715.  
  716.  
  717. static int
  718. level_3 (idx, string, lhs)
  719.      int idx;
  720.      sb *string;
  721.      exp_t *lhs;
  722. {
  723.   exp_t rhs;
  724.  
  725.   idx = level_2 (idx, string, lhs);
  726.  
  727.   while (idx < string->len
  728.      && (string->ptr[idx] == '+'
  729.          || string->ptr[idx] == '-'))
  730.     {
  731.       char op = string->ptr[idx++];
  732.       idx = level_2 (idx, string, &rhs);
  733.       switch (op)
  734.     {
  735.     case '+':
  736.       lhs->value += rhs.value;
  737.       if (lhs->add_symbol.name && rhs.add_symbol.name)
  738.         {
  739.           ERROR ((stderr, "can't add two relocatable expressions\n"));
  740.         }
  741.       /* change nn+symbol to symbol + nn */
  742.       if (rhs.add_symbol.name)
  743.         {
  744.           lhs->add_symbol = rhs.add_symbol;
  745.         }
  746.       break;
  747.     case '-':
  748.       lhs->value -= rhs.value;
  749.       lhs->sub_symbol = rhs.add_symbol;
  750.       break;
  751.     }
  752.     }
  753.   return sb_skip_white (idx, string);
  754. }
  755.  
  756. static int
  757. level_4 (idx, string, lhs)
  758.      int idx;
  759.      sb *string;
  760.      exp_t *lhs;
  761. {
  762.   exp_t rhs;
  763.  
  764.   idx = level_3 (idx, string, lhs);
  765.  
  766.   while (idx < string->len &&
  767.      string->ptr[idx] == '&')
  768.     {
  769.       char op = string->ptr[idx++];
  770.       idx = level_3 (idx, string, &rhs);
  771.       switch (op)
  772.     {
  773.     case '&':
  774.       checkconst ('&', lhs);
  775.       checkconst ('&', &rhs);
  776.       lhs->value &= rhs.value;
  777.       break;
  778.     }
  779.     }
  780.   return sb_skip_white (idx, string);
  781. }
  782.  
  783. static int
  784. level_5 (idx, string, lhs)
  785.      int idx;
  786.      sb *string;
  787.      exp_t *lhs;
  788. {
  789.   exp_t rhs;
  790.  
  791.   idx = level_4 (idx, string, lhs);
  792.  
  793.   while (idx < string->len
  794.      && (string->ptr[idx] == '|' || string->ptr[idx] == '~'))
  795.     {
  796.       char op = string->ptr[idx++];
  797.       idx = level_4 (idx, string, &rhs);
  798.       switch (op)
  799.     {
  800.     case '|':
  801.       checkconst ('|', lhs);
  802.       checkconst ('|', &rhs);
  803.       lhs->value |= rhs.value;
  804.       break;
  805.     case '~':
  806.       checkconst ('~', lhs);
  807.       checkconst ('~', &rhs);
  808.       lhs->value ^= rhs.value;
  809.       break;
  810.     }
  811.     }
  812.   return sb_skip_white (idx, string);
  813. }
  814.  
  815.  
  816. /* parse the expression at offset idx into string, fill up res with
  817.    the result. return the index of the first char past the expression.
  818.    */
  819.  
  820. static int
  821. exp_parse (idx, string, res)
  822.      int idx;
  823.      sb *string;
  824.      exp_t *res;
  825. {
  826.   return level_5 (sb_skip_white (idx, string), string, res);
  827. }
  828.  
  829.  
  830. /* turn the expression at exp into text and glue it onto the end of
  831.    string. */
  832.  
  833. static void
  834. exp_string (exp, string)
  835.      exp_t *exp;
  836.      sb *string;
  837. {
  838.   int np = 0;
  839.   int ad = 0;
  840.   sb_reset (string);
  841.  
  842.   if (exp->add_symbol.len)
  843.     {
  844.       sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
  845.       np = 1;
  846.       ad = 1;
  847.     }
  848.   if (exp->value)
  849.     {
  850.       char buf[20];
  851.       if (np)
  852.     sb_add_char (string, '+');
  853.       sprintf (buf, "%d", exp->value);
  854.       sb_add_string (string, buf);
  855.       np = 1;
  856.       ad = 1;
  857.     }
  858.   if (exp->sub_symbol.len)
  859.     {
  860.       sb_add_char (string, '-');
  861.       sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
  862.       np = 0;
  863.       ad = 1;
  864.     }
  865.  
  866.   if (!ad)
  867.     sb_add_char (string, '0');
  868. }
  869.  
  870.  
  871. /* parse the expression at offset idx into sb in, return the value in val.  
  872.    if the expression is not constant, give ERROR emsg.  returns the index
  873.    of the first character past the end of the expression. */
  874.  
  875. static int
  876. exp_get_abs (emsg, idx, in, val)
  877.      const char *emsg;
  878.      int idx;
  879.      sb *in;
  880.      int *val;
  881. {
  882.   exp_t res;
  883.   idx = exp_parse (idx, in, &res);
  884.   if (res.add_symbol.len || res.sub_symbol.len)
  885.     ERROR ((stderr, emsg));
  886.   *val = res.value;
  887.   return idx;
  888. }
  889.  
  890.  
  891. sb label; /* current label parsed from line */
  892. hash_table assign_hash_table;   /* hash table for all assigned variables */
  893. hash_table keyword_hash_table;  /* hash table for keyword */
  894. hash_table vars;  /* hash table for  eq variables */
  895.  
  896. #define in_comment ';'
  897.  
  898. #if 0
  899. static void
  900. strip_comments (out)
  901.      sb *out;
  902. {
  903.   char *s = out->ptr;
  904.   int i = 0;
  905.   for (i = 0; i < out->len; i++)
  906.     {
  907.       if (ISCOMMENTCHAR(s[i]))
  908.     {
  909.       out->len = i;
  910.       return;
  911.     }
  912.     }
  913. }
  914. #endif
  915.  
  916. /* push back character ch so that it can be read again. */
  917.  
  918. static void
  919. unget (ch)
  920.      int ch;
  921. {
  922.   if (ch == '\n')
  923.     {
  924.       sp->linecount--;
  925.     }
  926.   if (sp->pushback_index)
  927.     sp->pushback_index--;
  928.   else
  929.     sb_add_char (&sp->pushback, ch);
  930. }
  931.  
  932. /* push the sb ptr onto the include stack, with the given name, type and index. */
  933.  
  934. static
  935. void
  936. include_buf (name, ptr, type, index)
  937.      sb *name;
  938.      sb *ptr;
  939.      include_type type;
  940.      int index;
  941. {
  942.   sp++;
  943.   if (sp - include_stack >= MAX_INCLUDES)
  944.     FATAL ((stderr, "unreasonable nesting.\n"));
  945.   sb_new (&sp->name);
  946.   sb_add_sb (&sp->name, name);
  947.   sp->handle = 0;
  948.   sp->linecount = 1;
  949.   sp->pushback_index = 0;
  950.   sp->type = type;
  951.   sp->index = index;
  952.   sb_new (&sp->pushback);
  953.   sb_add_sb (&sp->pushback, ptr);
  954. }
  955.  
  956.  
  957. /* used in ERROR messages, print info on where the include stack is onto file. */
  958. static 
  959. void
  960. include_print_where_line (file)
  961.      FILE *file;
  962. {
  963.   struct include_stack *p = include_stack + 1;
  964.  
  965.   while (p <= sp)
  966.     {
  967.       fprintf (file, "%s:%d ", sb_name (&p->name), p->linecount - 1);
  968.       p++;
  969.     }
  970. }
  971.  
  972. /* used in listings, print the line number onto file. */
  973. static void
  974. include_print_line (file)
  975.      FILE *file;
  976. {
  977.   int n;
  978.   struct include_stack *p = include_stack + 1;
  979.  
  980.   n = fprintf (file, "%4d", p->linecount);
  981.   p++;
  982.   while (p <= sp)
  983.     {
  984.       n += fprintf (file, ".%d", p->linecount);
  985.       p++;
  986.     }
  987.   while (n < 8 * 3)
  988.     {
  989.       fprintf (file, " ");
  990.       n++;
  991.     }
  992. }
  993.  
  994.  
  995. /* read a line from the top of the include stack into sb in. */
  996.  
  997. static int
  998. get_line (in)
  999.      sb *in;
  1000. {
  1001.   int online = 0;
  1002.   int more = 1;
  1003.  
  1004.   if (copysource)
  1005.     {
  1006.       putc (comment_char, outfile);
  1007.       if (print_line_number)
  1008.     include_print_line (outfile);
  1009.     }
  1010.  
  1011.   while (1)
  1012.     {
  1013.       int ch = get ();
  1014.  
  1015.       while (ch == '\r')
  1016.     ch = get ();
  1017.  
  1018.       if (ch == EOF)
  1019.     {
  1020.       if (online)
  1021.         {
  1022.           WARNING ((stderr, "End of file not at start of line.\n"));
  1023.           if (copysource)
  1024.         putc ('\n', outfile);
  1025.           ch = '\n';
  1026.         }
  1027.       else
  1028.         more = 0;
  1029.       break;
  1030.     }
  1031.  
  1032.       if (copysource)
  1033.     {
  1034.       putc (ch, outfile);
  1035.     }
  1036.  
  1037.       if (ch == '\n')
  1038.     {
  1039.       ch = get ();
  1040.       online = 0;
  1041.       if (ch == '+')
  1042.         {
  1043.           /* continued line */
  1044.           if (copysource)
  1045.         {
  1046.           putc (comment_char, outfile);
  1047.           putc ('+', outfile);
  1048.         }
  1049.           ch = get ();
  1050.         }
  1051.       else
  1052.         {
  1053.           if (ch != EOF)
  1054.         unget (ch);
  1055.           break;
  1056.         }
  1057.     }
  1058.       else
  1059.     {
  1060.       sb_add_char (in, ch);
  1061.     }
  1062.       online++;
  1063.     }
  1064.  
  1065.   return more;
  1066. }
  1067.  
  1068. /* find a label from sb in and put it in out. */
  1069.  
  1070. static int
  1071. grab_label (in, out)
  1072.      sb *in;
  1073.      sb *out;
  1074. {
  1075.   int i = 0;
  1076.   sb_reset (out);
  1077.   if (ISFIRSTCHAR (in->ptr[i]))
  1078.     {
  1079.       sb_add_char (out, in->ptr[i]);
  1080.       i++;
  1081.       while ((ISNEXTCHAR (in->ptr[i]) 
  1082.           || in->ptr[i] == '\\'
  1083.           || in->ptr[i] == '&') 
  1084.          && i < in->len)
  1085.     {
  1086.       sb_add_char (out, in->ptr[i]);
  1087.       i++;
  1088.     }
  1089.     }
  1090.   return i;
  1091. }
  1092.  
  1093. /* find all strange base stuff and turn into decimal. also
  1094.    find all the other numbers and convert them from the default radix */
  1095.  
  1096. static void
  1097. change_base (idx, in, out)
  1098.      int idx;
  1099.      sb *in;
  1100.      sb *out;
  1101. {
  1102.   char buffer[20];
  1103.  
  1104.   while (idx < in->len)
  1105.     {
  1106.       if (in->ptr[idx] == '\\'
  1107.       && idx + 1 < in->len
  1108.       && in->ptr[idx + 1] == '(')
  1109.     {
  1110.       idx += 2;
  1111.       while (idx < in->len
  1112.          && in->ptr[idx] != ')')
  1113.         {
  1114.           sb_add_char (out, in->ptr[idx]);
  1115.           idx++;
  1116.         }
  1117.       if (idx < in->len)
  1118.         idx++;
  1119.     }
  1120.       else if (idx < in->len - 1 && in->ptr[idx + 1] == '\'' && ! mri)
  1121.     {
  1122.       int base;
  1123.       int value;
  1124.       switch (in->ptr[idx])
  1125.         {
  1126.         case 'b':
  1127.         case 'B':
  1128.           base = 2;
  1129.           break;
  1130.         case 'q':
  1131.         case 'Q':
  1132.           base = 8;
  1133.           break;
  1134.         case 'h':
  1135.         case 'H':
  1136.           base = 16;
  1137.           break;
  1138.         case 'd':
  1139.         case 'D':
  1140.           base = 10;
  1141.           break;
  1142.         default:
  1143.           ERROR ((stderr, "Illegal base character %c.\n", in->ptr[idx]));
  1144.           base = 10;
  1145.           break;
  1146.         }
  1147.  
  1148.       idx = sb_strtol (idx + 2, in, base, &value);
  1149.       sprintf (buffer, "%d", value);
  1150.       sb_add_string (out, buffer);
  1151.     }
  1152.       else if (ISFIRSTCHAR (in->ptr[idx]))
  1153.     {
  1154.       /* copy entire names through quickly */
  1155.       sb_add_char (out, in->ptr[idx]);
  1156.       idx++;
  1157.       while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
  1158.         {
  1159.           sb_add_char (out, in->ptr[idx]);
  1160.           idx++;
  1161.         }
  1162.     }
  1163.       else if (isdigit (in->ptr[idx]))
  1164.     {
  1165.       int value;
  1166.       /* all numbers must start with a digit, let's chew it and
  1167.          spit out decimal */
  1168.       idx = sb_strtol (idx, in, radix, &value);
  1169.       sprintf (buffer, "%d", value);
  1170.       sb_add_string (out, buffer);
  1171.  
  1172.       /* skip all undigsested letters */
  1173.       while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
  1174.         {
  1175.           sb_add_char (out, in->ptr[idx]);
  1176.           idx++;
  1177.         }
  1178.     }
  1179.       else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
  1180.     {
  1181.       char tchar = in->ptr[idx];
  1182.       /* copy entire names through quickly */
  1183.       sb_add_char (out, in->ptr[idx]);
  1184.       idx++;
  1185.       while (idx < in->len && in->ptr[idx] != tchar)
  1186.         {
  1187.           sb_add_char (out, in->ptr[idx]);
  1188.           idx++;
  1189.         }
  1190.     }
  1191.       else
  1192.     {
  1193.       /* nothing special, just pass it through */
  1194.       sb_add_char (out, in->ptr[idx]);
  1195.       idx++;
  1196.     }
  1197.     }
  1198.  
  1199. }
  1200.  
  1201. /* .end */
  1202. static void
  1203. do_end (in)
  1204.      sb *in;
  1205. {
  1206.   had_end = 1;
  1207.   if (mri)
  1208.     fprintf (outfile, "%s\n", sb_name (in));
  1209. }
  1210.  
  1211. /* .assign */
  1212.  
  1213. static void
  1214. do_assign (again, idx, in)
  1215.      int again;
  1216.      int idx;
  1217.      sb *in;
  1218. {
  1219.   /* stick label in symbol table with following value */
  1220.   exp_t e;
  1221.   sb acc;
  1222.  
  1223.   sb_new (&acc);
  1224.   idx = exp_parse (idx, in, &e);
  1225.   exp_string (&e, &acc);
  1226.   hash_add_to_string_table (&assign_hash_table, &label, &acc, again);
  1227.   sb_kill (&acc);
  1228. }
  1229.  
  1230.  
  1231. /* .radix [b|q|d|h] */
  1232.  
  1233. static
  1234. void
  1235. do_radix (ptr)
  1236.      sb *ptr;
  1237. {
  1238.   int idx = sb_skip_white (0, ptr);
  1239.   switch (ptr->ptr[idx])
  1240.     {
  1241.     case 'B':
  1242.     case 'b':
  1243.       radix = 2;
  1244.       break;
  1245.     case 'q':
  1246.     case 'Q':
  1247.       radix = 8;
  1248.       break;
  1249.     case 'd':
  1250.     case 'D':
  1251.       radix = 10;
  1252.       break;
  1253.     case 'h':
  1254.     case 'H':
  1255.       radix = 16;
  1256.       break;
  1257.     default:
  1258.       ERROR ((stderr, "radix is %c must be one of b, q, d or h", radix));
  1259.     }
  1260. }
  1261.  
  1262.  
  1263. /* Parse off a .b, .w or .l */
  1264.  
  1265. static int
  1266. get_opsize (idx, in, size)
  1267.      int idx;
  1268.      sb *in;
  1269.      int *size;
  1270. {
  1271.   *size = 4;
  1272.   if (in->ptr[idx] == '.')
  1273.     {
  1274.       idx++;
  1275.     }
  1276.   switch (in->ptr[idx])
  1277.     {
  1278.     case 'b':
  1279.     case 'B':
  1280.       *size = 1;
  1281.       break;
  1282.     case 'w':
  1283.     case 'W':
  1284.       *size = 2;
  1285.       break;
  1286.     case 'l':
  1287.     case 'L':
  1288.       *size = 4;
  1289.       break;
  1290.     case ' ':
  1291.     case '\t':
  1292.       break;
  1293.     default:
  1294.       ERROR ((stderr, "size must be one of b, w or l, is %c.\n", in->ptr[idx]));
  1295.       break;
  1296.     }
  1297.   idx++;
  1298.  
  1299.   return idx;
  1300. }
  1301.  
  1302. static 
  1303. int eol(idx, line)
  1304.      int idx;
  1305.      sb *line;
  1306. {
  1307.   idx = sb_skip_white (idx, line);
  1308.   if (idx < line->len 
  1309.       && ISCOMMENTCHAR(line->ptr[idx]))
  1310.     return 1;
  1311.   if (idx >= line->len)
  1312.     return 1;
  1313.   return 0;
  1314. }
  1315.  
  1316. /* .data [.b|.w|.l] <data>* 
  1317.     or d[bwl] <data>* */
  1318.  
  1319. static void
  1320. do_data (idx, in, size)
  1321.      int idx;
  1322.      sb *in;
  1323.      int size;
  1324. {
  1325.   int opsize = 4;
  1326.   char *opname = ".yikes!";
  1327.   sb acc;
  1328.   sb_new (&acc);
  1329.  
  1330.   if (!size) 
  1331.     {
  1332.       idx = get_opsize (idx, in, &opsize);
  1333.     }
  1334.   else {
  1335.     opsize = size;
  1336.   }
  1337.   switch (opsize)
  1338.     {
  1339.     case 4:
  1340.       opname = ".long";
  1341.       break;
  1342.     case 2:
  1343.       opname = ".short";
  1344.       break;
  1345.     case 1:
  1346.       opname = ".byte";
  1347.       break;
  1348.     }
  1349.  
  1350.  
  1351.   fprintf (outfile, "%s\t", opname);
  1352.  
  1353.   idx =   sb_skip_white (idx, in);
  1354.  
  1355.   if (alternate 
  1356.       && idx < in->len 
  1357.       && in->ptr[idx] == '"')
  1358.     {
  1359.       int i;
  1360.       idx = getstring (idx, in, &acc);
  1361.       for (i = 0; i < acc.len; i++)
  1362.     {
  1363.       if (i)
  1364.         fprintf(outfile,",");
  1365.       fprintf (outfile, "%d", acc.ptr[i]);
  1366.     }
  1367.     }
  1368.   else 
  1369.     {
  1370.       while (!eol (idx, in))
  1371.     {
  1372.       exp_t e;
  1373.       idx = exp_parse (idx, in, &e);
  1374.       exp_string (&e, &acc);
  1375.       sb_add_char (&acc, 0);
  1376.       fprintf (outfile, acc.ptr);
  1377.       if (idx < in->len && in->ptr[idx] == ',')
  1378.         {
  1379.           fprintf (outfile, ",");
  1380.           idx++;
  1381.         }
  1382.     }
  1383.     }
  1384.   sb_kill (&acc);
  1385.   sb_print_at (outfile, idx, in);
  1386.   fprintf (outfile, "\n");
  1387. }
  1388.  
  1389. /* .datab [.b|.w|.l] <repeat>,<fill> */
  1390.  
  1391. static void
  1392. do_datab (idx, in)
  1393.      int idx;
  1394.      sb *in;
  1395. {
  1396.   int opsize;
  1397.   int repeat;
  1398.   int fill;
  1399.  
  1400.   idx = get_opsize (idx, in, &opsize);
  1401.  
  1402.   idx = exp_get_abs ("datab repeat must be constant.\n", idx, in, &repeat);
  1403.   idx = sb_skip_comma (idx, in);
  1404.   idx = exp_get_abs ("datab data must be absolute.\n", idx, in, &fill);
  1405.  
  1406.   fprintf (outfile, ".fill\t%d,%d,%d\n", repeat, opsize, fill);
  1407. }
  1408.  
  1409. /* .align <size> */
  1410.  
  1411. static void
  1412. do_align (idx, in)
  1413.      int idx;
  1414.      sb *in;
  1415. {
  1416.   int al, have_fill, fill;
  1417.  
  1418.   idx = exp_get_abs ("align needs absolute expression.\n", idx, in, &al);
  1419.   idx = sb_skip_white (idx, in);
  1420.   have_fill = 0;
  1421.   fill = 0;
  1422.   if (! eol (idx, in))
  1423.     {
  1424.       idx = sb_skip_comma (idx, in);
  1425.       idx = exp_get_abs (".align needs absolute fill value.\n", idx, in,
  1426.              &fill);
  1427.       have_fill = 1;
  1428.     }
  1429.  
  1430.   if (al != 1
  1431.       && al != 2
  1432.       && al != 4)
  1433.     WARNING ((stderr, "alignment must be one of 1, 2 or 4.\n"));
  1434.  
  1435.   fprintf (outfile, ".align    %d", al);
  1436.   if (have_fill)
  1437.     fprintf (outfile, ",%d", fill);
  1438.   fprintf (outfile, "\n");
  1439. }
  1440.  
  1441. /* .res[.b|.w|.l] <size> */
  1442.  
  1443. static void
  1444. do_res (idx, in, type)
  1445.      int idx;
  1446.      sb *in;
  1447.      int type;
  1448. {
  1449.   int size = 4;
  1450.   int count = 0;
  1451.  
  1452.   idx = get_opsize (idx, in, &size);
  1453.   while (!eol(idx, in))
  1454.     {
  1455.       idx = sb_skip_white (idx, in);
  1456.       if (in->ptr[idx] == ',')
  1457.     idx++;
  1458.       idx = exp_get_abs ("res needs absolute expression for fill count.\n", idx, in, &count);
  1459.  
  1460.       if (type == 'c' || type == 'z')
  1461.     count++;
  1462.  
  1463.       fprintf (outfile, ".space    %d\n", count * size);
  1464.     }
  1465. }
  1466.  
  1467.  
  1468. /* .export */
  1469.  
  1470. static void
  1471. do_export (in)
  1472.      sb *in;
  1473. {
  1474.   fprintf (outfile, ".global    %s\n", sb_name (in));
  1475. }
  1476.  
  1477. /* .print [list] [nolist] */
  1478.  
  1479. static void
  1480. do_print (idx, in)
  1481.      int idx;
  1482.      sb *in;
  1483. {
  1484.   idx = sb_skip_white (idx, in);
  1485.   while (idx < in->len)
  1486.     {
  1487.       if (strncasecmp (in->ptr + idx, "LIST", 4) == 0)
  1488.     {
  1489.       fprintf (outfile, ".list\n");
  1490.       idx += 4;
  1491.     }
  1492.       else if (strncasecmp (in->ptr + idx, "NOLIST", 6) == 0)
  1493.     {
  1494.       fprintf (outfile, ".nolist\n");
  1495.       idx += 6;
  1496.     }
  1497.       idx++;
  1498.     }
  1499. }
  1500.  
  1501. /* .head */
  1502. static void
  1503. do_heading (idx, in)
  1504.      int idx;
  1505.      sb *in;
  1506. {
  1507.   sb head;
  1508.   sb_new (&head);
  1509.   idx = getstring (idx, in, &head);
  1510.   fprintf (outfile, ".title    \"%s\"\n", sb_name (&head));
  1511.   sb_kill (&head);
  1512. }
  1513.  
  1514. /* .page */
  1515.  
  1516. static void
  1517. do_page ()
  1518. {
  1519.   fprintf (outfile, ".eject\n");
  1520. }
  1521.  
  1522. /* .form [lin=<value>] [col=<value>] */
  1523. static void
  1524. do_form (idx, in)
  1525.      int idx;
  1526.      sb *in;
  1527. {
  1528.   int lines = 60;
  1529.   int columns = 132;
  1530.   idx = sb_skip_white (idx, in);
  1531.  
  1532.   while (idx < in->len)
  1533.     {
  1534.  
  1535.       if (strncasecmp (in->ptr + idx, "LIN=", 4) == 0)
  1536.     {
  1537.       idx += 4;
  1538.       idx = exp_get_abs ("form LIN= needs absolute expresssion.\n", idx, in, &lines);
  1539.     }
  1540.  
  1541.       if (strncasecmp (in->ptr + idx, "COL=", 4) == 0)
  1542.     {
  1543.       idx += 4;
  1544.       idx = exp_get_abs ("form COL= needs absolute expresssion.\n", idx, in, &columns);
  1545.     }
  1546.  
  1547.       idx++;
  1548.     }
  1549.   fprintf (outfile, ".psize %d,%d\n", lines, columns);
  1550.  
  1551. }
  1552.  
  1553.  
  1554. /* Fetch string from the input stream,
  1555.    rules:
  1556.     'Bxyx<whitespace>      -> return 'Bxyza
  1557.     %<char>        -> return string of decimal value of x
  1558.     "<string>"        -> return string
  1559.     xyx<whitespace>     -> return xyz
  1560. */
  1561. static int
  1562. get_any_string (idx, in, out, expand, pretend_quoted)
  1563.      int idx;
  1564.      sb *in;
  1565.      sb *out;
  1566.      int expand;
  1567.      int pretend_quoted;
  1568. {
  1569.   sb_reset (out);
  1570.   idx = sb_skip_white (idx, in);
  1571.  
  1572.   if (idx < in->len)
  1573.     {
  1574.       if (in->len > 2 && in->ptr[idx+1] == '\'' && ISBASE (in->ptr[idx]))
  1575.     {
  1576.       while (!ISSEP (in->ptr[idx]))
  1577.         sb_add_char (out, in->ptr[idx++]);
  1578.     }
  1579.       else if (in->ptr[idx] == '%'
  1580.            && alternate
  1581.            && expand)
  1582.     {
  1583.       int val;
  1584.       char buf[20];
  1585.       /* Turns the next expression into a string */
  1586.       idx = exp_get_abs ("% operator needs absolute expression",
  1587.                  idx + 1,
  1588.                  in,
  1589.                  &val);
  1590.       sprintf(buf, "%d", val);
  1591.       sb_add_string (out, buf);
  1592.     }
  1593.       else if (in->ptr[idx] == '"'
  1594.            || in->ptr[idx] == '<'
  1595.            || (alternate && in->ptr[idx] == '\''))
  1596.     {
  1597.       if (alternate && expand)
  1598.         {
  1599.           /* Keep the quotes */
  1600.           sb_add_char (out,  '\"');
  1601.             
  1602.           idx =  getstring (idx, in, out);
  1603.           sb_add_char (out,  '\"');
  1604.  
  1605.         }
  1606.       else {
  1607.         idx = getstring (idx, in, out);
  1608.       }
  1609.     }
  1610.       else 
  1611.     {
  1612.       while (idx < in->len 
  1613.          && (in->ptr[idx] == '"'
  1614.              || in->ptr[idx] == '\''
  1615.              || pretend_quoted 
  1616.              || !ISSEP (in->ptr[idx])))
  1617.         {
  1618.           if (in->ptr[idx] == '"' 
  1619.           || in->ptr[idx] == '\'')
  1620.         {
  1621.           char tchar = in->ptr[idx];
  1622.           sb_add_char (out, in->ptr[idx++]);
  1623.           while (idx < in->len
  1624.              && in->ptr[idx] != tchar)
  1625.             sb_add_char (out, in->ptr[idx++]);            
  1626.           if (idx == in->len)
  1627.             return idx;          
  1628.         }
  1629.           sb_add_char (out, in->ptr[idx++]);
  1630.         }
  1631.     }
  1632.     }
  1633.  
  1634.   return idx;
  1635. }
  1636.  
  1637.  
  1638. /* skip along sb in starting at idx, suck off whitespace a ( and more
  1639.    whitespace.  return the idx of the next char */
  1640.  
  1641. static int
  1642. skip_openp (idx, in)
  1643.      int idx;
  1644.      sb *in;
  1645. {
  1646.   idx = sb_skip_white (idx, in);
  1647.   if (in->ptr[idx] != '(')
  1648.     ERROR ((stderr, "misplaced ( .\n"));
  1649.   idx = sb_skip_white (idx + 1, in);
  1650.   return idx;
  1651. }
  1652.  
  1653. /* skip along sb in starting at idx, suck off whitespace a ) and more
  1654.    whitespace.  return the idx of the next char */
  1655.  
  1656. static int
  1657. skip_closep (idx, in)
  1658.      int idx;
  1659.      sb *in;
  1660. {
  1661.   idx = sb_skip_white (idx, in);
  1662.   if (in->ptr[idx] != ')')
  1663.     ERROR ((stderr, "misplaced ).\n"));
  1664.   idx = sb_skip_white (idx + 1, in);
  1665.   return idx;
  1666. }
  1667.  
  1668. /* .len */
  1669.  
  1670. static int
  1671. dolen (idx, in, out)
  1672.      int idx;
  1673.      sb *in;
  1674.      sb *out;
  1675. {
  1676.  
  1677.   sb stringout;
  1678.   char buffer[10];
  1679.  
  1680.   sb_new (&stringout);
  1681.   idx = skip_openp (idx, in);
  1682.   idx = get_and_process (idx, in, &stringout);
  1683.   idx = skip_closep (idx, in);
  1684.   sprintf (buffer, "%d", stringout.len);
  1685.   sb_add_string (out, buffer);
  1686.  
  1687.   sb_kill (&stringout);
  1688.   return idx;
  1689. }
  1690.  
  1691.  
  1692. /* .instr */
  1693.  
  1694. static
  1695. int
  1696. doinstr (idx, in, out)
  1697.      int idx;
  1698.      sb *in;
  1699.      sb *out;
  1700. {
  1701.   sb string;
  1702.   sb search;
  1703.   int i;
  1704.   int start;
  1705.   int res;
  1706.   char buffer[10];
  1707.  
  1708.   sb_new (&string);
  1709.   sb_new (&search);
  1710.   idx = skip_openp (idx, in);
  1711.   idx = get_and_process (idx, in, &string);
  1712.   idx = sb_skip_comma (idx, in);
  1713.   idx = get_and_process (idx, in, &search);
  1714.   idx = sb_skip_comma (idx, in);
  1715.   if (isdigit (in->ptr[idx]))
  1716.     {
  1717.       idx = exp_get_abs (".instr needs absolute expresson.\n", idx, in, &start);
  1718.     }
  1719.   else
  1720.     {
  1721.       start = 0;
  1722.     }
  1723.   idx = skip_closep (idx, in);
  1724.   res = -1;
  1725.   for (i = start; i < string.len; i++)
  1726.     {
  1727.       if (strncmp (string.ptr + i, search.ptr, search.len) == 0)
  1728.     {
  1729.       res = i;
  1730.       break;
  1731.     }
  1732.     }
  1733.   sprintf (buffer, "%d", res);
  1734.   sb_add_string (out, buffer);
  1735.   sb_kill (&string);
  1736.   sb_kill (&search);
  1737.   return idx;
  1738. }
  1739.  
  1740.  
  1741. static int
  1742. dosubstr (idx, in, out)
  1743.      int idx;
  1744.      sb *in;
  1745.      sb *out;
  1746. {
  1747.   sb string;
  1748.   int pos;
  1749.   int len;
  1750.   sb_new (&string);
  1751.  
  1752.   idx = skip_openp (idx, in);
  1753.   idx = get_and_process (idx, in, &string);
  1754.   idx = sb_skip_comma (idx, in);
  1755.   idx = exp_get_abs ("need absolute position.\n", idx, in, &pos);
  1756.   idx = sb_skip_comma (idx, in);
  1757.   idx = exp_get_abs ("need absolute length.\n", idx, in, &len);
  1758.   idx = skip_closep (idx, in);
  1759.  
  1760.  
  1761.   if (len < 0 || pos < 0 ||
  1762.       pos > string.len
  1763.       || pos + len > string.len)
  1764.     {
  1765.       sb_add_string (out, " ");
  1766.     }
  1767.   else 
  1768.     {
  1769.       sb_add_char (out, '"');
  1770.       while (len > 0)
  1771.     {
  1772.       sb_add_char (out, string.ptr[pos++]);
  1773.       len--;
  1774.     }
  1775.       sb_add_char (out, '"');
  1776.     }
  1777.   sb_kill(&string);
  1778.   return idx;
  1779. }
  1780.  
  1781. /* scan line, change tokens in the hash table to their replacements */
  1782. static void
  1783. process_assigns (idx, in, buf)
  1784.      int idx;
  1785.      sb *in;
  1786.      sb *buf;
  1787. {
  1788.   while (idx < in->len)
  1789.     {
  1790.       hash_entry *ptr;
  1791.       if (in->ptr[idx] == '\\'
  1792.       && idx + 1 < in->len
  1793.       && in->ptr[idx + 1] == '(')
  1794.     {
  1795.       do
  1796.         {
  1797.           sb_add_char (buf, in->ptr[idx]);
  1798.           idx++;
  1799.         }
  1800.       while (idx < in->len && in->ptr[idx - 1] != ')');
  1801.     }
  1802.       else if (in->ptr[idx] == '\\'
  1803.       && idx + 1 < in->len
  1804.       && in->ptr[idx + 1] == '&')
  1805.     {
  1806.       idx = condass_lookup_name (in, idx + 2, buf, 1);
  1807.     }
  1808.       else if (in->ptr[idx] == '\\'
  1809.            && idx + 1 < in->len
  1810.            && in->ptr[idx + 1] == '$')
  1811.     {
  1812.       idx = condass_lookup_name (in, idx + 2, buf, 0);
  1813.     }
  1814.       else if (idx + 3 < in->len
  1815.            && in->ptr[idx] == '.'
  1816.            && toupper ((unsigned char) in->ptr[idx + 1]) == 'L'
  1817.            && toupper ((unsigned char) in->ptr[idx + 2]) == 'E'
  1818.            && toupper ((unsigned char) in->ptr[idx + 3]) == 'N')
  1819.     idx = dolen (idx + 4, in, buf);
  1820.       else if (idx + 6 < in->len
  1821.            && in->ptr[idx] == '.'
  1822.            && toupper ((unsigned char) in->ptr[idx + 1]) == 'I'
  1823.            && toupper ((unsigned char) in->ptr[idx + 2]) == 'N'
  1824.            && toupper ((unsigned char) in->ptr[idx + 3]) == 'S'
  1825.            && toupper ((unsigned char) in->ptr[idx + 4]) == 'T'
  1826.            && toupper ((unsigned char) in->ptr[idx + 5]) == 'R')
  1827.     idx = doinstr (idx + 6, in, buf);
  1828.       else if (idx + 7 < in->len
  1829.            && in->ptr[idx] == '.'
  1830.            && toupper ((unsigned char) in->ptr[idx + 1]) == 'S'
  1831.            && toupper ((unsigned char) in->ptr[idx + 2]) == 'U'
  1832.            && toupper ((unsigned char) in->ptr[idx + 3]) == 'B'
  1833.            && toupper ((unsigned char) in->ptr[idx + 4]) == 'S'
  1834.            && toupper ((unsigned char) in->ptr[idx + 5]) == 'T'
  1835.            && toupper ((unsigned char) in->ptr[idx + 6]) == 'R')
  1836.     idx = dosubstr (idx + 7, in, buf);
  1837.       else if (ISFIRSTCHAR (in->ptr[idx]))
  1838.     {
  1839.       /* may be a simple name subsitution, see if we have a word */
  1840.       sb acc;
  1841.       int cur = idx + 1;
  1842.       while (cur < in->len
  1843.          && (ISNEXTCHAR (in->ptr[cur])))
  1844.         cur++;
  1845.  
  1846.       sb_new (&acc);
  1847.       sb_add_buffer (&acc, in->ptr + idx, cur - idx);
  1848.       ptr = hash_lookup (&assign_hash_table, &acc);
  1849.       if (ptr)
  1850.         {
  1851.           /* Found a definition for it */
  1852.           sb_add_sb (buf, &ptr->value.s);
  1853.         }
  1854.       else
  1855.         {
  1856.           /* No definition, just copy the word */
  1857.           sb_add_sb (buf, &acc);
  1858.         }
  1859.       sb_kill (&acc);
  1860.       idx = cur;
  1861.     }
  1862.       else
  1863.     {
  1864.       sb_add_char (buf, in->ptr[idx++]);
  1865.     }
  1866.     }
  1867. }
  1868.  
  1869. static int
  1870. get_and_process (idx, in, out)
  1871.      int idx;
  1872.      sb *in;
  1873.      sb *out;
  1874. {
  1875.   sb t;
  1876.   sb_new (&t);
  1877.   idx = get_any_string (idx, in, &t, 1, 0);
  1878.   process_assigns (0, &t, out);
  1879.   sb_kill (&t);
  1880.   return idx;
  1881. }
  1882.  
  1883. static
  1884. void
  1885. process_file ()
  1886. {
  1887.   sb line;
  1888.   sb t1, t2;
  1889.   sb acc;
  1890.   sb label_in;
  1891.   int more;
  1892.  
  1893.   sb_new (&line);
  1894.   sb_new (&t1);
  1895.   sb_new (&t2);
  1896.   sb_new(&acc);
  1897.   sb_new (&label_in);
  1898.   sb_reset (&line);
  1899.   more = get_line (&line);
  1900.   while (more)
  1901.     {
  1902.       /* Find any label and pseudo op that we're intested in */
  1903.       int l;
  1904.       if (line.len == 0)
  1905.     {
  1906.       if (condass_on ())
  1907.         fprintf (outfile, "\n");
  1908.     }
  1909.       else if (mri
  1910.            && (line.ptr[0] == '*'
  1911.            || line.ptr[0] == '!'))
  1912.     {
  1913.       /* MRI line comment.  */
  1914.       fprintf (outfile, sb_name (&line));
  1915.     }
  1916.       else
  1917.     {
  1918.       l = grab_label (&line, &label_in);
  1919.       sb_reset (&label);            
  1920.       if (label_in.len)
  1921.         {
  1922.           /* Munge any label */
  1923.  
  1924.           
  1925.           process_assigns (0, &label_in, &label);
  1926.         }
  1927.  
  1928.       if (line.ptr[l] == ':')
  1929.         l++;
  1930.       while (ISWHITE (line.ptr[l]) && l < line.len)
  1931.         l++;
  1932.  
  1933.       if (l < line.len)
  1934.         {
  1935.           if (process_pseudo_op (l, &line, &acc))
  1936.         {
  1937.  
  1938.  
  1939.  
  1940.         }
  1941.           else if (condass_on ())
  1942.         {
  1943.           if (macro_op (l, &line))
  1944.             {
  1945.  
  1946.  
  1947.             }
  1948.           else
  1949.             {
  1950.               {
  1951.             if (label.len)
  1952.               {
  1953.                 fprintf (outfile, "%s:\t", sb_name (&label));
  1954.               }
  1955.             else
  1956.               fprintf (outfile, "\t");
  1957.             sb_reset(&t1);
  1958.             process_assigns (l, &line, &t1);
  1959.             sb_reset (&t2);
  1960.             change_base (0, &t1, &t2);
  1961.             fprintf (outfile, "%s\n", sb_name (&t2));
  1962.               }
  1963.             }
  1964.         }
  1965.         }
  1966.       else {
  1967.         /* Only a label on this line */
  1968.         if (label.len && condass_on())
  1969.           {
  1970.         fprintf (outfile, "%s:\n", sb_name (&label));
  1971.           }
  1972.       }
  1973.     }
  1974.  
  1975.       if (had_end)
  1976.     break;
  1977.       sb_reset (&line);
  1978.       more = get_line (&line);
  1979.     }
  1980.  
  1981.   if (!had_end && !mri)
  1982.     WARNING ((stderr, "END missing from end of file.\n"));
  1983. }
  1984.  
  1985.  
  1986.  
  1987.  
  1988.  
  1989. static void
  1990. free_old_entry (ptr)
  1991.      hash_entry *ptr;
  1992. {
  1993.   if (ptr)
  1994.     {
  1995.       if (ptr->type == hash_string)
  1996.     sb_kill(&ptr->value.s);
  1997.     }
  1998. }
  1999.  
  2000. /* name: .ASSIGNA <value> */
  2001.  
  2002. static void
  2003. do_assigna (idx, in)
  2004.      int idx;
  2005.      sb *in;
  2006. {
  2007.   sb tmp;
  2008.   int val;
  2009.   sb_new (&tmp);
  2010.  
  2011.   process_assigns (idx, in, &tmp);
  2012.   idx = exp_get_abs (".ASSIGNA needs constant expression argument.\n", 0, &tmp, &val);
  2013.  
  2014.   if (!label.len)
  2015.     {
  2016.       ERROR ((stderr, ".ASSIGNA without label.\n"));
  2017.     }
  2018.   else
  2019.     {
  2020.       hash_entry *ptr = hash_create (&vars, &label);
  2021.       free_old_entry (ptr);
  2022.       ptr->type = hash_integer;
  2023.       ptr->value.i = val;
  2024.     }
  2025.   sb_kill (&tmp);
  2026. }
  2027.  
  2028. /* name: .ASSIGNC <string> */
  2029.  
  2030. static void
  2031. do_assignc (idx, in)
  2032.      int idx;
  2033.      sb *in;
  2034. {
  2035.   sb acc;
  2036.   sb_new (&acc);
  2037.   idx = getstring (idx, in, &acc);
  2038.  
  2039.   if (!label.len)
  2040.     {
  2041.       ERROR ((stderr, ".ASSIGNS without label.\n"));
  2042.     }
  2043.   else
  2044.     {
  2045.       hash_entry *ptr = hash_create (&vars, &label);
  2046.       free_old_entry (ptr);
  2047.       ptr->type = hash_string;
  2048.       sb_new (&ptr->value.s);
  2049.       sb_add_sb (&ptr->value.s, &acc);
  2050.     }
  2051.   sb_kill (&acc);
  2052. }
  2053.  
  2054.  
  2055. /* name: .REG (reg) */
  2056.  
  2057. static void
  2058. do_reg (idx, in)
  2059.      int idx;
  2060.      sb *in;
  2061. {
  2062.   /* remove reg stuff from inside parens */
  2063.   sb what;
  2064.   if (!mri)
  2065.     idx = skip_openp (idx, in);
  2066.   else
  2067.     idx = sb_skip_white (idx, in);
  2068.   sb_new (&what);
  2069.   while (idx < in->len
  2070.      && (mri
  2071.          ? ! eol (idx, in)
  2072.          : in->ptr[idx] != ')'))
  2073.     {
  2074.       sb_add_char (&what, in->ptr[idx]);
  2075.       idx++;
  2076.     }
  2077.   hash_add_to_string_table (&assign_hash_table, &label, &what, 1);
  2078.   sb_kill (&what);
  2079. }
  2080.  
  2081.  
  2082. static int
  2083. condass_lookup_name (inbuf, idx, out, warn)
  2084.      sb *inbuf;
  2085.      int idx;
  2086.      sb *out;
  2087.      int warn;
  2088. {
  2089.   hash_entry *ptr;
  2090.   sb condass_acc;
  2091.   sb_new (&condass_acc);
  2092.  
  2093.   while (idx < inbuf->len
  2094.      && ISNEXTCHAR (inbuf->ptr[idx]))
  2095.     {
  2096.       sb_add_char (&condass_acc, inbuf->ptr[idx++]);
  2097.     }
  2098.  
  2099.   if (inbuf->ptr[idx] == '\'')
  2100.     idx++;
  2101.   ptr = hash_lookup (&vars, &condass_acc);
  2102.  
  2103.  
  2104.   if (!ptr)
  2105.     {
  2106.       if (warn) 
  2107.     {
  2108.       WARNING ((stderr, "Can't find preprocessor variable %s.\n", sb_name (&condass_acc)));
  2109.     }
  2110.       else 
  2111.     {
  2112.       sb_add_string (out, "0");
  2113.     }
  2114.     }
  2115.   else
  2116.     {
  2117.       if (ptr->type == hash_integer)
  2118.     {
  2119.       char buffer[30];
  2120.       sprintf (buffer, "%d", ptr->value.i);
  2121.       sb_add_string (out, buffer);
  2122.     }
  2123.       else
  2124.     {
  2125.       sb_add_sb (out, &ptr->value.s);
  2126.     }
  2127.     }
  2128.   sb_kill (&condass_acc);
  2129.   return idx;
  2130. }
  2131.  
  2132. #define EQ 1
  2133. #define NE 2
  2134. #define GE 3
  2135. #define LT 4
  2136. #define LE 5
  2137. #define GT 6
  2138. #define NEVER 7
  2139.  
  2140. static int
  2141. whatcond (idx, in, val)
  2142.      int idx;
  2143.      sb *in;
  2144.      int *val;
  2145. {
  2146.   int cond;
  2147.  
  2148.   idx = sb_skip_white (idx, in);
  2149.   cond = NEVER;
  2150.   if (idx + 1 < in->len)
  2151.     {
  2152.       char *p;
  2153.       char a, b;
  2154.  
  2155.       p = in->ptr + idx;
  2156.       a = toupper ((unsigned char) p[0]);
  2157.       b = toupper ((unsigned char) p[1]);
  2158.       if (a == 'E' && b == 'Q')
  2159.     cond = EQ;
  2160.       else if (a == 'N' && b == 'E')
  2161.     cond = NE;
  2162.       else if (a == 'L' && b == 'T')
  2163.     cond = LT;
  2164.       else if (a == 'L' && b == 'E')
  2165.     cond = LE;
  2166.       else if (a == 'G' && b == 'T')
  2167.     cond = GT;
  2168.       else if (a == 'G' && b == 'E')
  2169.     cond = GE;
  2170.     }
  2171.   if (cond == NEVER)
  2172.     {
  2173.       ERROR ((stderr, "Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n"));
  2174.       cond = NEVER;
  2175.     }
  2176.   idx = sb_skip_white (idx + 2, in);
  2177.   *val = cond;
  2178.   return idx;
  2179. }
  2180.  
  2181. static int
  2182. istrue (idx, in)
  2183.      int idx;
  2184.      sb *in;
  2185. {
  2186.   int res;
  2187.   sb acc_a;
  2188.   sb cond;
  2189.   sb acc_b;
  2190.   sb_new (&acc_a);
  2191.   sb_new (&cond);
  2192.   sb_new (&acc_b);
  2193.   idx = sb_skip_white (idx, in);
  2194.  
  2195.   if (in->ptr[idx] == '"')
  2196.     {
  2197.       int cond;
  2198.       int same;
  2199.       /* This is a string comparision */
  2200.       idx = getstring (idx, in, &acc_a);
  2201.       idx = whatcond (idx, in, &cond);
  2202.       idx = getstring (idx, in, &acc_b);
  2203.       same = acc_a.len == acc_b.len && (strncmp (acc_a.ptr, acc_b.ptr, acc_a.len) == 0);
  2204.  
  2205.       if (cond != EQ && cond != NE)
  2206.     {
  2207.       ERROR ((stderr, "Comparison operator for strings must be EQ or NE\n"));
  2208.       res = 0;
  2209.     }
  2210.       else
  2211.     res = (cond != EQ) ^ same;
  2212.     }
  2213.   else
  2214.     /* This is a numeric expression */
  2215.     {
  2216.       int vala;
  2217.       int valb;
  2218.       int cond;
  2219.       idx = exp_get_abs ("Conditional operator must have absolute operands.\n", idx, in, &vala);
  2220.       idx = whatcond (idx, in, &cond);
  2221.       idx = sb_skip_white (idx, in);
  2222.       if (in->ptr[idx] == '"')
  2223.     {
  2224.       WARNING ((stderr, "String compared against expression.\n"));
  2225.       res = 0;
  2226.     }
  2227.       else
  2228.     {
  2229.       idx = exp_get_abs ("Conditional operator must have absolute operands.\n", idx, in, &valb);
  2230.       switch (cond)
  2231.         {
  2232.         default:
  2233.           res = 42;
  2234.           break;
  2235.         case EQ:
  2236.           res = vala == valb;
  2237.           break;
  2238.         case NE:
  2239.           res = vala != valb;
  2240.           break;
  2241.         case LT:
  2242.           res = vala < valb;
  2243.           break;
  2244.         case LE:
  2245.           res = vala <= valb;
  2246.           break;
  2247.         case GT:
  2248.           res = vala > valb;
  2249.           break;
  2250.         case GE:
  2251.           res = vala >= valb;
  2252.           break;
  2253.         case NEVER:
  2254.           res = 0;
  2255.           break;
  2256.         }
  2257.     }
  2258.     }
  2259.  
  2260.   sb_kill (&acc_a);
  2261.   sb_kill (&cond);
  2262.   sb_kill (&acc_b);
  2263.   return res;
  2264. }
  2265.  
  2266. /* .AIF */
  2267. static void
  2268. do_aif (idx, in)
  2269.      int idx;
  2270.      sb *in;
  2271. {
  2272.   if (ifi >= IFNESTING)
  2273.     {
  2274.       FATAL ((stderr, "AIF nesting unreasonable.\n"));
  2275.     }
  2276.   ifi++;
  2277.   ifstack[ifi].on = ifstack[ifi-1].on ? istrue (idx, in) : 0;
  2278.   ifstack[ifi].hadelse = 0;
  2279. }
  2280.  
  2281.  
  2282. /* .AELSE */
  2283. static void
  2284. do_aelse ()
  2285. {
  2286.   ifstack[ifi].on = ifstack[ifi-1].on ? !ifstack[ifi].on : 0;
  2287.   if (ifstack[ifi].hadelse)
  2288.     {
  2289.       ERROR ((stderr, "Multiple AELSEs in AIF.\n"));
  2290.     }
  2291.   ifstack[ifi].hadelse = 1;
  2292. }
  2293.  
  2294.  
  2295. /* .AENDI */
  2296. static void
  2297. do_aendi ()
  2298. {
  2299.   if (ifi != 0)
  2300.     {
  2301.       ifi--;
  2302.     }
  2303.   else
  2304.     {
  2305.       ERROR ((stderr, "AENDI without AIF.\n"));
  2306.     }
  2307. }
  2308.  
  2309. static int
  2310. condass_on ()
  2311. {
  2312.   return ifstack[ifi].on;
  2313. }
  2314.  
  2315. /* MRI IFEQ, IFNE, IFLT, IFLE, IFGE, IFGT.  */
  2316.  
  2317. static void
  2318. do_if (idx, in, cond)
  2319.      int idx;
  2320.      sb *in;
  2321.      int cond;
  2322. {
  2323.   int val;
  2324.   int res;
  2325.  
  2326.   if (ifi >= IFNESTING)
  2327.     {
  2328.       FATAL ((stderr, "IF nesting unreasonable.\n"));
  2329.     }
  2330.  
  2331.   idx = exp_get_abs ("Conditional operator must have absolute operands.\n",
  2332.              idx, in, &val);
  2333.   switch (cond)
  2334.     {
  2335.     default:
  2336.     case EQ: res = val == 0; break;
  2337.     case NE: res = val != 0; break;
  2338.     case LT: res = val <  0; break;
  2339.     case LE: res = val <= 0; break;
  2340.     case GE: res = val >= 0; break;
  2341.     case GT: res = val >  0; break;
  2342.     }
  2343.  
  2344.   ifi++;
  2345.   ifstack[ifi].on = ifstack[ifi-1].on ? res: 0;
  2346.   ifstack[ifi].hadelse = 0;
  2347. }
  2348.  
  2349. /* Get a string for the MRI IFC or IFNC pseudo-ops.  */
  2350.  
  2351. static int
  2352. get_mri_string (idx, in, val, terminator)
  2353.      int idx;
  2354.      sb *in;
  2355.      sb *val;
  2356.      int terminator;
  2357. {
  2358.   idx = sb_skip_white (idx, in);
  2359.  
  2360.   if (idx < in->len
  2361.       && in->ptr[idx] == '\'')
  2362.     {
  2363.       sb_add_char (val, '\'');
  2364.       for (++idx; idx < in->len; ++idx)
  2365.     {
  2366.       sb_add_char (val, in->ptr[idx]);
  2367.       if (in->ptr[idx] == '\'')
  2368.         {
  2369.           ++idx;
  2370.           if (idx >= in->len
  2371.           || in->ptr[idx] != '\'')
  2372.         break;
  2373.         }
  2374.     }
  2375.       idx = sb_skip_white (idx, in);
  2376.     }
  2377.   else
  2378.     {
  2379.       int i;
  2380.  
  2381.       while (idx < in->len
  2382.          && in->ptr[idx] != terminator)
  2383.     {
  2384.       sb_add_char (val, in->ptr[idx]);
  2385.       ++idx;
  2386.     }
  2387.       i = val->len - 1;
  2388.       while (i >= 0 && ISWHITE (val->ptr[i]))
  2389.     --i;
  2390.       val->len = i + 1;
  2391.     }
  2392.  
  2393.   return idx;
  2394. }
  2395.  
  2396. /* MRI IFC, IFNC.  */
  2397.  
  2398. static void
  2399. do_ifc (idx, in, ifnc)
  2400.      int idx;
  2401.      sb *in;
  2402.      int ifnc;
  2403. {
  2404.   sb first;
  2405.   sb second;
  2406.   int res;
  2407.  
  2408.   if (ifi >= IFNESTING)
  2409.     {
  2410.       FATAL ((stderr, "IF nesting unreasonable.\n"));
  2411.     }
  2412.  
  2413.   sb_new (&first);
  2414.   sb_new (&second);
  2415.  
  2416.   idx = get_mri_string (idx, in, &first, ',');
  2417.  
  2418.   if (idx >= in->len || in->ptr[idx] != ',')
  2419.     {
  2420.       ERROR ((stderr, "Bad format for IF or IFNC.\n"));
  2421.       return;
  2422.     }
  2423.  
  2424.   idx = get_mri_string (idx + 1, in, &second, ';');
  2425.  
  2426.   res = (first.len == second.len
  2427.      && strncmp (first.ptr, second.ptr, first.len) == 0);
  2428.   res ^= ifnc;
  2429.  
  2430.   ifi++;
  2431.   ifstack[ifi].on = ifstack[ifi-1].on ? res : 0;
  2432.   ifstack[ifi].hadelse = 0;
  2433. }
  2434.  
  2435. /* .ENDR */
  2436. static void
  2437. do_aendr ()
  2438. {
  2439.   if (!mri)
  2440.     ERROR ((stderr, "AENDR without a AREPEAT.\n"));
  2441.   else
  2442.     ERROR ((stderr, "ENDR without a REPT.\n"));
  2443. }
  2444.  
  2445. /* .AWHILE */
  2446.  
  2447. static
  2448. void
  2449. do_awhile (idx, in)
  2450.      int idx;
  2451.      sb *in;
  2452. {
  2453.   int line = linecount ();
  2454.   sb exp;
  2455.   sb sub;
  2456.   int doit;
  2457.  
  2458.   sb_new (&sub);
  2459.   sb_new (&exp);
  2460.  
  2461.   process_assigns (idx, in, &exp);
  2462.   doit = istrue (0, &exp);
  2463.  
  2464.   if (! buffer_and_nest ("AWHILE", "AENDW", &sub, get_line))
  2465.     FATAL ((stderr, "AWHILE without a AENDW at %d.\n", line - 1));
  2466.  
  2467.   /* Turn
  2468.          .AWHILE exp
  2469.          foo
  2470.     .AENDW
  2471.      into
  2472.         foo
  2473.     .AWHILE exp
  2474.     foo
  2475.     .ENDW
  2476.    */
  2477.  
  2478.   if (doit)
  2479.     {
  2480.       int index = include_next_index ();
  2481.  
  2482.       sb copy;
  2483.       sb_new (©);
  2484.       sb_add_sb (©, &sub);
  2485.       sb_add_sb (©, in);
  2486.       sb_add_string (©, "\n");
  2487.       sb_add_sb (©, &sub);
  2488.       sb_add_string (©, "\t.AENDW\n");
  2489.       /* Push another WHILE */
  2490.       include_buf (&exp, ©, include_while, index);
  2491.       sb_kill (©);
  2492.     }
  2493.   sb_kill (&exp);
  2494.   sb_kill (&sub);
  2495. }
  2496.  
  2497.  
  2498. /* .AENDW */
  2499.  
  2500. static void
  2501. do_aendw ()
  2502. {
  2503.   ERROR ((stderr, "AENDW without a AENDW.\n"));
  2504. }
  2505.  
  2506.  
  2507. /* .EXITM
  2508.    
  2509.    Pop things off the include stack until the type and index changes */
  2510.  
  2511. static void
  2512. do_exitm ()
  2513. {
  2514.   include_type type = sp->type;
  2515.   if (type == include_repeat
  2516.       || type == include_while
  2517.       || type == include_macro)
  2518.     {
  2519.       int index = sp->index;
  2520.       include_pop ();
  2521.       while (sp->index == index
  2522.          && sp->type == type)
  2523.     {
  2524.       include_pop ();
  2525.     }
  2526.     }
  2527. }
  2528.  
  2529. /* .AREPEAT */
  2530.  
  2531. static void
  2532. do_arepeat (idx, in)
  2533.      int idx;
  2534.      sb *in;
  2535. {
  2536.   int line = linecount ();
  2537.   sb exp;            /* buffer with expression in it */
  2538.   sb copy;            /* expanded repeat block */
  2539.   sb sub;            /* contents of AREPEAT */
  2540.   int rc;
  2541.   int ret;
  2542.   char buffer[30];
  2543.  
  2544.   sb_new (&exp);
  2545.   sb_new (©);
  2546.   sb_new (&sub);
  2547.   process_assigns (idx, in, &exp);
  2548.   idx = exp_get_abs ("AREPEAT must have absolute operand.\n", 0, &exp, &rc);
  2549.   if (!mri)
  2550.     ret = buffer_and_nest ("AREPEAT", "AENDR", &sub, get_line);
  2551.   else
  2552.     ret = buffer_and_nest ("REPT", "ENDR", &sub, get_line);
  2553.   if (! ret)
  2554.     FATAL ((stderr, "AREPEAT without a AENDR at %d.\n", line - 1));
  2555.   if (rc > 0)
  2556.     {
  2557.       /* Push back the text following the repeat, and another repeat block
  2558.      so
  2559.      .AREPEAT 20
  2560.      foo
  2561.      .AENDR
  2562.      gets turned into
  2563.      foo
  2564.      .AREPEAT 19
  2565.      foo
  2566.      .AENDR
  2567.      */
  2568.       int index = include_next_index ();
  2569.       sb_add_sb (©, &sub);
  2570.       if (rc > 1)
  2571.     {
  2572.       if (!mri)
  2573.         sprintf (buffer, "\t.AREPEAT    %d\n", rc - 1);
  2574.       else
  2575.         sprintf (buffer, "\tREPT    %d\n", rc - 1);
  2576.       sb_add_string (©, buffer);
  2577.       sb_add_sb (©, &sub);
  2578.       if (!mri)
  2579.         sb_add_string (©, "    .AENDR\n");
  2580.       else
  2581.         sb_add_string (©, "    ENDR\n");
  2582.     }
  2583.  
  2584.       include_buf (&exp, ©, include_repeat, index);
  2585.     }
  2586.   sb_kill (&exp);
  2587.   sb_kill (&sub);
  2588.   sb_kill (©);
  2589. }
  2590.  
  2591. /* .ENDM */
  2592.  
  2593. static void
  2594. do_endm ()
  2595. {
  2596.   ERROR ((stderr, ".ENDM without a matching .MACRO.\n"));
  2597. }
  2598.  
  2599. /* MRI IRP pseudo-op.  */
  2600.  
  2601. static void
  2602. do_irp (idx, in, irpc)
  2603.      int idx;
  2604.      sb *in;
  2605.      int irpc;
  2606. {
  2607.   const char *err;
  2608.   sb out;
  2609.  
  2610.   sb_new (&out);
  2611.  
  2612.   err = expand_irp (irpc, idx, in, &out, get_line, comment_char);
  2613.   if (err != NULL)
  2614.     ERROR ((stderr, "%s\n", err));
  2615.  
  2616.   fprintf (outfile, "%s", sb_terminate (&out));
  2617.  
  2618.   sb_kill (&out);
  2619. }
  2620.  
  2621. /* MACRO PROCESSING */
  2622.  
  2623. /* Parse off LOCAL n1, n2,... Invent a label name for it */
  2624. static
  2625. void 
  2626. do_local (idx, line)
  2627.      int idx;
  2628.      sb *line;
  2629. {
  2630.   ERROR ((stderr, "LOCAL outside of MACRO"));
  2631. }
  2632.  
  2633. static void
  2634. do_macro (idx, in)
  2635.      int idx;
  2636.      sb *in;
  2637. {
  2638.   const char *err;
  2639.   int line = linecount ();
  2640.  
  2641.   err = define_macro (idx, in, &label, get_line);
  2642.   if (err != NULL)
  2643.     ERROR ((stderr, "macro at line %d: %s\n", line - 1, err));
  2644. }
  2645.  
  2646. static int
  2647. macro_op (idx, in)
  2648.      int idx;
  2649.      sb *in;
  2650. {
  2651.   const char *err;
  2652.   sb out;
  2653.   sb name;
  2654.  
  2655.   if (! macro_defined)
  2656.     return 0;
  2657.  
  2658.   sb_terminate (in);
  2659.   if (! check_macro (in->ptr + idx, &out, comment_char, &err))
  2660.     return 0;
  2661.  
  2662.   if (err != NULL)
  2663.     ERROR ((stderr, "%s\n", err));
  2664.  
  2665.   sb_new (&name);
  2666.   sb_add_string (&name, "macro expansion");
  2667.  
  2668.   include_buf (&name, &out, include_macro, include_next_index ());
  2669.  
  2670.   sb_kill (&name);
  2671.   sb_kill (&out);
  2672.  
  2673.   return 1;
  2674. }
  2675.  
  2676. /* STRING HANDLING */
  2677.  
  2678. static int
  2679. getstring (idx, in, acc)
  2680.      int idx;
  2681.      sb *in;
  2682.      sb *acc;
  2683. {
  2684.   idx = sb_skip_white (idx, in);
  2685.  
  2686.   while (idx < in->len
  2687.      && (in->ptr[idx] == '"' 
  2688.          || in->ptr[idx] == '<' 
  2689.          || (in->ptr[idx] == '\'' && alternate)))
  2690.     {
  2691.       if (in->ptr[idx] == '<')
  2692.     {
  2693.       if (alternate || mri)
  2694.         {
  2695.           int nest = 0;
  2696.           idx++;
  2697.           while ((in->ptr[idx] != '>' || nest)
  2698.              && idx < in->len)
  2699.         {
  2700.           if (in->ptr[idx] == '!')
  2701.             {
  2702.               idx++  ;
  2703.               sb_add_char (acc, in->ptr[idx++]);
  2704.             }
  2705.           else {
  2706.             if (in->ptr[idx] == '>')
  2707.               nest--;
  2708.             if (in->ptr[idx] == '<')
  2709.               nest++;
  2710.             sb_add_char (acc, in->ptr[idx++]);
  2711.           }
  2712.         }
  2713.           idx++;
  2714.         }
  2715.       else {
  2716.         int code;
  2717.         idx++;
  2718.         idx = exp_get_abs ("Character code in string must be absolute expression.\n",
  2719.                    idx, in, &code);
  2720.         sb_add_char (acc, code);
  2721.  
  2722.         if (in->ptr[idx] != '>')
  2723.           ERROR ((stderr, "Missing > for character code.\n"));
  2724.         idx++;
  2725.       }
  2726.     }
  2727.       else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
  2728.     {
  2729.       char tchar = in->ptr[idx];
  2730.       idx++;
  2731.       while (idx < in->len)
  2732.         {
  2733.           if (alternate && in->ptr[idx] == '!')
  2734.         {
  2735.           idx++  ;
  2736.           sb_add_char (acc, in->ptr[idx++]);
  2737.         }
  2738.           else {
  2739.         if (in->ptr[idx] == tchar)
  2740.           {
  2741.             idx++;
  2742.             if (idx >= in->len || in->ptr[idx] != tchar)
  2743.               break;
  2744.           }
  2745.         sb_add_char (acc, in->ptr[idx]);
  2746.         idx++;
  2747.           }
  2748.         }
  2749.     }
  2750.     }
  2751.   
  2752.   return idx;
  2753. }
  2754.  
  2755. /* .SDATA[C|Z] <string> */
  2756.  
  2757. static
  2758. void
  2759. do_sdata (idx, in, type)
  2760.      int idx;
  2761.      sb *in;
  2762.      int type;
  2763. {
  2764.   int nc = 0;
  2765.   int pidx = -1;
  2766.   sb acc;
  2767.   sb_new (&acc);
  2768.   fprintf (outfile, ".byte\t");
  2769.  
  2770.   while (!eol (idx, in))
  2771.     {
  2772.       int i;
  2773.       sb_reset (&acc);
  2774.       idx = sb_skip_white (idx, in);
  2775.       while (!eol (idx, in))
  2776.     {
  2777.       pidx = idx = get_any_string (idx, in, &acc, 0, 1);
  2778.       if (type == 'c')
  2779.         {
  2780.           if (acc.len > 255)
  2781.         {
  2782.           ERROR ((stderr, "string for SDATAC longer than 255 characters (%d).\n", acc.len));
  2783.         }
  2784.           fprintf (outfile, "%d", acc.len);
  2785.           nc = 1;
  2786.         }
  2787.  
  2788.       for (i = 0; i < acc.len; i++)
  2789.         {
  2790.           if (nc)
  2791.         {
  2792.           fprintf (outfile, ",");
  2793.         }
  2794.           fprintf (outfile, "%d", acc.ptr[i]);
  2795.           nc = 1;
  2796.         }
  2797.  
  2798.       if (type == 'z')
  2799.         {
  2800.           if (nc)
  2801.         fprintf (outfile, ",");
  2802.           fprintf (outfile, "0");
  2803.         }
  2804.       idx = sb_skip_comma (idx, in);
  2805.       if (idx == pidx) break;
  2806.     }
  2807.       if (!alternate && in->ptr[idx] != ',' && idx != in->len)
  2808.     {
  2809.       fprintf (outfile, "\n");
  2810.       ERROR ((stderr, "illegal character in SDATA line (0x%x).\n", in->ptr[idx]));
  2811.       break;
  2812.     }
  2813.       idx++;
  2814.     }
  2815.   sb_kill (&acc);
  2816.   fprintf (outfile, "\n");
  2817. }
  2818.  
  2819. /* .SDATAB <count> <string> */
  2820.  
  2821. static void
  2822. do_sdatab (idx, in)
  2823.      int idx;
  2824.      sb *in;
  2825. {
  2826.   int repeat;
  2827.   int i;
  2828.   sb acc;
  2829.   sb_new (&acc);
  2830.  
  2831.   idx = exp_get_abs ("Must have absolute SDATAB repeat count.\n", idx, in, &repeat);
  2832.   if (repeat <= 0)
  2833.     {
  2834.       ERROR ((stderr, "Must have positive SDATAB repeat count (%d).\n", repeat));
  2835.       repeat = 1;
  2836.     }
  2837.  
  2838.   idx = sb_skip_comma (idx, in);
  2839.   idx = getstring (idx, in, &acc);
  2840.  
  2841.   for (i = 0; i < repeat; i++)
  2842.     {
  2843.       if (i)
  2844.     fprintf (outfile, "\t");
  2845.       fprintf (outfile, ".byte\t");
  2846.       sb_print (outfile, &acc);
  2847.       fprintf (outfile, "\n");
  2848.     }
  2849.   sb_kill (&acc);
  2850.  
  2851. }
  2852.  
  2853. static int
  2854. new_file (name)
  2855.      const char *name;
  2856. {
  2857.   FILE *newone = fopen (name, "r");
  2858.   if (!newone)
  2859.     return 0;
  2860.  
  2861.   if (isp == MAX_INCLUDES)
  2862.     FATAL ((stderr, "Unreasonable include depth (%ld).\n", (long) isp));
  2863.  
  2864.   sp++;
  2865.   sp->handle = newone;
  2866.  
  2867.   sb_new (&sp->name);
  2868.   sb_add_string (&sp->name, name);
  2869.  
  2870.   sp->linecount = 1;
  2871.   sp->pushback_index = 0;
  2872.   sp->type = include_file;
  2873.   sp->index = 0;
  2874.   sb_new (&sp->pushback);
  2875.   return 1;
  2876. }
  2877.  
  2878. static void
  2879. do_include (idx, in)
  2880.      int idx;
  2881.      sb *in;
  2882. {
  2883.   sb t;
  2884.   sb cat;
  2885.   include_path *includes;
  2886.  
  2887.   sb_new (&t);
  2888.   sb_new (&cat);
  2889.  
  2890.   if (! mri)
  2891.     idx = getstring (idx, in, &t);
  2892.   else
  2893.     {
  2894.       idx = sb_skip_white (idx, in);
  2895.       while (idx < in->len && ! ISWHITE (in->ptr[idx]))
  2896.     {
  2897.       sb_add_char (&t, in->ptr[idx]);
  2898.       ++idx;
  2899.     }
  2900.     }
  2901.  
  2902.   for (includes = paths_head; includes; includes = includes->next)
  2903.     {
  2904.       sb_reset (&cat);
  2905.       sb_add_sb (&cat, &includes->path);
  2906.       sb_add_char (&cat, '/');
  2907.       sb_add_sb (&cat, &t);
  2908.       if (new_file (sb_name (&cat)))
  2909.     {
  2910.       break;
  2911.     }
  2912.     }
  2913.   if (!includes)
  2914.     {
  2915.       if (! new_file (sb_name (&t)))
  2916.     FATAL ((stderr, "Can't open include file `%s'.\n", sb_name (&t)));
  2917.     }
  2918.   sb_kill (&cat);
  2919.   sb_kill (&t);
  2920. }
  2921.  
  2922. static void
  2923. include_pop ()
  2924. {
  2925.   if (sp != include_stack)
  2926.     {
  2927.       if (sp->handle)
  2928.     fclose (sp->handle);
  2929.       sp--;
  2930.     }
  2931. }
  2932.  
  2933. /* Get the next character from the include stack.  If there's anything
  2934.    in the pushback buffer, take that first.  If we're at eof, pop from
  2935.    the stack and try again.  Keep the linecount up to date. */
  2936.  
  2937. static int
  2938. get ()
  2939. {
  2940.   int r;
  2941.  
  2942.   if (sp->pushback.len != sp->pushback_index)
  2943.     {
  2944.       r = (char) (sp->pushback.ptr[sp->pushback_index++]);
  2945.       /* When they've all gone, reset the pointer */
  2946.       if (sp->pushback_index == sp->pushback.len)
  2947.     {
  2948.       sp->pushback.len = 0;
  2949.       sp->pushback_index = 0;
  2950.     }
  2951.     }
  2952.   else if (sp->handle)
  2953.     {
  2954.       r = getc (sp->handle);
  2955.     }
  2956.   else
  2957.     r = EOF;
  2958.  
  2959.   if (r == EOF && isp)
  2960.     {
  2961.       include_pop ();
  2962.       r = get ();
  2963.       while (r == EOF && isp)
  2964.     {
  2965.       include_pop ();
  2966.       r = get ();
  2967.     }
  2968.       return r;
  2969.     }
  2970.   if (r == '\n')
  2971.     {
  2972.       sp->linecount++;
  2973.     }
  2974.  
  2975.   return r;
  2976. }
  2977.  
  2978. static int
  2979. linecount ()
  2980. {
  2981.   return sp->linecount;
  2982. }
  2983.  
  2984. static int
  2985. include_next_index ()
  2986. {
  2987.   static int index;
  2988.   if (!unreasonable
  2989.       && index > MAX_REASONABLE)
  2990.     FATAL ((stderr, "Unreasonable expansion (-u turns off check).\n"));
  2991.   return ++index;
  2992. }
  2993.  
  2994.  
  2995. /* Initialize the chartype vector. */
  2996.  
  2997. static void
  2998. chartype_init ()
  2999. {
  3000.   int x;
  3001.   for (x = 0; x < 256; x++)
  3002.     {
  3003.       if (isalpha (x) || x == '_' || x == '$')
  3004.     chartype[x] |= FIRSTBIT;
  3005.  
  3006.       if (mri && x == '.')
  3007.     chartype[x] |= FIRSTBIT;
  3008.  
  3009.       if (isdigit (x) || isalpha (x) || x == '_' || x == '$')
  3010.     chartype[x] |= NEXTBIT;
  3011.  
  3012.       if (x == ' ' || x == '\t' || x == ',' || x == '"' || x == ';'
  3013.       || x == '"' || x == '<' || x == '>' || x == ')' || x == '(')
  3014.     chartype[x] |= SEPBIT;
  3015.  
  3016.       if (x == 'b' || x == 'B'
  3017.       || x == 'q' || x == 'Q'
  3018.       || x == 'h' || x == 'H'
  3019.       || x == 'd' || x == 'D')
  3020.     chartype [x] |= BASEBIT;
  3021.       
  3022.       if (x == ' ' || x == '\t')
  3023.     chartype[x] |= WHITEBIT;
  3024.  
  3025.       if (x == comment_char)
  3026.     chartype[x] |= COMMENTBIT;
  3027.     }
  3028. }
  3029.  
  3030.  
  3031.  
  3032. /* What to do with all the keywords */
  3033. #define PROCESS     0x1000  /* Run substitution over the line */
  3034. #define LAB        0x2000  /* Spit out the label */
  3035.  
  3036. #define K_EQU         (PROCESS|1)
  3037. #define K_ASSIGN     (PROCESS|2)
  3038. #define K_REG         (PROCESS|3)
  3039. #define K_ORG         (PROCESS|4)
  3040. #define K_RADIX     (PROCESS|5)
  3041. #define K_DATA         (LAB|PROCESS|6)
  3042. #define K_DATAB     (LAB|PROCESS|7)
  3043. #define K_SDATA     (LAB|PROCESS|8)
  3044. #define K_SDATAB     (LAB|PROCESS|9)
  3045. #define K_SDATAC     (LAB|PROCESS|10)
  3046. #define K_SDATAZ    (LAB|PROCESS|11)
  3047. #define K_RES         (LAB|PROCESS|12)
  3048. #define K_SRES         (LAB|PROCESS|13)
  3049. #define K_SRESC     (LAB|PROCESS|14)
  3050. #define K_SRESZ     (LAB|PROCESS|15)
  3051. #define K_EXPORT     (LAB|PROCESS|16)
  3052. #define K_GLOBAL     (LAB|PROCESS|17)
  3053. #define K_PRINT     (LAB|PROCESS|19)
  3054. #define K_FORM         (LAB|PROCESS|20)
  3055. #define K_HEADING    (LAB|PROCESS|21)
  3056. #define K_PAGE        (LAB|PROCESS|22)
  3057. #define K_IMPORT    (LAB|PROCESS|23)
  3058. #define K_PROGRAM    (LAB|PROCESS|24)
  3059. #define K_END        (PROCESS|25)
  3060. #define K_INCLUDE    (PROCESS|26)
  3061. #define K_IGNORED    (PROCESS|27)
  3062. #define K_ASSIGNA    (PROCESS|28)
  3063. #define K_ASSIGNC    (29)
  3064. #define K_AIF        (PROCESS|30)
  3065. #define K_AELSE        (PROCESS|31)
  3066. #define K_AENDI        (PROCESS|32)
  3067. #define K_AREPEAT    (PROCESS|33)
  3068. #define K_AENDR        (PROCESS|34)
  3069. #define K_AWHILE    (35)
  3070. #define K_AENDW        (PROCESS|36)
  3071. #define K_EXITM        (37)
  3072. #define K_MACRO        (PROCESS|38)
  3073. #define K_ENDM        (39)
  3074. #define K_ALIGN        (PROCESS|LAB|40)
  3075. #define K_ALTERNATE     (41)
  3076. #define K_DB        (LAB|PROCESS|42)
  3077. #define K_DW        (LAB|PROCESS|43)
  3078. #define K_DL        (LAB|PROCESS|44)
  3079. #define K_LOCAL        (45)
  3080. #define K_IFEQ        (PROCESS|46)
  3081. #define K_IFNE        (PROCESS|47)
  3082. #define K_IFLT        (PROCESS|48)
  3083. #define K_IFLE        (PROCESS|49)
  3084. #define K_IFGE        (PROCESS|50)
  3085. #define K_IFGT        (PROCESS|51)
  3086. #define K_IFC        (PROCESS|52)
  3087. #define K_IFNC        (PROCESS|53)
  3088. #define K_IRP        (PROCESS|54)
  3089. #define K_IRPC        (PROCESS|55)
  3090.  
  3091.  
  3092. struct keyword
  3093. {
  3094.   char *name;
  3095.   int code;
  3096.   int extra;
  3097. };
  3098.  
  3099. static struct keyword kinfo[] =
  3100. {
  3101.   { "EQU", K_EQU, 0 },
  3102.   { "ALTERNATE", K_ALTERNATE, 0 },
  3103.   { "ASSIGN", K_ASSIGN, 0 },
  3104.   { "REG", K_REG, 0 },
  3105.   { "ORG", K_ORG, 0 },
  3106.   { "RADIX", K_RADIX, 0 },
  3107.   { "DATA", K_DATA, 0 },
  3108.   { "DB", K_DB, 0 },
  3109.   { "DW", K_DW, 0 },
  3110.   { "DL", K_DL, 0 },
  3111.   { "DATAB", K_DATAB, 0 },
  3112.   { "SDATA", K_SDATA, 0 },
  3113.   { "SDATAB", K_SDATAB, 0 },
  3114.   { "SDATAZ", K_SDATAZ, 0 },
  3115.   { "SDATAC", K_SDATAC, 0 },
  3116.   { "RES", K_RES, 0 },
  3117.   { "SRES", K_SRES, 0 },
  3118.   { "SRESC", K_SRESC, 0 },
  3119.   { "SRESZ", K_SRESZ, 0 },
  3120.   { "EXPORT", K_EXPORT, 0 },
  3121.   { "GLOBAL", K_GLOBAL, 0 },
  3122.   { "PRINT", K_PRINT, 0 },
  3123.   { "FORM", K_FORM, 0 },
  3124.   { "HEADING", K_HEADING, 0 },
  3125.   { "PAGE", K_PAGE, 0 },
  3126.   { "PROGRAM", K_IGNORED, 0 },
  3127.   { "END", K_END, 0 },
  3128.   { "INCLUDE", K_INCLUDE, 0 },
  3129.   { "ASSIGNA", K_ASSIGNA, 0 },
  3130.   { "ASSIGNC", K_ASSIGNC, 0 },
  3131.   { "AIF", K_AIF, 0 },
  3132.   { "AELSE", K_AELSE, 0 },
  3133.   { "AENDI", K_AENDI, 0 },
  3134.   { "AREPEAT", K_AREPEAT, 0 },
  3135.   { "AENDR", K_AENDR, 0 },
  3136.   { "EXITM", K_EXITM, 0 },
  3137.   { "MACRO", K_MACRO, 0 },
  3138.   { "ENDM", K_ENDM, 0 },
  3139.   { "AWHILE", K_AWHILE, 0 },
  3140.   { "ALIGN", K_ALIGN, 0 },
  3141.   { "AENDW", K_AENDW, 0 },
  3142.   { "ALTERNATE", K_ALTERNATE, 0 },
  3143.   { "LOCAL", K_LOCAL, 0 },
  3144.   { NULL, 0, 0 }
  3145. };
  3146.  
  3147. /* Although the conditional operators are handled by gas, we need to
  3148.    handle them here as well, in case they are used in a recursive
  3149.    macro to end the recursion.  */
  3150.  
  3151. static struct keyword mrikinfo[] =
  3152. {
  3153.   { "IFEQ", K_IFEQ, 0 },
  3154.   { "IFNE", K_IFNE, 0 },
  3155.   { "IFLT", K_IFLT, 0 },
  3156.   { "IFLE", K_IFLE, 0 },
  3157.   { "IFGE", K_IFGE, 0 },
  3158.   { "IFGT", K_IFGT, 0 },
  3159.   { "IFC", K_IFC, 0 },
  3160.   { "IFNC", K_IFNC, 0 },
  3161.   { "ELSEC", K_AELSE, 0 },
  3162.   { "ENDC", K_AENDI, 0 },
  3163.   { "MEXIT", K_EXITM, 0 },
  3164.   { "REPT", K_AREPEAT, 0 },
  3165.   { "IRP", K_IRP, 0 },
  3166.   { "IRPC", K_IRPC, 0 },
  3167.   { "ENDR", K_AENDR, 0 },
  3168.   { NULL, 0, 0 }
  3169. };
  3170.  
  3171. /* Look for a pseudo op on the line. If one's there then call
  3172.    its handler. */
  3173.  
  3174. static int
  3175. process_pseudo_op (idx, line, acc)
  3176.      int idx;
  3177.      sb *line;
  3178.      sb *acc;
  3179. {
  3180.   int oidx = idx;
  3181.  
  3182.   if (line->ptr[idx] == '.' || alternate || mri)
  3183.     {
  3184.       /* Scan forward and find pseudo name */
  3185.       char *in;
  3186.       hash_entry *ptr;
  3187.  
  3188.       char *s;
  3189.       char *e;
  3190.       if (line->ptr[idx] == '.')
  3191.     idx++;
  3192.       in = line->ptr + idx;
  3193.       s = in;
  3194.       e = s;
  3195.       sb_reset (acc);
  3196.  
  3197.       while (idx < line->len && *e && ISFIRSTCHAR (*e))
  3198.     {
  3199.       sb_add_char (acc, *e);
  3200.       e++;
  3201.       idx++;
  3202.     }
  3203.  
  3204.       ptr = hash_lookup (&keyword_hash_table, acc);
  3205.  
  3206.       if (!ptr)
  3207.     {
  3208. #if 0
  3209.       /* This one causes lots of pain when trying to preprocess
  3210.          ordinary code */
  3211.       WARNING ((stderr, "Unrecognised pseudo op `%s'.\n", sb_name (acc)));
  3212. #endif
  3213.       return 0;
  3214.     }
  3215.       if (ptr->value.i & LAB)
  3216.     {            /* output the label */
  3217.       if (label.len)
  3218.         {
  3219.           fprintf (outfile, "%s:\t", sb_name (&label));
  3220.         }
  3221.       else
  3222.         fprintf (outfile, "\t");
  3223.     }
  3224.  
  3225.       if (mri && ptr->value.i == K_END)
  3226.     {
  3227.       sb t;
  3228.  
  3229.       sb_new (&t);
  3230.       sb_add_buffer (&t, line->ptr + oidx, idx - oidx);
  3231.       fprintf (outfile, "\t%s", sb_name (&t));
  3232.       sb_kill (&t);
  3233.     }
  3234.  
  3235.       if (ptr->value.i & PROCESS)
  3236.     {
  3237.       /* Polish the rest of the line before handling the pseudo op */
  3238. #if 0
  3239.       strip_comments(line);
  3240. #endif
  3241.       sb_reset (acc);
  3242.       process_assigns (idx, line, acc);
  3243.       sb_reset(line);
  3244.       change_base (0, acc, line);
  3245.       idx = 0;
  3246.     }
  3247.       if (!condass_on ())
  3248.     {
  3249.       switch (ptr->value.i)
  3250.         {
  3251.         case K_AIF:
  3252.           do_aif (idx, line);
  3253.           break;
  3254.         case K_AELSE:
  3255.           do_aelse ();
  3256.           break;
  3257.         case K_AENDI:
  3258.           do_aendi ();
  3259.           break;
  3260.         }
  3261.       return 1;
  3262.     }
  3263.       else
  3264.     {
  3265.       switch (ptr->value.i)
  3266.         {
  3267.         case K_ALTERNATE:
  3268.           alternate = 1;
  3269.           macro_init (1, mri, 0, exp_get_abs);
  3270.           return 1;
  3271.         case K_AELSE:
  3272.           do_aelse ();
  3273.           return 1;
  3274.         case K_AENDI:
  3275.           do_aendi ();
  3276.           return 1;
  3277.         case K_ORG:
  3278.           ERROR ((stderr, "ORG command not allowed.\n"));
  3279.           break;
  3280.         case K_RADIX:
  3281.           do_radix (line);
  3282.           return 1;
  3283.         case K_DB:
  3284.           do_data (idx, line, 1);
  3285.           return 1;
  3286.         case K_DW:
  3287.           do_data (idx, line, 2);
  3288.           return 1;
  3289.         case K_DL:
  3290.           do_data (idx, line, 4);
  3291.           return 1;
  3292.         case K_DATA:
  3293.           do_data (idx, line, 0);
  3294.           return 1;
  3295.         case K_DATAB:
  3296.           do_datab (idx, line);
  3297.           return 1;
  3298.         case K_SDATA:
  3299.           do_sdata (idx, line, 0);
  3300.           return 1;
  3301.         case K_SDATAB:
  3302.           do_sdatab (idx, line);
  3303.           return 1;
  3304.         case K_SDATAC:
  3305.           do_sdata (idx, line, 'c');
  3306.           return 1;
  3307.         case K_SDATAZ:
  3308.           do_sdata (idx, line, 'z');
  3309.           return 1;
  3310.         case K_ASSIGN:
  3311.           do_assign (1, 0, line);
  3312.           return 1;
  3313.         case K_AIF:
  3314.           do_aif (idx, line);
  3315.           return 1;
  3316.         case K_AREPEAT:
  3317.           do_arepeat (idx, line);
  3318.           return 1;
  3319.         case K_AENDW:
  3320.           do_aendw ();
  3321.           return 1;
  3322.         case K_AWHILE:
  3323.           do_awhile (idx, line);
  3324.           return 1;
  3325.         case K_AENDR:
  3326.           do_aendr ();
  3327.           return 1;
  3328.         case K_EQU:
  3329.           do_assign (0, idx, line);
  3330.           return 1;
  3331.         case K_ALIGN:
  3332.           do_align (idx, line);
  3333.           return 1;
  3334.         case K_RES:
  3335.           do_res (idx, line, 0);
  3336.           return 1;
  3337.         case K_SRES:
  3338.           do_res (idx, line, 's');
  3339.           return 1;
  3340.         case K_INCLUDE:
  3341.           do_include (idx, line);
  3342.           return 1;
  3343.         case K_LOCAL:
  3344.           do_local (idx, line);
  3345.           return 1;
  3346.         case K_MACRO:
  3347.           do_macro (idx, line);
  3348.           return 1;
  3349.         case K_ENDM:
  3350.           do_endm ();
  3351.           return 1;
  3352.         case K_SRESC:
  3353.           do_res (idx, line, 'c');
  3354.           return 1;
  3355.         case K_PRINT:
  3356.           do_print (idx, line);
  3357.           return 1;
  3358.         case K_FORM:
  3359.           do_form (idx, line);
  3360.           return 1;
  3361.         case K_HEADING:
  3362.           do_heading (idx, line);
  3363.           return 1;
  3364.         case K_PAGE:
  3365.           do_page ();
  3366.           return 1;
  3367.         case K_GLOBAL:
  3368.         case K_EXPORT:
  3369.           do_export (line);
  3370.           return 1;
  3371.         case K_IMPORT:
  3372.           return 1;
  3373.         case K_SRESZ:
  3374.           do_res (idx, line, 'z');
  3375.           return 1;
  3376.         case K_IGNORED:
  3377.           return 1;
  3378.         case K_END:
  3379.           do_end (line);
  3380.           return 1;
  3381.         case K_ASSIGNA:
  3382.           do_assigna (idx, line);
  3383.           return 1;
  3384.         case K_ASSIGNC:
  3385.           do_assignc (idx, line);
  3386.           return 1;
  3387.         case K_EXITM:
  3388.           do_exitm ();
  3389.           return 1;
  3390.         case K_REG:
  3391.           do_reg (idx, line);
  3392.           return 1;
  3393.         case K_IFEQ:
  3394.           do_if (idx, line, EQ);
  3395.           return 1;
  3396.         case K_IFNE:
  3397.           do_if (idx, line, NE);
  3398.           return 1;
  3399.         case K_IFLT:
  3400.           do_if (idx, line, LT);
  3401.           return 1;
  3402.         case K_IFLE:
  3403.           do_if (idx, line, LE);
  3404.           return 1;
  3405.         case K_IFGE:
  3406.           do_if (idx, line, GE);
  3407.           return 1;
  3408.         case K_IFGT:
  3409.           do_if (idx, line, GT);
  3410.           return 1;
  3411.         case K_IFC:
  3412.           do_ifc (idx, line, 0);
  3413.           return 1;
  3414.         case K_IFNC:
  3415.           do_ifc (idx, line, 1);
  3416.           return 1;
  3417.         case K_IRP:
  3418.           do_irp (idx, line, 0);
  3419.           return 1;
  3420.         case K_IRPC:
  3421.           do_irp (idx, line, 1);
  3422.           return 1;
  3423.         }
  3424.     }
  3425.     }
  3426.   return 0;
  3427. }
  3428.  
  3429.  
  3430.  
  3431. /* Add a keyword to the hash table.  */
  3432.  
  3433. static void
  3434. add_keyword (name, code)
  3435.      const char *name;
  3436.      int code;
  3437. {
  3438.   sb label;
  3439.   int j;
  3440.  
  3441.   sb_new (&label);
  3442.   sb_add_string (&label, name);
  3443.  
  3444.   hash_add_to_int_table (&keyword_hash_table, &label, code);
  3445.  
  3446.   sb_reset (&label);
  3447.   for (j = 0; name[j]; j++)
  3448.     sb_add_char (&label, name[j] - 'A' + 'a');
  3449.   hash_add_to_int_table (&keyword_hash_table, &label, code);
  3450.  
  3451.   sb_kill (&label);
  3452. }  
  3453.  
  3454. /* Build the keyword hash table - put each keyword in the table twice,
  3455.    once upper and once lower case.*/
  3456.  
  3457. static void
  3458. process_init ()
  3459. {
  3460.   int i;
  3461.  
  3462.   for (i = 0; kinfo[i].name; i++)
  3463.     add_keyword (kinfo[i].name, kinfo[i].code);
  3464.  
  3465.   if (mri)
  3466.     {
  3467.       for (i = 0; mrikinfo[i].name; i++)
  3468.     add_keyword (mrikinfo[i].name, mrikinfo[i].code);
  3469.     }
  3470. }
  3471.  
  3472.  
  3473. static void
  3474. do_define (string)
  3475.      const char *string;
  3476. {
  3477.   sb label;
  3478.   int res = 1;
  3479.   hash_entry *ptr;
  3480.   sb_new (&label);
  3481.  
  3482.  
  3483.   while (*string)
  3484.     {
  3485.       if (*string == '=') 
  3486.     {
  3487.       sb value;
  3488.       sb_new (&value);
  3489.       string++;
  3490.       while (*string)
  3491.         {
  3492.           sb_add_char (&value, *string);
  3493.           string++;
  3494.         }
  3495.       exp_get_abs ("Invalid expression on command line.\n", 0, &value, &res);
  3496.       sb_kill (&value);
  3497.       break;
  3498.     }
  3499.       sb_add_char (&label, *string);
  3500.  
  3501.       string ++;
  3502.     }
  3503.  
  3504.   ptr = hash_create (&vars, &label);
  3505.   free_old_entry (ptr);
  3506.   ptr->type = hash_integer;
  3507.   ptr->value.i = res;
  3508.   sb_kill (&label);
  3509. }
  3510. char *program_name;
  3511.  
  3512. /* The list of long options.  */
  3513. static struct option long_options[] =
  3514. {
  3515.   { "alternate", no_argument, 0, 'a' },
  3516.   { "include", required_argument, 0, 'I' },
  3517.   { "commentchar", required_argument, 0, 'c' },
  3518.   { "copysource", no_argument, 0, 's' },
  3519.   { "debug", no_argument, 0, 'd' },
  3520.   { "help", no_argument, 0, 'h' },
  3521.   { "mri", no_argument, 0, 'M' },
  3522.   { "output", required_argument, 0, 'o' },
  3523.   { "print", no_argument, 0, 'p' },
  3524.   { "unreasonable", no_argument, 0, 'u' },
  3525.   { "version", no_argument, 0, 'v' },
  3526.   { "define", required_argument, 0, 'd' },
  3527.   { NULL, no_argument, 0, 0 }
  3528. };
  3529.  
  3530. /* Show a usage message and exit.  */
  3531. static void
  3532. show_usage (file, status)
  3533.      FILE *file;
  3534.      int status;
  3535. {
  3536.   fprintf (file, "\
  3537. Usage: %s \n\
  3538.   [-a]      [--alternate]         enter alternate macro mode\n\
  3539.   [-c char] [--commentchar char]  change the comment character from !\n\
  3540.   [-d]      [--debug]             print some debugging info\n\
  3541.   [-h]      [--help]              print this message\n\
  3542.   [-M]      [--mri]               enter MRI compatibility mode\n\
  3543.   [-o out]  [--output out]        set the output file\n\
  3544.   [-p]      [--print]             print line numbers\n", program_name);
  3545.   fprintf (file, "\
  3546.   [-s]      [--copysource]        copy source through as comments \n\
  3547.   [-u]      [--unreasonable]      allow unreasonable nesting\n\
  3548.   [-v]      [--version]           print the program version\n\
  3549.   [-Dname=value]                  create preprocessor variable called name, with value\n\
  3550.   [-Ipath]                        add to include path list\n\
  3551.   [in-file]\n");
  3552.   exit (status);
  3553. }
  3554.  
  3555. /* Display a help message and exit.  */
  3556. static void
  3557. show_help ()
  3558. {
  3559.   printf ("%s: Gnu Assembler Macro Preprocessor\n",
  3560.       program_name);
  3561.   show_usage (stdout, 0);
  3562. }
  3563.  
  3564. int
  3565. main (argc, argv)
  3566.      int argc;
  3567.      char **argv;
  3568. {
  3569.   int opt;
  3570.   char *out_name = 0;
  3571.   sp = include_stack;
  3572.  
  3573.   ifstack[0].on = 1;
  3574.   ifi = 0;
  3575.  
  3576.  
  3577.  
  3578.   program_name = argv[0];
  3579.   xmalloc_set_program_name (program_name);
  3580.  
  3581.   hash_new_table (101, &keyword_hash_table);
  3582.   hash_new_table (101, &assign_hash_table);
  3583.   hash_new_table (101, &vars);
  3584.  
  3585.   sb_new (&label);
  3586.  
  3587.   while ((opt = getopt_long (argc, argv, "I:sdhavc:upo:D:M", long_options,
  3588.                  (int *) NULL))
  3589.      != EOF)
  3590.     {
  3591.       switch (opt)
  3592.     {
  3593.     case 'o':
  3594.       out_name = optarg;
  3595.       break;
  3596.     case 'u':
  3597.       unreasonable = 1;
  3598.       break;
  3599.     case 'I':
  3600.       {
  3601.         include_path *p = (include_path *) xmalloc (sizeof (include_path));
  3602.         sb_new (&p->path);
  3603.         sb_add_string (&p->path, optarg);
  3604.         if (paths_tail)
  3605.           paths_tail->next = p;
  3606.         else
  3607.           paths_head = p;
  3608.         paths_tail = p;
  3609.       }
  3610.       break;
  3611.     case 'p':
  3612.       print_line_number = 1;
  3613.       break;
  3614.     case 'c':
  3615.       comment_char = optarg[0];
  3616.       break;
  3617.     case 'a':
  3618.       alternate = 1;
  3619.       break;
  3620.     case 's':
  3621.       copysource = 1;
  3622.       break;
  3623.     case 'd':
  3624.       stats = 1;
  3625.       break;
  3626.     case 'D':
  3627.       do_define (optarg);
  3628.       break;
  3629.     case 'M':
  3630.       mri = 1;
  3631.       comment_char = ';';
  3632.       break;
  3633.     case 'h':
  3634.       show_help ();
  3635.       /*NOTREACHED*/
  3636.     case 'v':
  3637.       printf ("GNU %s version %s\n", program_name, program_version);
  3638.       exit (0);
  3639.       /*NOTREACHED*/
  3640.     case 0:
  3641.       break;
  3642.     default:
  3643.       show_usage (stderr, 1);
  3644.       /*NOTREACHED*/
  3645.     }
  3646.     }
  3647.  
  3648.   process_init ();
  3649.  
  3650.   macro_init (alternate, mri, 0, exp_get_abs);
  3651.  
  3652.   if (out_name) {
  3653.     outfile = fopen (out_name, "w");
  3654.     if (!outfile)
  3655.       {
  3656.     fprintf (stderr, "%s: Can't open output file `%s'.\n",
  3657.          program_name, out_name);
  3658.     exit (1);
  3659.       }
  3660.   }
  3661.   else  {
  3662.     outfile = stdout;
  3663.   }
  3664.  
  3665.   chartype_init ();
  3666.   if (!outfile)
  3667.     outfile = stdout;
  3668.  
  3669.   /* Process all the input files */
  3670.  
  3671.   while (optind < argc)
  3672.     {
  3673.       if (new_file (argv[optind]))
  3674.     {
  3675.       process_file ();
  3676.     }
  3677.       else
  3678.     {
  3679.       fprintf (stderr, "%s: Can't open input file `%s'.\n",
  3680.            program_name, argv[optind]);
  3681.       exit (1);
  3682.     }
  3683.       optind++;
  3684.     }
  3685.  
  3686.   quit ();
  3687.   return 0;
  3688. }
  3689.  
  3690. /* This function is used because an abort in some of the other files
  3691.    may be compiled into as_abort because they include as.h.  */
  3692.  
  3693. void
  3694. as_abort (file, line, fn)
  3695.      const char *file, *fn;
  3696.      int line;
  3697. {
  3698.   fprintf (stderr, "Internal error, aborting at %s line %d", file, line);
  3699.   if (fn)
  3700.     fprintf (stderr, " in %s", fn);
  3701.   fprintf (stderr, "\nPlease report this bug.\n");
  3702.   exit (1);
  3703. }
  3704.