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