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