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