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