2000-06-06 Michael Snyder <msnyder@seadog.cygnus.com>
[binutils.git] / gas / gasp.c
bloba8f56192aeeb3cb96568d74713373347274b6a85
1 /* gasp.c - Gnu assembler preprocessor main program.
2 Copyright (C) 1994, 95, 96, 97, 98, 99, 2000
3 Free Software Foundation, Inc.
5 Written by Steve and Judy Chamberlain of Cygnus Support,
6 sac@cygnus.com
8 This file is part of GASP, the GNU Assembler Preprocessor.
10 GASP is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
15 GASP is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GASP; see the file COPYING. If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 02111-1307, USA. */
27 This program translates the input macros and stuff into a form
28 suitable for gas to consume.
31 gasp [-sdhau] [-c char] [-o <outfile>] <infile>*
33 -s copy source to output
34 -c <char> comments are started with <char> instead of !
35 -u allow unreasonable stuff
36 -p print line numbers
37 -d print debugging stats
38 -s semi colons start comments
39 -a use alternate syntax
40 Pseudo ops can start with or without a .
41 Labels have to be in first column.
42 -I specify include dir
43 Macro arg parameters subsituted by name, don't need the &.
44 String can start with ' too.
45 Strings can be surrounded by <..>
46 A %<exp> in a string evaluates the expression
47 Literal char in a string with !
52 #include "config.h"
53 #include "bin-bugs.h"
55 #include <stdio.h>
56 #include <string.h>
57 #include <getopt.h>
58 #include <ctype.h>
60 #ifdef HAVE_STDLIB_H
61 #include <stdlib.h>
62 #endif
64 #ifdef NEED_MALLOC_DECLARATION
65 extern char *malloc ();
66 #endif
68 #include "ansidecl.h"
69 #include "libiberty.h"
70 #include "sb.h"
71 #include "macro.h"
72 #include "asintl.h"
74 char *program_version = "1.2";
76 /* This is normally declared in as.h, but we don't include that. We
77 need the function because other files linked with gasp.c might call
78 it. */
79 extern void as_abort PARAMS ((const char *, int, const char *));
81 /* The default obstack chunk size. If we set this to zero, the
82 obstack code will use whatever will fit in a 4096 byte block. This
83 is used by the hash table code used by macro.c. */
84 int chunksize = 0;
86 #define MAX_INCLUDES 30 /* Maximum include depth */
87 #define MAX_REASONABLE 1000 /* Maximum number of expansions */
89 int unreasonable; /* -u on command line */
90 int stats; /* -d on command line */
91 int print_line_number; /* -p flag on command line */
92 int copysource; /* -c flag on command line */
93 int warnings; /* Number of WARNINGs generated so far. */
94 int errors; /* Number of ERRORs generated so far. */
95 int fatals; /* Number of fatal ERRORs generated so far (either 0 or 1). */
96 int alternate = 0; /* -a on command line */
97 int mri = 0; /* -M on command line */
98 char comment_char = '!';
99 int radix = 10; /* Default radix */
101 int had_end; /* Seen .END */
103 /* The output stream */
104 FILE *outfile;
106 /* the attributes of each character are stored as a bit pattern
107 chartype, which gives us quick tests. */
110 #define FIRSTBIT 1
111 #define NEXTBIT 2
112 #define SEPBIT 4
113 #define WHITEBIT 8
114 #define COMMENTBIT 16
115 #define BASEBIT 32
116 #define ISCOMMENTCHAR(x) (chartype[(unsigned char)(x)] & COMMENTBIT)
117 #define ISFIRSTCHAR(x) (chartype[(unsigned char)(x)] & FIRSTBIT)
118 #define ISNEXTCHAR(x) (chartype[(unsigned char)(x)] & NEXTBIT)
119 #define ISSEP(x) (chartype[(unsigned char)(x)] & SEPBIT)
120 #define ISWHITE(x) (chartype[(unsigned char)(x)] & WHITEBIT)
121 #define ISBASE(x) (chartype[(unsigned char)(x)] & BASEBIT)
122 static char chartype[256];
125 /* Conditional assembly uses the `ifstack'. Each aif pushes another
126 entry onto the stack, and sets the on flag if it should. The aelse
127 sets hadelse, and toggles on. An aend pops a level. We limit to
128 100 levels of nesting, not because we're facists pigs with read
129 only minds, but because more than 100 levels of nesting is probably
130 a bug in the user's macro structure. */
132 #define IFNESTING 100
133 struct
135 int on; /* is the level being output */
136 int hadelse; /* has an aelse been seen */
138 ifstack[IFNESTING];
139 int ifi;
141 /* The final and intermediate results of expression evaluation are kept in
142 exp_t's. Note that a symbol is not an sb, but a pointer into the input
143 line. It must be coped somewhere safe before the next line is read in. */
145 typedef struct
147 char *name;
148 int len;
150 symbol;
152 typedef struct
154 int value; /* constant part */
155 symbol add_symbol; /* name part */
156 symbol sub_symbol; /* name part */
158 exp_t;
161 /* Hashing is done in a pretty standard way. A hash_table has a
162 pointer to a vector of pointers to hash_entrys, and the size of the
163 vector. A hash_entry contains a union of all the info we like to
164 store in hash table. If there is a hash collision, hash_entries
165 with the same hash are kept in a chain. */
167 /* What the data in a hash_entry means */
168 typedef enum
170 hash_integer, /* name->integer mapping */
171 hash_string, /* name->string mapping */
172 hash_macro, /* name is a macro */
173 hash_formal /* name is a formal argument */
174 } hash_type;
176 typedef struct hs
178 sb key; /* symbol name */
179 hash_type type; /* symbol meaning */
180 union
182 sb s;
183 int i;
184 struct macro_struct *m;
185 struct formal_struct *f;
186 } value;
187 struct hs *next; /* next hash_entry with same hash key */
188 } hash_entry;
190 typedef struct
192 hash_entry **table;
193 int size;
194 } hash_table;
197 /* how we nest files and expand macros etc.
199 we keep a stack of of include_stack structs. each include file
200 pushes a new level onto the stack. we keep an sb with a pushback
201 too. unget chars are pushed onto the pushback sb, getchars first
202 checks the pushback sb before reading from the input stream.
204 small things are expanded by adding the text of the item onto the
205 pushback sb. larger items are grown by pushing a new level and
206 allocating the entire pushback buf for the item. each time
207 something like a macro is expanded, the stack index is changed. we
208 can then perform an exitm by popping all entries off the stack with
209 the same stack index. if we're being reasonable, we can detect
210 recusive expansion by checking the index is reasonably small.
213 typedef enum
215 include_file, include_repeat, include_while, include_macro
216 } include_type;
218 struct include_stack
220 sb pushback; /* current pushback stream */
221 int pushback_index; /* next char to read from stream */
222 FILE *handle; /* open file */
223 sb name; /* name of file */
224 int linecount; /* number of lines read so far */
225 include_type type;
226 int index; /* index of this layer */
228 include_stack[MAX_INCLUDES];
230 struct include_stack *sp;
231 #define isp (sp - include_stack)
233 /* Include file list */
235 typedef struct include_path
237 struct include_path *next;
238 sb path;
239 } include_path;
241 include_path *paths_head;
242 include_path *paths_tail;
245 static void quit PARAMS ((void));
246 static void hash_new_table PARAMS ((int, hash_table *));
247 static int hash PARAMS ((sb *));
248 static hash_entry *hash_create PARAMS ((hash_table *, sb *));
249 static void hash_add_to_string_table PARAMS ((hash_table *, sb *, sb *, int));
250 static void hash_add_to_int_table PARAMS ((hash_table *, sb *, int));
251 static hash_entry *hash_lookup PARAMS ((hash_table *, sb *));
252 static void checkconst PARAMS ((int, exp_t *));
253 static int sb_strtol PARAMS ((int, sb *, int, int *));
254 static int level_0 PARAMS ((int, sb *, exp_t *));
255 static int level_1 PARAMS ((int, sb *, exp_t *));
256 static int level_2 PARAMS ((int, sb *, exp_t *));
257 static int level_3 PARAMS ((int, sb *, exp_t *));
258 static int level_4 PARAMS ((int, sb *, exp_t *));
259 static int level_5 PARAMS ((int, sb *, exp_t *));
260 static int exp_parse PARAMS ((int, sb *, exp_t *));
261 static void exp_string PARAMS ((exp_t *, sb *));
262 static int exp_get_abs PARAMS ((const char *, int, sb *, int *));
263 #if 0
264 static void strip_comments PARAMS ((sb *));
265 #endif
266 static void unget PARAMS ((int));
267 static void include_buf PARAMS ((sb *, sb *, include_type, int));
268 static void include_print_where_line PARAMS ((FILE *));
269 static void include_print_line PARAMS ((FILE *));
270 static int get_line PARAMS ((sb *));
271 static int grab_label PARAMS ((sb *, sb *));
272 static void change_base PARAMS ((int, sb *, sb *));
273 static void do_end PARAMS ((sb *));
274 static void do_assign PARAMS ((int, int, sb *));
275 static void do_radix PARAMS ((sb *));
276 static int get_opsize PARAMS ((int, sb *, int *));
277 static int eol PARAMS ((int, sb *));
278 static void do_data PARAMS ((int, sb *, int));
279 static void do_datab PARAMS ((int, sb *));
280 static void do_align PARAMS ((int, sb *));
281 static void do_res PARAMS ((int, sb *, int));
282 static void do_export PARAMS ((sb *));
283 static void do_print PARAMS ((int, sb *));
284 static void do_heading PARAMS ((int, sb *));
285 static void do_page PARAMS ((void));
286 static void do_form PARAMS ((int, sb *));
287 static int get_any_string PARAMS ((int, sb *, sb *, int, int));
288 static int skip_openp PARAMS ((int, sb *));
289 static int skip_closep PARAMS ((int, sb *));
290 static int dolen PARAMS ((int, sb *, sb *));
291 static int doinstr PARAMS ((int, sb *, sb *));
292 static int dosubstr PARAMS ((int, sb *, sb *));
293 static void process_assigns PARAMS ((int, sb *, sb *));
294 static int get_and_process PARAMS ((int, sb *, sb *));
295 static void process_file PARAMS ((void));
296 static void free_old_entry PARAMS ((hash_entry *));
297 static void do_assigna PARAMS ((int, sb *));
298 static void do_assignc PARAMS ((int, sb *));
299 static void do_reg PARAMS ((int, sb *));
300 static int condass_lookup_name PARAMS ((sb *, int, sb *, int));
301 static int whatcond PARAMS ((int, sb *, int *));
302 static int istrue PARAMS ((int, sb *));
303 static void do_aif PARAMS ((int, sb *));
304 static void do_aelse PARAMS ((void));
305 static void do_aendi PARAMS ((void));
306 static int condass_on PARAMS ((void));
307 static void do_if PARAMS ((int, sb *, int));
308 static int get_mri_string PARAMS ((int, sb *, sb *, int));
309 static void do_ifc PARAMS ((int, sb *, int));
310 static void do_aendr PARAMS ((void));
311 static void do_awhile PARAMS ((int, sb *));
312 static void do_aendw PARAMS ((void));
313 static void do_exitm PARAMS ((void));
314 static void do_arepeat PARAMS ((int, sb *));
315 static void do_endm PARAMS ((void));
316 static void do_irp PARAMS ((int, sb *, int));
317 static void do_local PARAMS ((int, sb *));
318 static void do_macro PARAMS ((int, sb *));
319 static int macro_op PARAMS ((int, sb *));
320 static int getstring PARAMS ((int, sb *, sb *));
321 static void do_sdata PARAMS ((int, sb *, int));
322 static void do_sdatab PARAMS ((int, sb *));
323 static int new_file PARAMS ((const char *));
324 static void do_include PARAMS ((int, sb *));
325 static void include_pop PARAMS ((void));
326 static int get PARAMS ((void));
327 static int linecount PARAMS ((void));
328 static int include_next_index PARAMS ((void));
329 static void chartype_init PARAMS ((void));
330 static int process_pseudo_op PARAMS ((int, sb *, sb *));
331 static void add_keyword PARAMS ((const char *, int));
332 static void process_init PARAMS ((void));
333 static void do_define PARAMS ((const char *));
334 static void show_usage PARAMS ((FILE *, int));
335 static void show_help PARAMS ((void));
337 #define FATAL(x) \
338 do { include_print_where_line (stderr); fprintf x ; fatals++; quit(); } while(0)
339 #define ERROR(x) \
340 do { include_print_where_line (stderr); fprintf x; errors++; } while(0)
341 #define WARNING(x) \
342 do { include_print_where_line (stderr); fprintf x; warnings++;} while(0)
346 /* exit the program and return the right ERROR code. */
347 static void
348 quit ()
350 int exitcode;
351 if (fatals + errors)
352 exitcode = 1;
353 else
354 exitcode = 0;
356 if (stats)
358 int i;
359 for (i = 0; i < sb_max_power_two; i++)
361 fprintf (stderr, "strings size %8d : %d\n", 1<<i, string_count[i]);
364 exit (exitcode);
367 /* hash table maintenance. */
369 /* build a new hash table with size buckets, and fill in the info at ptr. */
371 static void
372 hash_new_table (size, ptr)
373 int size;
374 hash_table *ptr;
376 int i;
377 ptr->size = size;
378 ptr->table = (hash_entry **) xmalloc (size * (sizeof (hash_entry *)));
379 /* Fill with null-pointer, not zero-bit-pattern. */
380 for (i = 0; i < size; i++)
381 ptr->table[i] = 0;
384 /* calculate and return the hash value of the sb at key. */
386 static int
387 hash (key)
388 sb *key;
390 int k = 0x1234;
391 int i;
392 char *p = key->ptr;
393 for (i = 0; i < key->len; i++)
395 k ^= (k << 2) ^ *p;
396 p++;
398 return k & 0xf0fff;
401 /* lookup key in hash_table tab, if present, then return it, otherwise
402 build a new one and fill it with hash_integer. */
404 static
405 hash_entry *
406 hash_create (tab, key)
407 hash_table *tab;
408 sb *key;
410 int k = hash (key) % tab->size;
411 hash_entry *p;
412 hash_entry **table = tab->table;
414 p = table[k];
416 while (1)
418 if (!p)
420 hash_entry *n = (hash_entry *) xmalloc (sizeof (hash_entry));
421 n->next = table[k];
422 sb_new (&n->key);
423 sb_add_sb (&n->key, key);
424 table[k] = n;
425 n->type = hash_integer;
426 return n;
428 if (strncmp (table[k]->key.ptr, key->ptr, key->len) == 0)
430 return p;
432 p = p->next;
436 /* add sb name with key into hash_table tab. if replacing old value
437 and again, then ERROR. */
439 static
440 void
441 hash_add_to_string_table (tab, key, name, again)
442 hash_table *tab;
443 sb *key;
444 sb *name;
445 int again;
447 hash_entry *ptr = hash_create (tab, key);
448 if (ptr->type == hash_integer)
450 sb_new (&ptr->value.s);
452 if (ptr->value.s.len)
454 if (!again)
455 ERROR ((stderr, _("redefinition not allowed\n")));
458 ptr->type = hash_string;
459 sb_reset (&ptr->value.s);
461 sb_add_sb (&ptr->value.s, name);
464 /* add integer name to hash_table tab with sb key. */
466 static
467 void
468 hash_add_to_int_table (tab, key, name)
469 hash_table *tab;
470 sb *key;
471 int name;
473 hash_entry *ptr = hash_create (tab, key);
474 ptr->value.i = name;
477 /* lookup sb key in hash_table tab. if found return hash_entry result,
478 else 0. */
480 static
481 hash_entry *
482 hash_lookup (tab, key)
483 hash_table *tab;
484 sb *key;
486 int k = hash (key) % tab->size;
487 hash_entry **table = tab->table;
488 hash_entry *p = table[k];
489 while (p)
491 if (p->key.len == key->len
492 && strncmp (p->key.ptr, key->ptr, key->len) == 0)
493 return p;
494 p = p->next;
496 return 0;
500 /* expressions
502 are handled in a really simple recursive decent way. each bit of
503 the machine takes an index into an sb and a pointer to an exp_t,
504 modifies the *exp_t and returns the index of the first character
505 past the part of the expression parsed.
507 expression precedence:
509 unary + - ~
518 /* make sure that the exp_t at term is constant, if not the give the op ERROR. */
520 static
521 void
522 checkconst (op, term)
523 int op;
524 exp_t *term;
526 if (term->add_symbol.len
527 || term->sub_symbol.len)
529 ERROR ((stderr, _("the %c operator cannot take non-absolute arguments.\n"), op));
533 /* turn the number in string at idx into a number of base,
534 fill in ptr and return the index of the first character not in the
535 number. */
537 static
539 sb_strtol (idx, string, base, ptr)
540 int idx;
541 sb *string;
542 int base;
543 int *ptr;
545 int value = 0;
546 idx = sb_skip_white (idx, string);
548 while (idx < string->len)
550 int ch = string->ptr[idx];
551 int dig = 0;
552 if (isdigit (ch))
553 dig = ch - '0';
554 else if (ch >= 'a' && ch <= 'f')
555 dig = ch - 'a' + 10;
556 else if (ch >= 'A' && ch <= 'F')
557 dig = ch - 'A' + 10;
558 else
559 break;
561 if (dig >= base)
562 break;
564 value = value * base + dig;
565 idx++;
567 *ptr = value;
568 return idx;
571 static int
572 level_0 (idx, string, lhs)
573 int idx;
574 sb *string;
575 exp_t *lhs;
577 lhs->add_symbol.len = 0;
578 lhs->add_symbol.name = 0;
580 lhs->sub_symbol.len = 0;
581 lhs->sub_symbol.name = 0;
583 idx = sb_skip_white (idx, string);
585 lhs->value = 0;
587 if (isdigit ((unsigned char) string->ptr[idx]))
589 idx = sb_strtol (idx, string, 10, &lhs->value);
591 else if (ISFIRSTCHAR (string->ptr[idx]))
593 int len = 0;
594 lhs->add_symbol.name = string->ptr + idx;
595 while (idx < string->len && ISNEXTCHAR (string->ptr[idx]))
597 idx++;
598 len++;
600 lhs->add_symbol.len = len;
602 else if (string->ptr[idx] == '"')
604 sb acc;
605 sb_new (&acc);
606 ERROR ((stderr, _("string where expression expected.\n")));
607 idx = getstring (idx, string, &acc);
608 sb_kill (&acc);
610 else
612 ERROR ((stderr, _("can't find primary in expression.\n")));
613 idx++;
615 return sb_skip_white (idx, string);
620 static int
621 level_1 (idx, string, lhs)
622 int idx;
623 sb *string;
624 exp_t *lhs;
626 idx = sb_skip_white (idx, string);
628 switch (string->ptr[idx])
630 case '+':
631 idx = level_1 (idx + 1, string, lhs);
632 break;
633 case '~':
634 idx = level_1 (idx + 1, string, lhs);
635 checkconst ('~', lhs);
636 lhs->value = ~lhs->value;
637 break;
638 case '-':
640 symbol t;
641 idx = level_1 (idx + 1, string, lhs);
642 lhs->value = -lhs->value;
643 t = lhs->add_symbol;
644 lhs->add_symbol = lhs->sub_symbol;
645 lhs->sub_symbol = t;
646 break;
648 case '(':
649 idx++;
650 idx = level_5 (sb_skip_white (idx, string), string, lhs);
651 if (string->ptr[idx] != ')')
652 ERROR ((stderr, _("misplaced closing parens.\n")));
653 else
654 idx++;
655 break;
656 default:
657 idx = level_0 (idx, string, lhs);
658 break;
660 return sb_skip_white (idx, string);
663 static int
664 level_2 (idx, string, lhs)
665 int idx;
666 sb *string;
667 exp_t *lhs;
669 exp_t rhs;
671 idx = level_1 (idx, string, lhs);
673 while (idx < string->len && (string->ptr[idx] == '*'
674 || string->ptr[idx] == '/'))
676 char op = string->ptr[idx++];
677 idx = level_1 (idx, string, &rhs);
678 switch (op)
680 case '*':
681 checkconst ('*', lhs);
682 checkconst ('*', &rhs);
683 lhs->value *= rhs.value;
684 break;
685 case '/':
686 checkconst ('/', lhs);
687 checkconst ('/', &rhs);
688 if (rhs.value == 0)
689 ERROR ((stderr, _("attempt to divide by zero.\n")));
690 else
691 lhs->value /= rhs.value;
692 break;
695 return sb_skip_white (idx, string);
699 static int
700 level_3 (idx, string, lhs)
701 int idx;
702 sb *string;
703 exp_t *lhs;
705 exp_t rhs;
707 idx = level_2 (idx, string, lhs);
709 while (idx < string->len
710 && (string->ptr[idx] == '+'
711 || string->ptr[idx] == '-'))
713 char op = string->ptr[idx++];
714 idx = level_2 (idx, string, &rhs);
715 switch (op)
717 case '+':
718 lhs->value += rhs.value;
719 if (lhs->add_symbol.name && rhs.add_symbol.name)
721 ERROR ((stderr, _("can't add two relocatable expressions\n")));
723 /* change nn+symbol to symbol + nn */
724 if (rhs.add_symbol.name)
726 lhs->add_symbol = rhs.add_symbol;
728 break;
729 case '-':
730 lhs->value -= rhs.value;
731 lhs->sub_symbol = rhs.add_symbol;
732 break;
735 return sb_skip_white (idx, string);
738 static int
739 level_4 (idx, string, lhs)
740 int idx;
741 sb *string;
742 exp_t *lhs;
744 exp_t rhs;
746 idx = level_3 (idx, string, lhs);
748 while (idx < string->len &&
749 string->ptr[idx] == '&')
751 char op = string->ptr[idx++];
752 idx = level_3 (idx, string, &rhs);
753 switch (op)
755 case '&':
756 checkconst ('&', lhs);
757 checkconst ('&', &rhs);
758 lhs->value &= rhs.value;
759 break;
762 return sb_skip_white (idx, string);
765 static int
766 level_5 (idx, string, lhs)
767 int idx;
768 sb *string;
769 exp_t *lhs;
771 exp_t rhs;
773 idx = level_4 (idx, string, lhs);
775 while (idx < string->len
776 && (string->ptr[idx] == '|' || string->ptr[idx] == '~'))
778 char op = string->ptr[idx++];
779 idx = level_4 (idx, string, &rhs);
780 switch (op)
782 case '|':
783 checkconst ('|', lhs);
784 checkconst ('|', &rhs);
785 lhs->value |= rhs.value;
786 break;
787 case '~':
788 checkconst ('~', lhs);
789 checkconst ('~', &rhs);
790 lhs->value ^= rhs.value;
791 break;
794 return sb_skip_white (idx, string);
798 /* parse the expression at offset idx into string, fill up res with
799 the result. return the index of the first char past the expression.
802 static int
803 exp_parse (idx, string, res)
804 int idx;
805 sb *string;
806 exp_t *res;
808 return level_5 (sb_skip_white (idx, string), string, res);
812 /* turn the expression at exp into text and glue it onto the end of
813 string. */
815 static void
816 exp_string (exp, string)
817 exp_t *exp;
818 sb *string;
820 int np = 0;
821 int ad = 0;
822 sb_reset (string);
824 if (exp->add_symbol.len)
826 sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
827 np = 1;
828 ad = 1;
830 if (exp->value)
832 char buf[20];
833 if (np)
834 sb_add_char (string, '+');
835 sprintf (buf, "%d", exp->value);
836 sb_add_string (string, buf);
837 np = 1;
838 ad = 1;
840 if (exp->sub_symbol.len)
842 sb_add_char (string, '-');
843 sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
844 np = 0;
845 ad = 1;
848 if (!ad)
849 sb_add_char (string, '0');
853 /* parse the expression at offset idx into sb in, return the value in val.
854 if the expression is not constant, give ERROR emsg. returns the index
855 of the first character past the end of the expression. */
857 static int
858 exp_get_abs (emsg, idx, in, val)
859 const char *emsg;
860 int idx;
861 sb *in;
862 int *val;
864 exp_t res;
865 idx = exp_parse (idx, in, &res);
866 if (res.add_symbol.len || res.sub_symbol.len)
867 ERROR ((stderr, "%s", emsg));
868 *val = res.value;
869 return idx;
873 sb label; /* current label parsed from line */
874 hash_table assign_hash_table; /* hash table for all assigned variables */
875 hash_table keyword_hash_table; /* hash table for keyword */
876 hash_table vars; /* hash table for eq variables */
878 #define in_comment ';'
880 #if 0
881 static void
882 strip_comments (out)
883 sb *out;
885 char *s = out->ptr;
886 int i = 0;
887 for (i = 0; i < out->len; i++)
889 if (ISCOMMENTCHAR(s[i]))
891 out->len = i;
892 return;
896 #endif
898 /* push back character ch so that it can be read again. */
900 static void
901 unget (ch)
902 int ch;
904 if (ch == '\n')
906 sp->linecount--;
908 if (sp->pushback_index)
909 sp->pushback_index--;
910 else
911 sb_add_char (&sp->pushback, ch);
914 /* push the sb ptr onto the include stack, with the given name, type and index. */
916 static
917 void
918 include_buf (name, ptr, type, index)
919 sb *name;
920 sb *ptr;
921 include_type type;
922 int index;
924 sp++;
925 if (sp - include_stack >= MAX_INCLUDES)
926 FATAL ((stderr, _("unreasonable nesting.\n")));
927 sb_new (&sp->name);
928 sb_add_sb (&sp->name, name);
929 sp->handle = 0;
930 sp->linecount = 1;
931 sp->pushback_index = 0;
932 sp->type = type;
933 sp->index = index;
934 sb_new (&sp->pushback);
935 sb_add_sb (&sp->pushback, ptr);
939 /* used in ERROR messages, print info on where the include stack is onto file. */
940 static
941 void
942 include_print_where_line (file)
943 FILE *file;
945 struct include_stack *p = include_stack + 1;
947 while (p <= sp)
949 fprintf (file, "%s:%d ", sb_name (&p->name), p->linecount - 1);
950 p++;
954 /* used in listings, print the line number onto file. */
955 static void
956 include_print_line (file)
957 FILE *file;
959 int n;
960 struct include_stack *p = include_stack + 1;
962 n = fprintf (file, "%4d", p->linecount);
963 p++;
964 while (p <= sp)
966 n += fprintf (file, ".%d", p->linecount);
967 p++;
969 while (n < 8 * 3)
971 fprintf (file, " ");
972 n++;
977 /* read a line from the top of the include stack into sb in. */
979 static int
980 get_line (in)
981 sb *in;
983 int online = 0;
984 int more = 1;
986 if (copysource)
988 putc (comment_char, outfile);
989 if (print_line_number)
990 include_print_line (outfile);
993 while (1)
995 int ch = get ();
997 while (ch == '\r')
998 ch = get ();
1000 if (ch == EOF)
1002 if (online)
1004 WARNING ((stderr, _("End of file not at start of line.\n")));
1005 if (copysource)
1006 putc ('\n', outfile);
1007 ch = '\n';
1009 else
1010 more = 0;
1011 break;
1014 if (copysource)
1016 putc (ch, outfile);
1019 if (ch == '\n')
1021 ch = get ();
1022 online = 0;
1023 if (ch == '+')
1025 /* continued line */
1026 if (copysource)
1028 putc (comment_char, outfile);
1029 putc ('+', outfile);
1031 ch = get ();
1033 else
1035 if (ch != EOF)
1036 unget (ch);
1037 break;
1040 else
1042 sb_add_char (in, ch);
1044 online++;
1047 return more;
1050 /* find a label from sb in and put it in out. */
1052 static int
1053 grab_label (in, out)
1054 sb *in;
1055 sb *out;
1057 int i = 0;
1058 sb_reset (out);
1059 if (ISFIRSTCHAR (in->ptr[i]) || in->ptr[i] == '\\')
1061 sb_add_char (out, in->ptr[i]);
1062 i++;
1063 while ((ISNEXTCHAR (in->ptr[i])
1064 || in->ptr[i] == '\\'
1065 || in->ptr[i] == '&')
1066 && i < in->len)
1068 sb_add_char (out, in->ptr[i]);
1069 i++;
1072 return i;
1075 /* find all strange base stuff and turn into decimal. also
1076 find all the other numbers and convert them from the default radix */
1078 static void
1079 change_base (idx, in, out)
1080 int idx;
1081 sb *in;
1082 sb *out;
1084 char buffer[20];
1086 while (idx < in->len)
1088 if (in->ptr[idx] == '\\'
1089 && idx + 1 < in->len
1090 && in->ptr[idx + 1] == '(')
1092 idx += 2;
1093 while (idx < in->len
1094 && in->ptr[idx] != ')')
1096 sb_add_char (out, in->ptr[idx]);
1097 idx++;
1099 if (idx < in->len)
1100 idx++;
1102 else if (idx < in->len - 1 && in->ptr[idx + 1] == '\'' && ! mri)
1104 int base;
1105 int value;
1106 switch (in->ptr[idx])
1108 case 'b':
1109 case 'B':
1110 base = 2;
1111 break;
1112 case 'q':
1113 case 'Q':
1114 base = 8;
1115 break;
1116 case 'h':
1117 case 'H':
1118 base = 16;
1119 break;
1120 case 'd':
1121 case 'D':
1122 base = 10;
1123 break;
1124 default:
1125 ERROR ((stderr, _("Illegal base character %c.\n"), in->ptr[idx]));
1126 base = 10;
1127 break;
1130 idx = sb_strtol (idx + 2, in, base, &value);
1131 sprintf (buffer, "%d", value);
1132 sb_add_string (out, buffer);
1134 else if (ISFIRSTCHAR (in->ptr[idx]))
1136 /* copy entire names through quickly */
1137 sb_add_char (out, in->ptr[idx]);
1138 idx++;
1139 while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
1141 sb_add_char (out, in->ptr[idx]);
1142 idx++;
1145 else if (isdigit ((unsigned char) in->ptr[idx]))
1147 int value;
1148 /* all numbers must start with a digit, let's chew it and
1149 spit out decimal */
1150 idx = sb_strtol (idx, in, radix, &value);
1151 sprintf (buffer, "%d", value);
1152 sb_add_string (out, buffer);
1154 /* skip all undigsested letters */
1155 while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
1157 sb_add_char (out, in->ptr[idx]);
1158 idx++;
1161 else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
1163 char tchar = in->ptr[idx];
1164 /* copy entire names through quickly */
1165 sb_add_char (out, in->ptr[idx]);
1166 idx++;
1167 while (idx < in->len && in->ptr[idx] != tchar)
1169 sb_add_char (out, in->ptr[idx]);
1170 idx++;
1173 else
1175 /* nothing special, just pass it through */
1176 sb_add_char (out, in->ptr[idx]);
1177 idx++;
1183 /* .end */
1184 static void
1185 do_end (in)
1186 sb *in;
1188 had_end = 1;
1189 if (mri)
1190 fprintf (outfile, "%s\n", sb_name (in));
1193 /* .assign */
1195 static void
1196 do_assign (again, idx, in)
1197 int again;
1198 int idx;
1199 sb *in;
1201 /* stick label in symbol table with following value */
1202 exp_t e;
1203 sb acc;
1205 sb_new (&acc);
1206 idx = exp_parse (idx, in, &e);
1207 exp_string (&e, &acc);
1208 hash_add_to_string_table (&assign_hash_table, &label, &acc, again);
1209 sb_kill (&acc);
1213 /* .radix [b|q|d|h] */
1215 static
1216 void
1217 do_radix (ptr)
1218 sb *ptr;
1220 int idx = sb_skip_white (0, ptr);
1221 switch (ptr->ptr[idx])
1223 case 'B':
1224 case 'b':
1225 radix = 2;
1226 break;
1227 case 'q':
1228 case 'Q':
1229 radix = 8;
1230 break;
1231 case 'd':
1232 case 'D':
1233 radix = 10;
1234 break;
1235 case 'h':
1236 case 'H':
1237 radix = 16;
1238 break;
1239 default:
1240 ERROR ((stderr, _("radix is %c must be one of b, q, d or h"), radix));
1245 /* Parse off a .b, .w or .l */
1247 static int
1248 get_opsize (idx, in, size)
1249 int idx;
1250 sb *in;
1251 int *size;
1253 *size = 4;
1254 if (in->ptr[idx] == '.')
1256 idx++;
1258 switch (in->ptr[idx])
1260 case 'b':
1261 case 'B':
1262 *size = 1;
1263 break;
1264 case 'w':
1265 case 'W':
1266 *size = 2;
1267 break;
1268 case 'l':
1269 case 'L':
1270 *size = 4;
1271 break;
1272 case ' ':
1273 case '\t':
1274 break;
1275 default:
1276 ERROR ((stderr, _("size must be one of b, w or l, is %c.\n"), in->ptr[idx]));
1277 break;
1279 idx++;
1281 return idx;
1284 static
1285 int eol(idx, line)
1286 int idx;
1287 sb *line;
1289 idx = sb_skip_white (idx, line);
1290 if (idx < line->len
1291 && ISCOMMENTCHAR(line->ptr[idx]))
1292 return 1;
1293 if (idx >= line->len)
1294 return 1;
1295 return 0;
1298 /* .data [.b|.w|.l] <data>*
1299 or d[bwl] <data>* */
1301 static void
1302 do_data (idx, in, size)
1303 int idx;
1304 sb *in;
1305 int size;
1307 int opsize = 4;
1308 char *opname = ".yikes!";
1309 sb acc;
1310 sb_new (&acc);
1312 if (!size)
1314 idx = get_opsize (idx, in, &opsize);
1316 else {
1317 opsize = size;
1319 switch (opsize)
1321 case 4:
1322 opname = ".long";
1323 break;
1324 case 2:
1325 opname = ".short";
1326 break;
1327 case 1:
1328 opname = ".byte";
1329 break;
1333 fprintf (outfile, "%s\t", opname);
1335 idx = sb_skip_white (idx, in);
1337 if (alternate
1338 && idx < in->len
1339 && in->ptr[idx] == '"')
1341 int i;
1342 idx = getstring (idx, in, &acc);
1343 for (i = 0; i < acc.len; i++)
1345 if (i)
1346 fprintf(outfile,",");
1347 fprintf (outfile, "%d", acc.ptr[i]);
1350 else
1352 while (!eol (idx, in))
1354 exp_t e;
1355 idx = exp_parse (idx, in, &e);
1356 exp_string (&e, &acc);
1357 sb_add_char (&acc, 0);
1358 fprintf (outfile, "%s", acc.ptr);
1359 if (idx < in->len && in->ptr[idx] == ',')
1361 fprintf (outfile, ",");
1362 idx++;
1366 sb_kill (&acc);
1367 sb_print_at (outfile, idx, in);
1368 fprintf (outfile, "\n");
1371 /* .datab [.b|.w|.l] <repeat>,<fill> */
1373 static void
1374 do_datab (idx, in)
1375 int idx;
1376 sb *in;
1378 int opsize;
1379 int repeat;
1380 int fill;
1382 idx = get_opsize (idx, in, &opsize);
1384 idx = exp_get_abs (_("datab repeat must be constant.\n"), idx, in, &repeat);
1385 idx = sb_skip_comma (idx, in);
1386 idx = exp_get_abs (_("datab data must be absolute.\n"), idx, in, &fill);
1388 fprintf (outfile, ".fill\t%d,%d,%d\n", repeat, opsize, fill);
1391 /* .align <size> */
1393 static void
1394 do_align (idx, in)
1395 int idx;
1396 sb *in;
1398 int al, have_fill, fill;
1400 idx = exp_get_abs (_("align needs absolute expression.\n"), idx, in, &al);
1401 idx = sb_skip_white (idx, in);
1402 have_fill = 0;
1403 fill = 0;
1404 if (! eol (idx, in))
1406 idx = sb_skip_comma (idx, in);
1407 idx = exp_get_abs (_(".align needs absolute fill value.\n"), idx, in,
1408 &fill);
1409 have_fill = 1;
1412 fprintf (outfile, ".align %d", al);
1413 if (have_fill)
1414 fprintf (outfile, ",%d", fill);
1415 fprintf (outfile, "\n");
1418 /* .res[.b|.w|.l] <size> */
1420 static void
1421 do_res (idx, in, type)
1422 int idx;
1423 sb *in;
1424 int type;
1426 int size = 4;
1427 int count = 0;
1429 idx = get_opsize (idx, in, &size);
1430 while (!eol(idx, in))
1432 idx = sb_skip_white (idx, in);
1433 if (in->ptr[idx] == ',')
1434 idx++;
1435 idx = exp_get_abs (_("res needs absolute expression for fill count.\n"), idx, in, &count);
1437 if (type == 'c' || type == 'z')
1438 count++;
1440 fprintf (outfile, ".space %d\n", count * size);
1445 /* .export */
1447 static void
1448 do_export (in)
1449 sb *in;
1451 fprintf (outfile, ".global %s\n", sb_name (in));
1454 /* .print [list] [nolist] */
1456 static void
1457 do_print (idx, in)
1458 int idx;
1459 sb *in;
1461 idx = sb_skip_white (idx, in);
1462 while (idx < in->len)
1464 if (strncasecmp (in->ptr + idx, "LIST", 4) == 0)
1466 fprintf (outfile, ".list\n");
1467 idx += 4;
1469 else if (strncasecmp (in->ptr + idx, "NOLIST", 6) == 0)
1471 fprintf (outfile, ".nolist\n");
1472 idx += 6;
1474 idx++;
1478 /* .head */
1479 static void
1480 do_heading (idx, in)
1481 int idx;
1482 sb *in;
1484 sb head;
1485 sb_new (&head);
1486 idx = getstring (idx, in, &head);
1487 fprintf (outfile, ".title \"%s\"\n", sb_name (&head));
1488 sb_kill (&head);
1491 /* .page */
1493 static void
1494 do_page ()
1496 fprintf (outfile, ".eject\n");
1499 /* .form [lin=<value>] [col=<value>] */
1500 static void
1501 do_form (idx, in)
1502 int idx;
1503 sb *in;
1505 int lines = 60;
1506 int columns = 132;
1507 idx = sb_skip_white (idx, in);
1509 while (idx < in->len)
1512 if (strncasecmp (in->ptr + idx, "LIN=", 4) == 0)
1514 idx += 4;
1515 idx = exp_get_abs (_("form LIN= needs absolute expresssion.\n"), idx, in, &lines);
1518 if (strncasecmp (in->ptr + idx, _("COL="), 4) == 0)
1520 idx += 4;
1521 idx = exp_get_abs (_("form COL= needs absolute expresssion.\n"), idx, in, &columns);
1524 idx++;
1526 fprintf (outfile, ".psize %d,%d\n", lines, columns);
1531 /* Fetch string from the input stream,
1532 rules:
1533 'Bxyx<whitespace> -> return 'Bxyza
1534 %<char> -> return string of decimal value of x
1535 "<string>" -> return string
1536 xyx<whitespace> -> return xyz
1538 static int
1539 get_any_string (idx, in, out, expand, pretend_quoted)
1540 int idx;
1541 sb *in;
1542 sb *out;
1543 int expand;
1544 int pretend_quoted;
1546 sb_reset (out);
1547 idx = sb_skip_white (idx, in);
1549 if (idx < in->len)
1551 if (in->len > 2 && in->ptr[idx+1] == '\'' && ISBASE (in->ptr[idx]))
1553 while (!ISSEP (in->ptr[idx]))
1554 sb_add_char (out, in->ptr[idx++]);
1556 else if (in->ptr[idx] == '%'
1557 && alternate
1558 && expand)
1560 int val;
1561 char buf[20];
1562 /* Turns the next expression into a string */
1563 idx = exp_get_abs (_("% operator needs absolute expression"),
1564 idx + 1,
1566 &val);
1567 sprintf(buf, "%d", val);
1568 sb_add_string (out, buf);
1570 else if (in->ptr[idx] == '"'
1571 || in->ptr[idx] == '<'
1572 || (alternate && in->ptr[idx] == '\''))
1574 if (alternate && expand)
1576 /* Keep the quotes */
1577 sb_add_char (out, '\"');
1579 idx = getstring (idx, in, out);
1580 sb_add_char (out, '\"');
1583 else {
1584 idx = getstring (idx, in, out);
1587 else
1589 while (idx < in->len
1590 && (in->ptr[idx] == '"'
1591 || in->ptr[idx] == '\''
1592 || pretend_quoted
1593 || !ISSEP (in->ptr[idx])))
1595 if (in->ptr[idx] == '"'
1596 || in->ptr[idx] == '\'')
1598 char tchar = in->ptr[idx];
1599 sb_add_char (out, in->ptr[idx++]);
1600 while (idx < in->len
1601 && in->ptr[idx] != tchar)
1602 sb_add_char (out, in->ptr[idx++]);
1603 if (idx == in->len)
1604 return idx;
1606 sb_add_char (out, in->ptr[idx++]);
1611 return idx;
1615 /* skip along sb in starting at idx, suck off whitespace a ( and more
1616 whitespace. return the idx of the next char */
1618 static int
1619 skip_openp (idx, in)
1620 int idx;
1621 sb *in;
1623 idx = sb_skip_white (idx, in);
1624 if (in->ptr[idx] != '(')
1625 ERROR ((stderr, _("misplaced ( .\n")));
1626 idx = sb_skip_white (idx + 1, in);
1627 return idx;
1630 /* skip along sb in starting at idx, suck off whitespace a ) and more
1631 whitespace. return the idx of the next char */
1633 static int
1634 skip_closep (idx, in)
1635 int idx;
1636 sb *in;
1638 idx = sb_skip_white (idx, in);
1639 if (in->ptr[idx] != ')')
1640 ERROR ((stderr, _("misplaced ).\n")));
1641 idx = sb_skip_white (idx + 1, in);
1642 return idx;
1645 /* .len */
1647 static int
1648 dolen (idx, in, out)
1649 int idx;
1650 sb *in;
1651 sb *out;
1654 sb stringout;
1655 char buffer[10];
1657 sb_new (&stringout);
1658 idx = skip_openp (idx, in);
1659 idx = get_and_process (idx, in, &stringout);
1660 idx = skip_closep (idx, in);
1661 sprintf (buffer, "%d", stringout.len);
1662 sb_add_string (out, buffer);
1664 sb_kill (&stringout);
1665 return idx;
1669 /* .instr */
1671 static
1673 doinstr (idx, in, out)
1674 int idx;
1675 sb *in;
1676 sb *out;
1678 sb string;
1679 sb search;
1680 int i;
1681 int start;
1682 int res;
1683 char buffer[10];
1685 sb_new (&string);
1686 sb_new (&search);
1687 idx = skip_openp (idx, in);
1688 idx = get_and_process (idx, in, &string);
1689 idx = sb_skip_comma (idx, in);
1690 idx = get_and_process (idx, in, &search);
1691 idx = sb_skip_comma (idx, in);
1692 if (isdigit ((unsigned char) in->ptr[idx]))
1694 idx = exp_get_abs (_(".instr needs absolute expresson.\n"), idx, in, &start);
1696 else
1698 start = 0;
1700 idx = skip_closep (idx, in);
1701 res = -1;
1702 for (i = start; i < string.len; i++)
1704 if (strncmp (string.ptr + i, search.ptr, search.len) == 0)
1706 res = i;
1707 break;
1710 sprintf (buffer, "%d", res);
1711 sb_add_string (out, buffer);
1712 sb_kill (&string);
1713 sb_kill (&search);
1714 return idx;
1718 static int
1719 dosubstr (idx, in, out)
1720 int idx;
1721 sb *in;
1722 sb *out;
1724 sb string;
1725 int pos;
1726 int len;
1727 sb_new (&string);
1729 idx = skip_openp (idx, in);
1730 idx = get_and_process (idx, in, &string);
1731 idx = sb_skip_comma (idx, in);
1732 idx = exp_get_abs (_("need absolute position.\n"), idx, in, &pos);
1733 idx = sb_skip_comma (idx, in);
1734 idx = exp_get_abs (_("need absolute length.\n"), idx, in, &len);
1735 idx = skip_closep (idx, in);
1738 if (len < 0 || pos < 0 ||
1739 pos > string.len
1740 || pos + len > string.len)
1742 sb_add_string (out, " ");
1744 else
1746 sb_add_char (out, '"');
1747 while (len > 0)
1749 sb_add_char (out, string.ptr[pos++]);
1750 len--;
1752 sb_add_char (out, '"');
1754 sb_kill(&string);
1755 return idx;
1758 /* scan line, change tokens in the hash table to their replacements */
1759 static void
1760 process_assigns (idx, in, buf)
1761 int idx;
1762 sb *in;
1763 sb *buf;
1765 while (idx < in->len)
1767 hash_entry *ptr;
1768 if (in->ptr[idx] == '\\'
1769 && idx + 1 < in->len
1770 && in->ptr[idx + 1] == '(')
1774 sb_add_char (buf, in->ptr[idx]);
1775 idx++;
1777 while (idx < in->len && in->ptr[idx - 1] != ')');
1779 else if (in->ptr[idx] == '\\'
1780 && idx + 1 < in->len
1781 && in->ptr[idx + 1] == '&')
1783 idx = condass_lookup_name (in, idx + 2, buf, 1);
1785 else if (in->ptr[idx] == '\\'
1786 && idx + 1 < in->len
1787 && in->ptr[idx + 1] == '$')
1789 idx = condass_lookup_name (in, idx + 2, buf, 0);
1791 else if (idx + 3 < in->len
1792 && in->ptr[idx] == '.'
1793 && toupper ((unsigned char) in->ptr[idx + 1]) == 'L'
1794 && toupper ((unsigned char) in->ptr[idx + 2]) == 'E'
1795 && toupper ((unsigned char) in->ptr[idx + 3]) == 'N')
1796 idx = dolen (idx + 4, in, buf);
1797 else if (idx + 6 < in->len
1798 && in->ptr[idx] == '.'
1799 && toupper ((unsigned char) in->ptr[idx + 1]) == 'I'
1800 && toupper ((unsigned char) in->ptr[idx + 2]) == 'N'
1801 && toupper ((unsigned char) in->ptr[idx + 3]) == 'S'
1802 && toupper ((unsigned char) in->ptr[idx + 4]) == 'T'
1803 && toupper ((unsigned char) in->ptr[idx + 5]) == 'R')
1804 idx = doinstr (idx + 6, in, buf);
1805 else if (idx + 7 < in->len
1806 && in->ptr[idx] == '.'
1807 && toupper ((unsigned char) in->ptr[idx + 1]) == 'S'
1808 && toupper ((unsigned char) in->ptr[idx + 2]) == 'U'
1809 && toupper ((unsigned char) in->ptr[idx + 3]) == 'B'
1810 && toupper ((unsigned char) in->ptr[idx + 4]) == 'S'
1811 && toupper ((unsigned char) in->ptr[idx + 5]) == 'T'
1812 && toupper ((unsigned char) in->ptr[idx + 6]) == 'R')
1813 idx = dosubstr (idx + 7, in, buf);
1814 else if (ISFIRSTCHAR (in->ptr[idx]))
1816 /* may be a simple name subsitution, see if we have a word */
1817 sb acc;
1818 int cur = idx + 1;
1819 while (cur < in->len
1820 && (ISNEXTCHAR (in->ptr[cur])))
1821 cur++;
1823 sb_new (&acc);
1824 sb_add_buffer (&acc, in->ptr + idx, cur - idx);
1825 ptr = hash_lookup (&assign_hash_table, &acc);
1826 if (ptr)
1828 /* Found a definition for it */
1829 sb_add_sb (buf, &ptr->value.s);
1831 else
1833 /* No definition, just copy the word */
1834 sb_add_sb (buf, &acc);
1836 sb_kill (&acc);
1837 idx = cur;
1839 else
1841 sb_add_char (buf, in->ptr[idx++]);
1846 static int
1847 get_and_process (idx, in, out)
1848 int idx;
1849 sb *in;
1850 sb *out;
1852 sb t;
1853 sb_new (&t);
1854 idx = get_any_string (idx, in, &t, 1, 0);
1855 process_assigns (0, &t, out);
1856 sb_kill (&t);
1857 return idx;
1860 static
1861 void
1862 process_file ()
1864 sb line;
1865 sb t1, t2;
1866 sb acc;
1867 sb label_in;
1868 int more;
1870 sb_new (&line);
1871 sb_new (&t1);
1872 sb_new (&t2);
1873 sb_new(&acc);
1874 sb_new (&label_in);
1875 sb_reset (&line);
1876 more = get_line (&line);
1877 while (more)
1879 /* Find any label and pseudo op that we're intested in */
1880 int l;
1881 if (line.len == 0)
1883 if (condass_on ())
1884 fprintf (outfile, "\n");
1886 else if (mri
1887 && (line.ptr[0] == '*'
1888 || line.ptr[0] == '!'))
1890 /* MRI line comment. */
1891 fprintf (outfile, "%s", sb_name (&line));
1893 else
1895 l = grab_label (&line, &label_in);
1896 sb_reset (&label);
1898 if (line.ptr[l] == ':')
1899 l++;
1900 while (ISWHITE (line.ptr[l]) && l < line.len)
1901 l++;
1903 if (label_in.len)
1905 int do_assigns;
1907 /* Munge the label, unless this is EQU or ASSIGN. */
1908 do_assigns = 1;
1909 if (l < line.len
1910 && (line.ptr[l] == '.' || alternate || mri))
1912 int lx = l;
1914 if (line.ptr[lx] == '.')
1915 ++lx;
1916 if (lx + 3 <= line.len
1917 && strncasecmp ("EQU", line.ptr + lx, 3) == 0
1918 && (lx + 3 == line.len
1919 || ! ISFIRSTCHAR (line.ptr[lx + 3])))
1920 do_assigns = 0;
1921 else if (lx + 6 <= line.len
1922 && strncasecmp ("ASSIGN", line.ptr + lx, 6) == 0
1923 && (lx + 6 == line.len
1924 || ! ISFIRSTCHAR (line.ptr[lx + 6])))
1925 do_assigns = 0;
1928 if (do_assigns)
1929 process_assigns (0, &label_in, &label);
1930 else
1931 sb_add_sb (&label, &label_in);
1934 if (l < line.len)
1936 if (process_pseudo_op (l, &line, &acc))
1942 else if (condass_on ())
1944 if (macro_op (l, &line))
1949 else
1952 if (label.len)
1954 fprintf (outfile, "%s:\t", sb_name (&label));
1956 else
1957 fprintf (outfile, "\t");
1958 sb_reset(&t1);
1959 process_assigns (l, &line, &t1);
1960 sb_reset (&t2);
1961 change_base (0, &t1, &t2);
1962 fprintf (outfile, "%s\n", sb_name (&t2));
1967 else {
1968 /* Only a label on this line */
1969 if (label.len && condass_on())
1971 fprintf (outfile, "%s:\n", sb_name (&label));
1976 if (had_end)
1977 break;
1978 sb_reset (&line);
1979 more = get_line (&line);
1982 if (!had_end && !mri)
1983 WARNING ((stderr, _("END missing from end of file.\n")));
1990 static void
1991 free_old_entry (ptr)
1992 hash_entry *ptr;
1994 if (ptr)
1996 if (ptr->type == hash_string)
1997 sb_kill(&ptr->value.s);
2001 /* name: .ASSIGNA <value> */
2003 static void
2004 do_assigna (idx, in)
2005 int idx;
2006 sb *in;
2008 sb tmp;
2009 int val;
2010 sb_new (&tmp);
2012 process_assigns (idx, in, &tmp);
2013 idx = exp_get_abs (_(".ASSIGNA needs constant expression argument.\n"), 0, &tmp, &val);
2015 if (!label.len)
2017 ERROR ((stderr, _(".ASSIGNA without label.\n")));
2019 else
2021 hash_entry *ptr = hash_create (&vars, &label);
2022 free_old_entry (ptr);
2023 ptr->type = hash_integer;
2024 ptr->value.i = val;
2026 sb_kill (&tmp);
2029 /* name: .ASSIGNC <string> */
2031 static void
2032 do_assignc (idx, in)
2033 int idx;
2034 sb *in;
2036 sb acc;
2037 sb_new (&acc);
2038 idx = getstring (idx, in, &acc);
2040 if (!label.len)
2042 ERROR ((stderr, _(".ASSIGNS without label.\n")));
2044 else
2046 hash_entry *ptr = hash_create (&vars, &label);
2047 free_old_entry (ptr);
2048 ptr->type = hash_string;
2049 sb_new (&ptr->value.s);
2050 sb_add_sb (&ptr->value.s, &acc);
2052 sb_kill (&acc);
2056 /* name: .REG (reg) */
2058 static void
2059 do_reg (idx, in)
2060 int idx;
2061 sb *in;
2063 /* remove reg stuff from inside parens */
2064 sb what;
2065 if (!mri)
2066 idx = skip_openp (idx, in);
2067 else
2068 idx = sb_skip_white (idx, in);
2069 sb_new (&what);
2070 while (idx < in->len
2071 && (mri
2072 ? ! eol (idx, in)
2073 : in->ptr[idx] != ')'))
2075 sb_add_char (&what, in->ptr[idx]);
2076 idx++;
2078 hash_add_to_string_table (&assign_hash_table, &label, &what, 1);
2079 sb_kill (&what);
2083 static int
2084 condass_lookup_name (inbuf, idx, out, warn)
2085 sb *inbuf;
2086 int idx;
2087 sb *out;
2088 int warn;
2090 hash_entry *ptr;
2091 sb condass_acc;
2092 sb_new (&condass_acc);
2094 while (idx < inbuf->len
2095 && ISNEXTCHAR (inbuf->ptr[idx]))
2097 sb_add_char (&condass_acc, inbuf->ptr[idx++]);
2100 if (inbuf->ptr[idx] == '\'')
2101 idx++;
2102 ptr = hash_lookup (&vars, &condass_acc);
2105 if (!ptr)
2107 if (warn)
2109 WARNING ((stderr, _("Can't find preprocessor variable %s.\n"), sb_name (&condass_acc)));
2111 else
2113 sb_add_string (out, "0");
2116 else
2118 if (ptr->type == hash_integer)
2120 char buffer[30];
2121 sprintf (buffer, "%d", ptr->value.i);
2122 sb_add_string (out, buffer);
2124 else
2126 sb_add_sb (out, &ptr->value.s);
2129 sb_kill (&condass_acc);
2130 return idx;
2133 #define EQ 1
2134 #define NE 2
2135 #define GE 3
2136 #define LT 4
2137 #define LE 5
2138 #define GT 6
2139 #define NEVER 7
2141 static int
2142 whatcond (idx, in, val)
2143 int idx;
2144 sb *in;
2145 int *val;
2147 int cond;
2149 idx = sb_skip_white (idx, in);
2150 cond = NEVER;
2151 if (idx + 1 < in->len)
2153 char *p;
2154 char a, b;
2156 p = in->ptr + idx;
2157 a = toupper ((unsigned char) p[0]);
2158 b = toupper ((unsigned char) p[1]);
2159 if (a == 'E' && b == 'Q')
2160 cond = EQ;
2161 else if (a == 'N' && b == 'E')
2162 cond = NE;
2163 else if (a == 'L' && b == 'T')
2164 cond = LT;
2165 else if (a == 'L' && b == 'E')
2166 cond = LE;
2167 else if (a == 'G' && b == 'T')
2168 cond = GT;
2169 else if (a == 'G' && b == 'E')
2170 cond = GE;
2172 if (cond == NEVER)
2174 ERROR ((stderr, _("Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n")));
2175 cond = NEVER;
2177 idx = sb_skip_white (idx + 2, in);
2178 *val = cond;
2179 return idx;
2182 static int
2183 istrue (idx, in)
2184 int idx;
2185 sb *in;
2187 int res;
2188 sb acc_a;
2189 sb cond;
2190 sb acc_b;
2191 sb_new (&acc_a);
2192 sb_new (&cond);
2193 sb_new (&acc_b);
2194 idx = sb_skip_white (idx, in);
2196 if (in->ptr[idx] == '"')
2198 int cond;
2199 int same;
2200 /* This is a string comparision */
2201 idx = getstring (idx, in, &acc_a);
2202 idx = whatcond (idx, in, &cond);
2203 idx = getstring (idx, in, &acc_b);
2204 same = acc_a.len == acc_b.len && (strncmp (acc_a.ptr, acc_b.ptr, acc_a.len) == 0);
2206 if (cond != EQ && cond != NE)
2208 ERROR ((stderr, _("Comparison operator for strings must be EQ or NE\n")));
2209 res = 0;
2211 else
2212 res = (cond != EQ) ^ same;
2214 else
2215 /* This is a numeric expression */
2217 int vala;
2218 int valb;
2219 int cond;
2220 idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"), idx, in, &vala);
2221 idx = whatcond (idx, in, &cond);
2222 idx = sb_skip_white (idx, in);
2223 if (in->ptr[idx] == '"')
2225 WARNING ((stderr, _("String compared against expression.\n")));
2226 res = 0;
2228 else
2230 idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"), idx, in, &valb);
2231 switch (cond)
2233 default:
2234 res = 42;
2235 break;
2236 case EQ:
2237 res = vala == valb;
2238 break;
2239 case NE:
2240 res = vala != valb;
2241 break;
2242 case LT:
2243 res = vala < valb;
2244 break;
2245 case LE:
2246 res = vala <= valb;
2247 break;
2248 case GT:
2249 res = vala > valb;
2250 break;
2251 case GE:
2252 res = vala >= valb;
2253 break;
2254 case NEVER:
2255 res = 0;
2256 break;
2261 sb_kill (&acc_a);
2262 sb_kill (&cond);
2263 sb_kill (&acc_b);
2264 return res;
2267 /* .AIF */
2268 static void
2269 do_aif (idx, in)
2270 int idx;
2271 sb *in;
2273 if (ifi >= IFNESTING)
2275 FATAL ((stderr, _("AIF nesting unreasonable.\n")));
2277 ifi++;
2278 ifstack[ifi].on = ifstack[ifi-1].on ? istrue (idx, in) : 0;
2279 ifstack[ifi].hadelse = 0;
2283 /* .AELSE */
2284 static void
2285 do_aelse ()
2287 ifstack[ifi].on = ifstack[ifi-1].on ? !ifstack[ifi].on : 0;
2288 if (ifstack[ifi].hadelse)
2290 ERROR ((stderr, _("Multiple AELSEs in AIF.\n")));
2292 ifstack[ifi].hadelse = 1;
2296 /* .AENDI */
2297 static void
2298 do_aendi ()
2300 if (ifi != 0)
2302 ifi--;
2304 else
2306 ERROR ((stderr, _("AENDI without AIF.\n")));
2310 static int
2311 condass_on ()
2313 return ifstack[ifi].on;
2316 /* MRI IFEQ, IFNE, IFLT, IFLE, IFGE, IFGT. */
2318 static void
2319 do_if (idx, in, cond)
2320 int idx;
2321 sb *in;
2322 int cond;
2324 int val;
2325 int res;
2327 if (ifi >= IFNESTING)
2329 FATAL ((stderr, _("IF nesting unreasonable.\n")));
2332 idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"),
2333 idx, in, &val);
2334 switch (cond)
2336 default:
2337 case EQ: res = val == 0; break;
2338 case NE: res = val != 0; break;
2339 case LT: res = val < 0; break;
2340 case LE: res = val <= 0; break;
2341 case GE: res = val >= 0; break;
2342 case GT: res = val > 0; break;
2345 ifi++;
2346 ifstack[ifi].on = ifstack[ifi-1].on ? res: 0;
2347 ifstack[ifi].hadelse = 0;
2350 /* Get a string for the MRI IFC or IFNC pseudo-ops. */
2352 static int
2353 get_mri_string (idx, in, val, terminator)
2354 int idx;
2355 sb *in;
2356 sb *val;
2357 int terminator;
2359 idx = sb_skip_white (idx, in);
2361 if (idx < in->len
2362 && in->ptr[idx] == '\'')
2364 sb_add_char (val, '\'');
2365 for (++idx; idx < in->len; ++idx)
2367 sb_add_char (val, in->ptr[idx]);
2368 if (in->ptr[idx] == '\'')
2370 ++idx;
2371 if (idx >= in->len
2372 || in->ptr[idx] != '\'')
2373 break;
2376 idx = sb_skip_white (idx, in);
2378 else
2380 int i;
2382 while (idx < in->len
2383 && in->ptr[idx] != terminator)
2385 sb_add_char (val, in->ptr[idx]);
2386 ++idx;
2388 i = val->len - 1;
2389 while (i >= 0 && ISWHITE (val->ptr[i]))
2390 --i;
2391 val->len = i + 1;
2394 return idx;
2397 /* MRI IFC, IFNC. */
2399 static void
2400 do_ifc (idx, in, ifnc)
2401 int idx;
2402 sb *in;
2403 int ifnc;
2405 sb first;
2406 sb second;
2407 int res;
2409 if (ifi >= IFNESTING)
2411 FATAL ((stderr, _("IF nesting unreasonable.\n")));
2414 sb_new (&first);
2415 sb_new (&second);
2417 idx = get_mri_string (idx, in, &first, ',');
2419 if (idx >= in->len || in->ptr[idx] != ',')
2421 ERROR ((stderr, _("Bad format for IF or IFNC.\n")));
2422 return;
2425 idx = get_mri_string (idx + 1, in, &second, ';');
2427 res = (first.len == second.len
2428 && strncmp (first.ptr, second.ptr, first.len) == 0);
2429 res ^= ifnc;
2431 ifi++;
2432 ifstack[ifi].on = ifstack[ifi-1].on ? res : 0;
2433 ifstack[ifi].hadelse = 0;
2436 /* .ENDR */
2437 static void
2438 do_aendr ()
2440 if (!mri)
2441 ERROR ((stderr, _("AENDR without a AREPEAT.\n")));
2442 else
2443 ERROR ((stderr, _("ENDR without a REPT.\n")));
2446 /* .AWHILE */
2448 static
2449 void
2450 do_awhile (idx, in)
2451 int idx;
2452 sb *in;
2454 int line = linecount ();
2455 sb exp;
2456 sb sub;
2457 int doit;
2459 sb_new (&sub);
2460 sb_new (&exp);
2462 process_assigns (idx, in, &exp);
2463 doit = istrue (0, &exp);
2465 if (! buffer_and_nest ("AWHILE", "AENDW", &sub, get_line))
2466 FATAL ((stderr, _("AWHILE without a AENDW at %d.\n"), line - 1));
2468 /* Turn
2469 .AWHILE exp
2471 .AENDW
2472 into
2474 .AWHILE exp
2476 .ENDW
2479 if (doit)
2481 int index = include_next_index ();
2483 sb copy;
2484 sb_new (&copy);
2485 sb_add_sb (&copy, &sub);
2486 sb_add_sb (&copy, in);
2487 sb_add_string (&copy, "\n");
2488 sb_add_sb (&copy, &sub);
2489 sb_add_string (&copy, "\t.AENDW\n");
2490 /* Push another WHILE */
2491 include_buf (&exp, &copy, include_while, index);
2492 sb_kill (&copy);
2494 sb_kill (&exp);
2495 sb_kill (&sub);
2499 /* .AENDW */
2501 static void
2502 do_aendw ()
2504 ERROR ((stderr, _("AENDW without a AENDW.\n")));
2508 /* .EXITM
2510 Pop things off the include stack until the type and index changes */
2512 static void
2513 do_exitm ()
2515 include_type type = sp->type;
2516 if (type == include_repeat
2517 || type == include_while
2518 || type == include_macro)
2520 int index = sp->index;
2521 include_pop ();
2522 while (sp->index == index
2523 && sp->type == type)
2525 include_pop ();
2530 /* .AREPEAT */
2532 static void
2533 do_arepeat (idx, in)
2534 int idx;
2535 sb *in;
2537 int line = linecount ();
2538 sb exp; /* buffer with expression in it */
2539 sb copy; /* expanded repeat block */
2540 sb sub; /* contents of AREPEAT */
2541 int rc;
2542 int ret;
2543 char buffer[30];
2545 sb_new (&exp);
2546 sb_new (&copy);
2547 sb_new (&sub);
2548 process_assigns (idx, in, &exp);
2549 idx = exp_get_abs (_("AREPEAT must have absolute operand.\n"), 0, &exp, &rc);
2550 if (!mri)
2551 ret = buffer_and_nest ("AREPEAT", "AENDR", &sub, get_line);
2552 else
2553 ret = buffer_and_nest ("REPT", "ENDR", &sub, get_line);
2554 if (! ret)
2555 FATAL ((stderr, _("AREPEAT without a AENDR at %d.\n"), line - 1));
2556 if (rc > 0)
2558 /* Push back the text following the repeat, and another repeat block
2560 .AREPEAT 20
2562 .AENDR
2563 gets turned into
2565 .AREPEAT 19
2567 .AENDR
2569 int index = include_next_index ();
2570 sb_add_sb (&copy, &sub);
2571 if (rc > 1)
2573 if (!mri)
2574 sprintf (buffer, "\t.AREPEAT %d\n", rc - 1);
2575 else
2576 sprintf (buffer, "\tREPT %d\n", rc - 1);
2577 sb_add_string (&copy, buffer);
2578 sb_add_sb (&copy, &sub);
2579 if (!mri)
2580 sb_add_string (&copy, " .AENDR\n");
2581 else
2582 sb_add_string (&copy, " ENDR\n");
2585 include_buf (&exp, &copy, include_repeat, index);
2587 sb_kill (&exp);
2588 sb_kill (&sub);
2589 sb_kill (&copy);
2592 /* .ENDM */
2594 static void
2595 do_endm ()
2597 ERROR ((stderr, _(".ENDM without a matching .MACRO.\n")));
2600 /* MRI IRP pseudo-op. */
2602 static void
2603 do_irp (idx, in, irpc)
2604 int idx;
2605 sb *in;
2606 int irpc;
2608 const char *err;
2609 sb out;
2611 sb_new (&out);
2613 err = expand_irp (irpc, idx, in, &out, get_line, comment_char);
2614 if (err != NULL)
2615 ERROR ((stderr, "%s\n", err));
2617 fprintf (outfile, "%s", sb_terminate (&out));
2619 sb_kill (&out);
2622 /* MACRO PROCESSING */
2624 /* Parse off LOCAL n1, n2,... Invent a label name for it */
2625 static
2626 void
2627 do_local (idx, line)
2628 int idx ATTRIBUTE_UNUSED;
2629 sb *line ATTRIBUTE_UNUSED;
2631 ERROR ((stderr, _("LOCAL outside of MACRO")));
2634 static void
2635 do_macro (idx, in)
2636 int idx;
2637 sb *in;
2639 const char *err;
2640 int line = linecount ();
2642 err = define_macro (idx, in, &label, get_line, (const char **) NULL);
2643 if (err != NULL)
2644 ERROR ((stderr, _("macro at line %d: %s\n"), line - 1, err));
2647 static int
2648 macro_op (idx, in)
2649 int idx;
2650 sb *in;
2652 const char *err;
2653 sb out;
2654 sb name;
2656 if (! macro_defined)
2657 return 0;
2659 sb_terminate (in);
2660 if (! check_macro (in->ptr + idx, &out, comment_char, &err, NULL))
2661 return 0;
2663 if (err != NULL)
2664 ERROR ((stderr, "%s\n", err));
2666 sb_new (&name);
2667 sb_add_string (&name, _("macro expansion"));
2669 include_buf (&name, &out, include_macro, include_next_index ());
2671 sb_kill (&name);
2672 sb_kill (&out);
2674 return 1;
2677 /* STRING HANDLING */
2679 static int
2680 getstring (idx, in, acc)
2681 int idx;
2682 sb *in;
2683 sb *acc;
2685 idx = sb_skip_white (idx, in);
2687 while (idx < in->len
2688 && (in->ptr[idx] == '"'
2689 || in->ptr[idx] == '<'
2690 || (in->ptr[idx] == '\'' && alternate)))
2692 if (in->ptr[idx] == '<')
2694 if (alternate || mri)
2696 int nest = 0;
2697 idx++;
2698 while ((in->ptr[idx] != '>' || nest)
2699 && idx < in->len)
2701 if (in->ptr[idx] == '!')
2703 idx++ ;
2704 sb_add_char (acc, in->ptr[idx++]);
2706 else {
2707 if (in->ptr[idx] == '>')
2708 nest--;
2709 if (in->ptr[idx] == '<')
2710 nest++;
2711 sb_add_char (acc, in->ptr[idx++]);
2714 idx++;
2716 else {
2717 int code;
2718 idx++;
2719 idx = exp_get_abs (_("Character code in string must be absolute expression.\n"),
2720 idx, in, &code);
2721 sb_add_char (acc, code);
2723 if (in->ptr[idx] != '>')
2724 ERROR ((stderr, _("Missing > for character code.\n")));
2725 idx++;
2728 else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
2730 char tchar = in->ptr[idx];
2731 idx++;
2732 while (idx < in->len)
2734 if (alternate && in->ptr[idx] == '!')
2736 idx++ ;
2737 sb_add_char (acc, in->ptr[idx++]);
2739 else {
2740 if (in->ptr[idx] == tchar)
2742 idx++;
2743 if (idx >= in->len || in->ptr[idx] != tchar)
2744 break;
2746 sb_add_char (acc, in->ptr[idx]);
2747 idx++;
2753 return idx;
2756 /* .SDATA[C|Z] <string> */
2758 static
2759 void
2760 do_sdata (idx, in, type)
2761 int idx;
2762 sb *in;
2763 int type;
2765 int nc = 0;
2766 int pidx = -1;
2767 sb acc;
2768 sb_new (&acc);
2769 fprintf (outfile, ".byte\t");
2771 while (!eol (idx, in))
2773 int i;
2774 sb_reset (&acc);
2775 idx = sb_skip_white (idx, in);
2776 while (!eol (idx, in))
2778 pidx = idx = get_any_string (idx, in, &acc, 0, 1);
2779 if (type == 'c')
2781 if (acc.len > 255)
2783 ERROR ((stderr, _("string for SDATAC longer than 255 characters (%d).\n"), acc.len));
2785 fprintf (outfile, "%d", acc.len);
2786 nc = 1;
2789 for (i = 0; i < acc.len; i++)
2791 if (nc)
2793 fprintf (outfile, ",");
2795 fprintf (outfile, "%d", acc.ptr[i]);
2796 nc = 1;
2799 if (type == 'z')
2801 if (nc)
2802 fprintf (outfile, ",");
2803 fprintf (outfile, "0");
2805 idx = sb_skip_comma (idx, in);
2806 if (idx == pidx) break;
2808 if (!alternate && in->ptr[idx] != ',' && idx != in->len)
2810 fprintf (outfile, "\n");
2811 ERROR ((stderr, _("illegal character in SDATA line (0x%x).\n"), in->ptr[idx]));
2812 break;
2814 idx++;
2816 sb_kill (&acc);
2817 fprintf (outfile, "\n");
2820 /* .SDATAB <count> <string> */
2822 static void
2823 do_sdatab (idx, in)
2824 int idx;
2825 sb *in;
2827 int repeat;
2828 int i;
2829 sb acc;
2830 sb_new (&acc);
2832 idx = exp_get_abs (_("Must have absolute SDATAB repeat count.\n"), idx, in, &repeat);
2833 if (repeat <= 0)
2835 ERROR ((stderr, _("Must have positive SDATAB repeat count (%d).\n"), repeat));
2836 repeat = 1;
2839 idx = sb_skip_comma (idx, in);
2840 idx = getstring (idx, in, &acc);
2842 for (i = 0; i < repeat; i++)
2844 if (i)
2845 fprintf (outfile, "\t");
2846 fprintf (outfile, ".byte\t");
2847 sb_print (outfile, &acc);
2848 fprintf (outfile, "\n");
2850 sb_kill (&acc);
2854 static int
2855 new_file (name)
2856 const char *name;
2858 FILE *newone = fopen (name, "r");
2859 if (!newone)
2860 return 0;
2862 if (isp == MAX_INCLUDES)
2863 FATAL ((stderr, _("Unreasonable include depth (%ld).\n"), (long) isp));
2865 sp++;
2866 sp->handle = newone;
2868 sb_new (&sp->name);
2869 sb_add_string (&sp->name, name);
2871 sp->linecount = 1;
2872 sp->pushback_index = 0;
2873 sp->type = include_file;
2874 sp->index = 0;
2875 sb_new (&sp->pushback);
2876 return 1;
2879 static void
2880 do_include (idx, in)
2881 int idx;
2882 sb *in;
2884 sb t;
2885 sb cat;
2886 include_path *includes;
2888 sb_new (&t);
2889 sb_new (&cat);
2891 if (! mri)
2892 idx = getstring (idx, in, &t);
2893 else
2895 idx = sb_skip_white (idx, in);
2896 while (idx < in->len && ! ISWHITE (in->ptr[idx]))
2898 sb_add_char (&t, in->ptr[idx]);
2899 ++idx;
2903 for (includes = paths_head; includes; includes = includes->next)
2905 sb_reset (&cat);
2906 sb_add_sb (&cat, &includes->path);
2907 sb_add_char (&cat, '/');
2908 sb_add_sb (&cat, &t);
2909 if (new_file (sb_name (&cat)))
2911 break;
2914 if (!includes)
2916 if (! new_file (sb_name (&t)))
2917 FATAL ((stderr, _("Can't open include file `%s'.\n"), sb_name (&t)));
2919 sb_kill (&cat);
2920 sb_kill (&t);
2923 static void
2924 include_pop ()
2926 if (sp != include_stack)
2928 if (sp->handle)
2929 fclose (sp->handle);
2930 sp--;
2934 /* Get the next character from the include stack. If there's anything
2935 in the pushback buffer, take that first. If we're at eof, pop from
2936 the stack and try again. Keep the linecount up to date. */
2938 static int
2939 get ()
2941 int r;
2943 if (sp->pushback.len != sp->pushback_index)
2945 r = (char) (sp->pushback.ptr[sp->pushback_index++]);
2946 /* When they've all gone, reset the pointer */
2947 if (sp->pushback_index == sp->pushback.len)
2949 sp->pushback.len = 0;
2950 sp->pushback_index = 0;
2953 else if (sp->handle)
2955 r = getc (sp->handle);
2957 else
2958 r = EOF;
2960 if (r == EOF && isp)
2962 include_pop ();
2963 r = get ();
2964 while (r == EOF && isp)
2966 include_pop ();
2967 r = get ();
2969 return r;
2971 if (r == '\n')
2973 sp->linecount++;
2976 return r;
2979 static int
2980 linecount ()
2982 return sp->linecount;
2985 static int
2986 include_next_index ()
2988 static int index;
2989 if (!unreasonable
2990 && index > MAX_REASONABLE)
2991 FATAL ((stderr, _("Unreasonable expansion (-u turns off check).\n")));
2992 return ++index;
2996 /* Initialize the chartype vector. */
2998 static void
2999 chartype_init ()
3001 int x;
3002 for (x = 0; x < 256; x++)
3004 if (isalpha (x) || x == '_' || x == '$')
3005 chartype[x] |= FIRSTBIT;
3007 if (mri && x == '.')
3008 chartype[x] |= FIRSTBIT;
3010 if (isdigit (x) || isalpha (x) || x == '_' || x == '$')
3011 chartype[x] |= NEXTBIT;
3013 if (x == ' ' || x == '\t' || x == ',' || x == '"' || x == ';'
3014 || x == '"' || x == '<' || x == '>' || x == ')' || x == '(')
3015 chartype[x] |= SEPBIT;
3017 if (x == 'b' || x == 'B'
3018 || x == 'q' || x == 'Q'
3019 || x == 'h' || x == 'H'
3020 || x == 'd' || x == 'D')
3021 chartype [x] |= BASEBIT;
3023 if (x == ' ' || x == '\t')
3024 chartype[x] |= WHITEBIT;
3026 if (x == comment_char)
3027 chartype[x] |= COMMENTBIT;
3033 /* What to do with all the keywords */
3034 #define PROCESS 0x1000 /* Run substitution over the line */
3035 #define LAB 0x2000 /* Spit out the label */
3037 #define K_EQU (PROCESS|1)
3038 #define K_ASSIGN (PROCESS|2)
3039 #define K_REG (PROCESS|3)
3040 #define K_ORG (PROCESS|4)
3041 #define K_RADIX (PROCESS|5)
3042 #define K_DATA (LAB|PROCESS|6)
3043 #define K_DATAB (LAB|PROCESS|7)
3044 #define K_SDATA (LAB|PROCESS|8)
3045 #define K_SDATAB (LAB|PROCESS|9)
3046 #define K_SDATAC (LAB|PROCESS|10)
3047 #define K_SDATAZ (LAB|PROCESS|11)
3048 #define K_RES (LAB|PROCESS|12)
3049 #define K_SRES (LAB|PROCESS|13)
3050 #define K_SRESC (LAB|PROCESS|14)
3051 #define K_SRESZ (LAB|PROCESS|15)
3052 #define K_EXPORT (LAB|PROCESS|16)
3053 #define K_GLOBAL (LAB|PROCESS|17)
3054 #define K_PRINT (LAB|PROCESS|19)
3055 #define K_FORM (LAB|PROCESS|20)
3056 #define K_HEADING (LAB|PROCESS|21)
3057 #define K_PAGE (LAB|PROCESS|22)
3058 #define K_IMPORT (LAB|PROCESS|23)
3059 #define K_PROGRAM (LAB|PROCESS|24)
3060 #define K_END (PROCESS|25)
3061 #define K_INCLUDE (PROCESS|26)
3062 #define K_IGNORED (PROCESS|27)
3063 #define K_ASSIGNA (PROCESS|28)
3064 #define K_ASSIGNC (29)
3065 #define K_AIF (PROCESS|30)
3066 #define K_AELSE (PROCESS|31)
3067 #define K_AENDI (PROCESS|32)
3068 #define K_AREPEAT (PROCESS|33)
3069 #define K_AENDR (PROCESS|34)
3070 #define K_AWHILE (35)
3071 #define K_AENDW (PROCESS|36)
3072 #define K_EXITM (37)
3073 #define K_MACRO (PROCESS|38)
3074 #define K_ENDM (39)
3075 #define K_ALIGN (PROCESS|LAB|40)
3076 #define K_ALTERNATE (41)
3077 #define K_DB (LAB|PROCESS|42)
3078 #define K_DW (LAB|PROCESS|43)
3079 #define K_DL (LAB|PROCESS|44)
3080 #define K_LOCAL (45)
3081 #define K_IFEQ (PROCESS|46)
3082 #define K_IFNE (PROCESS|47)
3083 #define K_IFLT (PROCESS|48)
3084 #define K_IFLE (PROCESS|49)
3085 #define K_IFGE (PROCESS|50)
3086 #define K_IFGT (PROCESS|51)
3087 #define K_IFC (PROCESS|52)
3088 #define K_IFNC (PROCESS|53)
3089 #define K_IRP (PROCESS|54)
3090 #define K_IRPC (PROCESS|55)
3093 struct keyword
3095 char *name;
3096 int code;
3097 int extra;
3100 static struct keyword kinfo[] =
3102 { "EQU", K_EQU, 0 },
3103 { "ALTERNATE", K_ALTERNATE, 0 },
3104 { "ASSIGN", K_ASSIGN, 0 },
3105 { "REG", K_REG, 0 },
3106 { "ORG", K_ORG, 0 },
3107 { "RADIX", K_RADIX, 0 },
3108 { "DATA", K_DATA, 0 },
3109 { "DB", K_DB, 0 },
3110 { "DW", K_DW, 0 },
3111 { "DL", K_DL, 0 },
3112 { "DATAB", K_DATAB, 0 },
3113 { "SDATA", K_SDATA, 0 },
3114 { "SDATAB", K_SDATAB, 0 },
3115 { "SDATAZ", K_SDATAZ, 0 },
3116 { "SDATAC", K_SDATAC, 0 },
3117 { "RES", K_RES, 0 },
3118 { "SRES", K_SRES, 0 },
3119 { "SRESC", K_SRESC, 0 },
3120 { "SRESZ", K_SRESZ, 0 },
3121 { "EXPORT", K_EXPORT, 0 },
3122 { "GLOBAL", K_GLOBAL, 0 },
3123 { "PRINT", K_PRINT, 0 },
3124 { "FORM", K_FORM, 0 },
3125 { "HEADING", K_HEADING, 0 },
3126 { "PAGE", K_PAGE, 0 },
3127 { "PROGRAM", K_IGNORED, 0 },
3128 { "END", K_END, 0 },
3129 { "INCLUDE", K_INCLUDE, 0 },
3130 { "ASSIGNA", K_ASSIGNA, 0 },
3131 { "ASSIGNC", K_ASSIGNC, 0 },
3132 { "AIF", K_AIF, 0 },
3133 { "AELSE", K_AELSE, 0 },
3134 { "AENDI", K_AENDI, 0 },
3135 { "AREPEAT", K_AREPEAT, 0 },
3136 { "AENDR", K_AENDR, 0 },
3137 { "EXITM", K_EXITM, 0 },
3138 { "MACRO", K_MACRO, 0 },
3139 { "ENDM", K_ENDM, 0 },
3140 { "AWHILE", K_AWHILE, 0 },
3141 { "ALIGN", K_ALIGN, 0 },
3142 { "AENDW", K_AENDW, 0 },
3143 { "ALTERNATE", K_ALTERNATE, 0 },
3144 { "LOCAL", K_LOCAL, 0 },
3145 { NULL, 0, 0 }
3148 /* Although the conditional operators are handled by gas, we need to
3149 handle them here as well, in case they are used in a recursive
3150 macro to end the recursion. */
3152 static struct keyword mrikinfo[] =
3154 { "IFEQ", K_IFEQ, 0 },
3155 { "IFNE", K_IFNE, 0 },
3156 { "IFLT", K_IFLT, 0 },
3157 { "IFLE", K_IFLE, 0 },
3158 { "IFGE", K_IFGE, 0 },
3159 { "IFGT", K_IFGT, 0 },
3160 { "IFC", K_IFC, 0 },
3161 { "IFNC", K_IFNC, 0 },
3162 { "ELSEC", K_AELSE, 0 },
3163 { "ENDC", K_AENDI, 0 },
3164 { "MEXIT", K_EXITM, 0 },
3165 { "REPT", K_AREPEAT, 0 },
3166 { "IRP", K_IRP, 0 },
3167 { "IRPC", K_IRPC, 0 },
3168 { "ENDR", K_AENDR, 0 },
3169 { NULL, 0, 0 }
3172 /* Look for a pseudo op on the line. If one's there then call
3173 its handler. */
3175 static int
3176 process_pseudo_op (idx, line, acc)
3177 int idx;
3178 sb *line;
3179 sb *acc;
3181 int oidx = idx;
3183 if (line->ptr[idx] == '.' || alternate || mri)
3185 /* Scan forward and find pseudo name */
3186 char *in;
3187 hash_entry *ptr;
3189 char *s;
3190 char *e;
3191 if (line->ptr[idx] == '.')
3192 idx++;
3193 in = line->ptr + idx;
3194 s = in;
3195 e = s;
3196 sb_reset (acc);
3198 while (idx < line->len && *e && ISFIRSTCHAR (*e))
3200 sb_add_char (acc, *e);
3201 e++;
3202 idx++;
3205 ptr = hash_lookup (&keyword_hash_table, acc);
3207 if (!ptr)
3209 #if 0
3210 /* This one causes lots of pain when trying to preprocess
3211 ordinary code */
3212 WARNING ((stderr, _("Unrecognised pseudo op `%s'.\n"), sb_name (acc)));
3213 #endif
3214 return 0;
3216 if (ptr->value.i & LAB)
3217 { /* output the label */
3218 if (label.len)
3220 fprintf (outfile, "%s:\t", sb_name (&label));
3222 else
3223 fprintf (outfile, "\t");
3226 if (mri && ptr->value.i == K_END)
3228 sb t;
3230 sb_new (&t);
3231 sb_add_buffer (&t, line->ptr + oidx, idx - oidx);
3232 fprintf (outfile, "\t%s", sb_name (&t));
3233 sb_kill (&t);
3236 if (ptr->value.i & PROCESS)
3238 /* Polish the rest of the line before handling the pseudo op */
3239 #if 0
3240 strip_comments(line);
3241 #endif
3242 sb_reset (acc);
3243 process_assigns (idx, line, acc);
3244 sb_reset(line);
3245 change_base (0, acc, line);
3246 idx = 0;
3248 if (!condass_on ())
3250 switch (ptr->value.i)
3252 case K_AIF:
3253 do_aif (idx, line);
3254 break;
3255 case K_AELSE:
3256 do_aelse ();
3257 break;
3258 case K_AENDI:
3259 do_aendi ();
3260 break;
3262 return 1;
3264 else
3266 switch (ptr->value.i)
3268 case K_ALTERNATE:
3269 alternate = 1;
3270 macro_init (1, mri, 0, exp_get_abs);
3271 return 1;
3272 case K_AELSE:
3273 do_aelse ();
3274 return 1;
3275 case K_AENDI:
3276 do_aendi ();
3277 return 1;
3278 case K_ORG:
3279 ERROR ((stderr, _("ORG command not allowed.\n")));
3280 break;
3281 case K_RADIX:
3282 do_radix (line);
3283 return 1;
3284 case K_DB:
3285 do_data (idx, line, 1);
3286 return 1;
3287 case K_DW:
3288 do_data (idx, line, 2);
3289 return 1;
3290 case K_DL:
3291 do_data (idx, line, 4);
3292 return 1;
3293 case K_DATA:
3294 do_data (idx, line, 0);
3295 return 1;
3296 case K_DATAB:
3297 do_datab (idx, line);
3298 return 1;
3299 case K_SDATA:
3300 do_sdata (idx, line, 0);
3301 return 1;
3302 case K_SDATAB:
3303 do_sdatab (idx, line);
3304 return 1;
3305 case K_SDATAC:
3306 do_sdata (idx, line, 'c');
3307 return 1;
3308 case K_SDATAZ:
3309 do_sdata (idx, line, 'z');
3310 return 1;
3311 case K_ASSIGN:
3312 do_assign (0, 0, line);
3313 return 1;
3314 case K_AIF:
3315 do_aif (idx, line);
3316 return 1;
3317 case K_AREPEAT:
3318 do_arepeat (idx, line);
3319 return 1;
3320 case K_AENDW:
3321 do_aendw ();
3322 return 1;
3323 case K_AWHILE:
3324 do_awhile (idx, line);
3325 return 1;
3326 case K_AENDR:
3327 do_aendr ();
3328 return 1;
3329 case K_EQU:
3330 do_assign (1, idx, line);
3331 return 1;
3332 case K_ALIGN:
3333 do_align (idx, line);
3334 return 1;
3335 case K_RES:
3336 do_res (idx, line, 0);
3337 return 1;
3338 case K_SRES:
3339 do_res (idx, line, 's');
3340 return 1;
3341 case K_INCLUDE:
3342 do_include (idx, line);
3343 return 1;
3344 case K_LOCAL:
3345 do_local (idx, line);
3346 return 1;
3347 case K_MACRO:
3348 do_macro (idx, line);
3349 return 1;
3350 case K_ENDM:
3351 do_endm ();
3352 return 1;
3353 case K_SRESC:
3354 do_res (idx, line, 'c');
3355 return 1;
3356 case K_PRINT:
3357 do_print (idx, line);
3358 return 1;
3359 case K_FORM:
3360 do_form (idx, line);
3361 return 1;
3362 case K_HEADING:
3363 do_heading (idx, line);
3364 return 1;
3365 case K_PAGE:
3366 do_page ();
3367 return 1;
3368 case K_GLOBAL:
3369 case K_EXPORT:
3370 do_export (line);
3371 return 1;
3372 case K_IMPORT:
3373 return 1;
3374 case K_SRESZ:
3375 do_res (idx, line, 'z');
3376 return 1;
3377 case K_IGNORED:
3378 return 1;
3379 case K_END:
3380 do_end (line);
3381 return 1;
3382 case K_ASSIGNA:
3383 do_assigna (idx, line);
3384 return 1;
3385 case K_ASSIGNC:
3386 do_assignc (idx, line);
3387 return 1;
3388 case K_EXITM:
3389 do_exitm ();
3390 return 1;
3391 case K_REG:
3392 do_reg (idx, line);
3393 return 1;
3394 case K_IFEQ:
3395 do_if (idx, line, EQ);
3396 return 1;
3397 case K_IFNE:
3398 do_if (idx, line, NE);
3399 return 1;
3400 case K_IFLT:
3401 do_if (idx, line, LT);
3402 return 1;
3403 case K_IFLE:
3404 do_if (idx, line, LE);
3405 return 1;
3406 case K_IFGE:
3407 do_if (idx, line, GE);
3408 return 1;
3409 case K_IFGT:
3410 do_if (idx, line, GT);
3411 return 1;
3412 case K_IFC:
3413 do_ifc (idx, line, 0);
3414 return 1;
3415 case K_IFNC:
3416 do_ifc (idx, line, 1);
3417 return 1;
3418 case K_IRP:
3419 do_irp (idx, line, 0);
3420 return 1;
3421 case K_IRPC:
3422 do_irp (idx, line, 1);
3423 return 1;
3427 return 0;
3432 /* Add a keyword to the hash table. */
3434 static void
3435 add_keyword (name, code)
3436 const char *name;
3437 int code;
3439 sb label;
3440 int j;
3442 sb_new (&label);
3443 sb_add_string (&label, name);
3445 hash_add_to_int_table (&keyword_hash_table, &label, code);
3447 sb_reset (&label);
3448 for (j = 0; name[j]; j++)
3449 sb_add_char (&label, name[j] - 'A' + 'a');
3450 hash_add_to_int_table (&keyword_hash_table, &label, code);
3452 sb_kill (&label);
3455 /* Build the keyword hash table - put each keyword in the table twice,
3456 once upper and once lower case.*/
3458 static void
3459 process_init ()
3461 int i;
3463 for (i = 0; kinfo[i].name; i++)
3464 add_keyword (kinfo[i].name, kinfo[i].code);
3466 if (mri)
3468 for (i = 0; mrikinfo[i].name; i++)
3469 add_keyword (mrikinfo[i].name, mrikinfo[i].code);
3474 static void
3475 do_define (string)
3476 const char *string;
3478 sb label;
3479 int res = 1;
3480 hash_entry *ptr;
3481 sb_new (&label);
3484 while (*string)
3486 if (*string == '=')
3488 sb value;
3489 sb_new (&value);
3490 string++;
3491 while (*string)
3493 sb_add_char (&value, *string);
3494 string++;
3496 exp_get_abs (_("Invalid expression on command line.\n"), 0, &value, &res);
3497 sb_kill (&value);
3498 break;
3500 sb_add_char (&label, *string);
3502 string ++;
3505 ptr = hash_create (&vars, &label);
3506 free_old_entry (ptr);
3507 ptr->type = hash_integer;
3508 ptr->value.i = res;
3509 sb_kill (&label);
3511 char *program_name;
3513 /* The list of long options. */
3514 static struct option long_options[] =
3516 { "alternate", no_argument, 0, 'a' },
3517 { "include", required_argument, 0, 'I' },
3518 { "commentchar", required_argument, 0, 'c' },
3519 { "copysource", no_argument, 0, 's' },
3520 { "debug", no_argument, 0, 'd' },
3521 { "help", no_argument, 0, 'h' },
3522 { "mri", no_argument, 0, 'M' },
3523 { "output", required_argument, 0, 'o' },
3524 { "print", no_argument, 0, 'p' },
3525 { "unreasonable", no_argument, 0, 'u' },
3526 { "version", no_argument, 0, 'v' },
3527 { "define", required_argument, 0, 'd' },
3528 { NULL, no_argument, 0, 0 }
3531 /* Show a usage message and exit. */
3532 static void
3533 show_usage (file, status)
3534 FILE *file;
3535 int status;
3537 fprintf (file, _("\
3538 Usage: %s \n\
3539 [-a] [--alternate] enter alternate macro mode\n\
3540 [-c char] [--commentchar char] change the comment character from !\n\
3541 [-d] [--debug] print some debugging info\n\
3542 [-h] [--help] print this message\n\
3543 [-M] [--mri] enter MRI compatibility mode\n\
3544 [-o out] [--output out] set the output file\n\
3545 [-p] [--print] print line numbers\n"), program_name);
3546 fprintf (file, _("\
3547 [-s] [--copysource] copy source through as comments \n\
3548 [-u] [--unreasonable] allow unreasonable nesting\n\
3549 [-v] [--version] print the program version\n\
3550 [-Dname=value] create preprocessor variable called name, with value\n\
3551 [-Ipath] add to include path list\n\
3552 [in-file]\n"));
3553 if (status == 0)
3554 printf (_("Report bugs to %s\n"), REPORT_BUGS_TO);
3555 exit (status);
3558 /* Display a help message and exit. */
3559 static void
3560 show_help ()
3562 printf (_("%s: Gnu Assembler Macro Preprocessor\n"),
3563 program_name);
3564 show_usage (stdout, 0);
3568 main (argc, argv)
3569 int argc;
3570 char **argv;
3572 int opt;
3573 char *out_name = 0;
3574 sp = include_stack;
3576 ifstack[0].on = 1;
3577 ifi = 0;
3579 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
3580 setlocale (LC_MESSAGES, "");
3581 #endif
3582 bindtextdomain (PACKAGE, LOCALEDIR);
3583 textdomain (PACKAGE);
3585 program_name = argv[0];
3586 xmalloc_set_program_name (program_name);
3588 hash_new_table (101, &keyword_hash_table);
3589 hash_new_table (101, &assign_hash_table);
3590 hash_new_table (101, &vars);
3592 sb_new (&label);
3594 while ((opt = getopt_long (argc, argv, "I:sdhavc:upo:D:M", long_options,
3595 (int *) NULL))
3596 != EOF)
3598 switch (opt)
3600 case 'o':
3601 out_name = optarg;
3602 break;
3603 case 'u':
3604 unreasonable = 1;
3605 break;
3606 case 'I':
3608 include_path *p = (include_path *) xmalloc (sizeof (include_path));
3609 p->next = NULL;
3610 sb_new (&p->path);
3611 sb_add_string (&p->path, optarg);
3612 if (paths_tail)
3613 paths_tail->next = p;
3614 else
3615 paths_head = p;
3616 paths_tail = p;
3618 break;
3619 case 'p':
3620 print_line_number = 1;
3621 break;
3622 case 'c':
3623 comment_char = optarg[0];
3624 break;
3625 case 'a':
3626 alternate = 1;
3627 break;
3628 case 's':
3629 copysource = 1;
3630 break;
3631 case 'd':
3632 stats = 1;
3633 break;
3634 case 'D':
3635 do_define (optarg);
3636 break;
3637 case 'M':
3638 mri = 1;
3639 comment_char = ';';
3640 break;
3641 case 'h':
3642 show_help ();
3643 /*NOTREACHED*/
3644 case 'v':
3645 /* This output is intended to follow the GNU standards document. */
3646 printf (_("GNU assembler pre-processor %s\n"), program_version);
3647 printf (_("Copyright 1996 Free Software Foundation, Inc.\n"));
3648 printf (_("\
3649 This program is free software; you may redistribute it under the terms of\n\
3650 the GNU General Public License. This program has absolutely no warranty.\n"));
3651 exit (0);
3652 /*NOTREACHED*/
3653 case 0:
3654 break;
3655 default:
3656 show_usage (stderr, 1);
3657 /*NOTREACHED*/
3661 process_init ();
3663 macro_init (alternate, mri, 0, exp_get_abs);
3665 if (out_name) {
3666 outfile = fopen (out_name, "w");
3667 if (!outfile)
3669 fprintf (stderr, _("%s: Can't open output file `%s'.\n"),
3670 program_name, out_name);
3671 exit (1);
3674 else {
3675 outfile = stdout;
3678 chartype_init ();
3679 if (!outfile)
3680 outfile = stdout;
3682 /* Process all the input files */
3684 while (optind < argc)
3686 if (new_file (argv[optind]))
3688 process_file ();
3690 else
3692 fprintf (stderr, _("%s: Can't open input file `%s'.\n"),
3693 program_name, argv[optind]);
3694 exit (1);
3696 optind++;
3699 quit ();
3700 return 0;
3703 /* This function is used because an abort in some of the other files
3704 may be compiled into as_abort because they include as.h. */
3706 void
3707 as_abort (file, line, fn)
3708 const char *file, *fn;
3709 int line;
3711 fprintf (stderr, _("Internal error, aborting at %s line %d"), file, line);
3712 if (fn)
3713 fprintf (stderr, " in %s", fn);
3714 fprintf (stderr, _("\nPlease report this bug.\n"));
3715 exit (1);