OSDN Git Service

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