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