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