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