* dwarf2dbg.h: Use PARAMS in function declarations.
[binutils.git] / gas / gasp.c
blobd8b98b32baf50935a841bbff61b93fc2662be9f6
1 /* gasp.c - Gnu assembler preprocessor main program.
2 Copyright (C) 1994, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
4 Written by Steve and Judy Chamberlain of Cygnus Support,
5 sac@cygnus.com
7 This file is part of GASP, the GNU Assembler Preprocessor.
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.
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.
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. */
26 This program translates the input macros and stuff into a form
27 suitable for gas to consume.
30 gasp [-sdhau] [-c char] [-o <outfile>] <infile>*
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 !
51 #include "config.h"
53 #include <stdio.h>
54 #include <string.h>
55 #include <getopt.h>
56 #include <ctype.h>
58 #ifdef HAVE_STDLIB_H
59 #include <stdlib.h>
60 #endif
62 #ifdef NEED_MALLOC_DECLARATION
63 extern char *malloc ();
64 #endif
66 #include "ansidecl.h"
67 #include "libiberty.h"
68 #include "sb.h"
69 #include "macro.h"
70 #include "asintl.h"
72 char *program_version = "1.2";
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 *));
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;
84 #define MAX_INCLUDES 30 /* Maximum include depth */
85 #define MAX_REASONABLE 1000 /* Maximum number of expansions */
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 */
99 int had_end; /* Seen .END */
101 /* The output stream */
102 FILE *outfile;
104 /* the attributes of each character are stored as a bit pattern
105 chartype, which gives us quick tests. */
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];
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. */
130 #define IFNESTING 100
131 struct
133 int on; /* is the level being output */
134 int hadelse; /* has an aelse been seen */
136 ifstack[IFNESTING];
137 int ifi;
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. */
143 typedef struct
145 char *name;
146 int len;
148 symbol;
150 typedef struct
152 int value; /* constant part */
153 symbol add_symbol; /* name part */
154 symbol sub_symbol; /* name part */
156 exp_t;
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. */
165 /* What the data in a hash_entry means */
166 typedef enum
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;
174 typedef struct hs
176 sb key; /* symbol name */
177 hash_type type; /* symbol meaning */
178 union
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;
188 typedef struct
190 hash_entry **table;
191 int size;
192 } hash_table;
195 /* Structures used to store macros.
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. */
203 /* describe the formal arguments to a macro */
205 typedef struct formal_struct
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 */
213 formal_entry;
215 /* describe the macro. */
217 typedef struct macro_struct
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. */
224 macro_entry;
226 /* how we nest files and expand macros etc.
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.
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.
242 typedef enum
244 include_file, include_repeat, include_while, include_macro
245 } include_type;
247 struct include_stack
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 */
257 include_stack[MAX_INCLUDES];
259 struct include_stack *sp;
260 #define isp (sp - include_stack)
262 /* Include file list */
264 typedef struct include_path
266 struct include_path *next;
267 sb path;
268 } include_path;
270 include_path *paths_head;
271 include_path *paths_tail;
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));
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)
375 /* exit the program and return the right ERROR code. */
376 static void
377 quit ()
379 int exitcode;
380 if (fatals + errors)
381 exitcode = 1;
382 else
383 exitcode = 0;
385 if (stats)
387 int i;
388 for (i = 0; i < sb_max_power_two; i++)
390 fprintf (stderr, "strings size %8d : %d\n", 1<<i, string_count[i]);
393 exit (exitcode);
396 /* hash table maintenance. */
398 /* build a new hash table with size buckets, and fill in the info at ptr. */
400 static void
401 hash_new_table (size, ptr)
402 int size;
403 hash_table *ptr;
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;
413 /* calculate and return the hash value of the sb at key. */
415 static int
416 hash (key)
417 sb *key;
419 int k = 0x1234;
420 int i;
421 char *p = key->ptr;
422 for (i = 0; i < key->len; i++)
424 k ^= (k << 2) ^ *p;
425 p++;
427 return k & 0xf0fff;
430 /* lookup key in hash_table tab, if present, then return it, otherwise
431 build a new one and fill it with hash_integer. */
433 static
434 hash_entry *
435 hash_create (tab, key)
436 hash_table *tab;
437 sb *key;
439 int k = hash (key) % tab->size;
440 hash_entry *p;
441 hash_entry **table = tab->table;
443 p = table[k];
445 while (1)
447 if (!p)
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;
457 if (strncmp (table[k]->key.ptr, key->ptr, key->len) == 0)
459 return p;
461 p = p->next;
465 /* add sb name with key into hash_table tab. if replacing old value
466 and again, then ERROR. */
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;
476 hash_entry *ptr = hash_create (tab, key);
477 if (ptr->type == hash_integer)
479 sb_new (&ptr->value.s);
481 if (ptr->value.s.len)
483 if (!again)
484 ERROR ((stderr, _("redefinition not allowed\n")));
487 ptr->type = hash_string;
488 sb_reset (&ptr->value.s);
490 sb_add_sb (&ptr->value.s, name);
493 /* add integer name to hash_table tab with sb key. */
495 static
496 void
497 hash_add_to_int_table (tab, key, name)
498 hash_table *tab;
499 sb *key;
500 int name;
502 hash_entry *ptr = hash_create (tab, key);
503 ptr->value.i = name;
506 /* lookup sb key in hash_table tab. if found return hash_entry result,
507 else 0. */
509 static
510 hash_entry *
511 hash_lookup (tab, key)
512 hash_table *tab;
513 sb *key;
515 int k = hash (key) % tab->size;
516 hash_entry **table = tab->table;
517 hash_entry *p = table[k];
518 while (p)
520 if (p->key.len == key->len
521 && strncmp (p->key.ptr, key->ptr, key->len) == 0)
522 return p;
523 p = p->next;
525 return 0;
529 /* expressions
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.
536 expression precedence:
538 unary + - ~
547 /* make sure that the exp_t at term is constant, if not the give the op ERROR. */
549 static
550 void
551 checkconst (op, term)
552 int op;
553 exp_t *term;
555 if (term->add_symbol.len
556 || term->sub_symbol.len)
558 ERROR ((stderr, _("the %c operator cannot take non-absolute arguments.\n"), op));
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. */
566 static
568 sb_strtol (idx, string, base, ptr)
569 int idx;
570 sb *string;
571 int base;
572 int *ptr;
574 int value = 0;
575 idx = sb_skip_white (idx, string);
577 while (idx < string->len)
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;
590 if (dig >= base)
591 break;
593 value = value * base + dig;
594 idx++;
596 *ptr = value;
597 return idx;
600 static int
601 level_0 (idx, string, lhs)
602 int idx;
603 sb *string;
604 exp_t *lhs;
606 lhs->add_symbol.len = 0;
607 lhs->add_symbol.name = 0;
609 lhs->sub_symbol.len = 0;
610 lhs->sub_symbol.name = 0;
612 idx = sb_skip_white (idx, string);
614 lhs->value = 0;
616 if (isdigit ((unsigned char) string->ptr[idx]))
618 idx = sb_strtol (idx, string, 10, &lhs->value);
620 else if (ISFIRSTCHAR (string->ptr[idx]))
622 int len = 0;
623 lhs->add_symbol.name = string->ptr + idx;
624 while (idx < string->len && ISNEXTCHAR (string->ptr[idx]))
626 idx++;
627 len++;
629 lhs->add_symbol.len = len;
631 else if (string->ptr[idx] == '"')
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);
639 else
641 ERROR ((stderr, _("can't find primary in expression.\n")));
642 idx++;
644 return sb_skip_white (idx, string);
649 static int
650 level_1 (idx, string, lhs)
651 int idx;
652 sb *string;
653 exp_t *lhs;
655 idx = sb_skip_white (idx, string);
657 switch (string->ptr[idx])
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 '-':
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;
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;
689 return sb_skip_white (idx, string);
692 static int
693 level_2 (idx, string, lhs)
694 int idx;
695 sb *string;
696 exp_t *lhs;
698 exp_t rhs;
700 idx = level_1 (idx, string, lhs);
702 while (idx < string->len && (string->ptr[idx] == '*'
703 || string->ptr[idx] == '/'))
705 char op = string->ptr[idx++];
706 idx = level_1 (idx, string, &rhs);
707 switch (op)
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;
724 return sb_skip_white (idx, string);
728 static int
729 level_3 (idx, string, lhs)
730 int idx;
731 sb *string;
732 exp_t *lhs;
734 exp_t rhs;
736 idx = level_2 (idx, string, lhs);
738 while (idx < string->len
739 && (string->ptr[idx] == '+'
740 || string->ptr[idx] == '-'))
742 char op = string->ptr[idx++];
743 idx = level_2 (idx, string, &rhs);
744 switch (op)
746 case '+':
747 lhs->value += rhs.value;
748 if (lhs->add_symbol.name && rhs.add_symbol.name)
750 ERROR ((stderr, _("can't add two relocatable expressions\n")));
752 /* change nn+symbol to symbol + nn */
753 if (rhs.add_symbol.name)
755 lhs->add_symbol = rhs.add_symbol;
757 break;
758 case '-':
759 lhs->value -= rhs.value;
760 lhs->sub_symbol = rhs.add_symbol;
761 break;
764 return sb_skip_white (idx, string);
767 static int
768 level_4 (idx, string, lhs)
769 int idx;
770 sb *string;
771 exp_t *lhs;
773 exp_t rhs;
775 idx = level_3 (idx, string, lhs);
777 while (idx < string->len &&
778 string->ptr[idx] == '&')
780 char op = string->ptr[idx++];
781 idx = level_3 (idx, string, &rhs);
782 switch (op)
784 case '&':
785 checkconst ('&', lhs);
786 checkconst ('&', &rhs);
787 lhs->value &= rhs.value;
788 break;
791 return sb_skip_white (idx, string);
794 static int
795 level_5 (idx, string, lhs)
796 int idx;
797 sb *string;
798 exp_t *lhs;
800 exp_t rhs;
802 idx = level_4 (idx, string, lhs);
804 while (idx < string->len
805 && (string->ptr[idx] == '|' || string->ptr[idx] == '~'))
807 char op = string->ptr[idx++];
808 idx = level_4 (idx, string, &rhs);
809 switch (op)
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;
823 return sb_skip_white (idx, string);
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.
831 static int
832 exp_parse (idx, string, res)
833 int idx;
834 sb *string;
835 exp_t *res;
837 return level_5 (sb_skip_white (idx, string), string, res);
841 /* turn the expression at exp into text and glue it onto the end of
842 string. */
844 static void
845 exp_string (exp, string)
846 exp_t *exp;
847 sb *string;
849 int np = 0;
850 int ad = 0;
851 sb_reset (string);
853 if (exp->add_symbol.len)
855 sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
856 np = 1;
857 ad = 1;
859 if (exp->value)
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;
869 if (exp->sub_symbol.len)
871 sb_add_char (string, '-');
872 sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
873 np = 0;
874 ad = 1;
877 if (!ad)
878 sb_add_char (string, '0');
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. */
886 static int
887 exp_get_abs (emsg, idx, in, val)
888 const char *emsg;
889 int idx;
890 sb *in;
891 int *val;
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;
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 */
907 #define in_comment ';'
909 #if 0
910 static void
911 strip_comments (out)
912 sb *out;
914 char *s = out->ptr;
915 int i = 0;
916 for (i = 0; i < out->len; i++)
918 if (ISCOMMENTCHAR(s[i]))
920 out->len = i;
921 return;
925 #endif
927 /* push back character ch so that it can be read again. */
929 static void
930 unget (ch)
931 int ch;
933 if (ch == '\n')
935 sp->linecount--;
937 if (sp->pushback_index)
938 sp->pushback_index--;
939 else
940 sb_add_char (&sp->pushback, ch);
943 /* push the sb ptr onto the include stack, with the given name, type and index. */
945 static
946 void
947 include_buf (name, ptr, type, index)
948 sb *name;
949 sb *ptr;
950 include_type type;
951 int index;
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);
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;
974 struct include_stack *p = include_stack + 1;
976 while (p <= sp)
978 fprintf (file, "%s:%d ", sb_name (&p->name), p->linecount - 1);
979 p++;
983 /* used in listings, print the line number onto file. */
984 static void
985 include_print_line (file)
986 FILE *file;
988 int n;
989 struct include_stack *p = include_stack + 1;
991 n = fprintf (file, "%4d", p->linecount);
992 p++;
993 while (p <= sp)
995 n += fprintf (file, ".%d", p->linecount);
996 p++;
998 while (n < 8 * 3)
1000 fprintf (file, " ");
1001 n++;
1006 /* read a line from the top of the include stack into sb in. */
1008 static int
1009 get_line (in)
1010 sb *in;
1012 int online = 0;
1013 int more = 1;
1015 if (copysource)
1017 putc (comment_char, outfile);
1018 if (print_line_number)
1019 include_print_line (outfile);
1022 while (1)
1024 int ch = get ();
1026 while (ch == '\r')
1027 ch = get ();
1029 if (ch == EOF)
1031 if (online)
1033 WARNING ((stderr, _("End of file not at start of line.\n")));
1034 if (copysource)
1035 putc ('\n', outfile);
1036 ch = '\n';
1038 else
1039 more = 0;
1040 break;
1043 if (copysource)
1045 putc (ch, outfile);
1048 if (ch == '\n')
1050 ch = get ();
1051 online = 0;
1052 if (ch == '+')
1054 /* continued line */
1055 if (copysource)
1057 putc (comment_char, outfile);
1058 putc ('+', outfile);
1060 ch = get ();
1062 else
1064 if (ch != EOF)
1065 unget (ch);
1066 break;
1069 else
1071 sb_add_char (in, ch);
1073 online++;
1076 return more;
1079 /* find a label from sb in and put it in out. */
1081 static int
1082 grab_label (in, out)
1083 sb *in;
1084 sb *out;
1086 int i = 0;
1087 sb_reset (out);
1088 if (ISFIRSTCHAR (in->ptr[i]) || in->ptr[i] == '\\')
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)
1097 sb_add_char (out, in->ptr[i]);
1098 i++;
1101 return i;
1104 /* find all strange base stuff and turn into decimal. also
1105 find all the other numbers and convert them from the default radix */
1107 static void
1108 change_base (idx, in, out)
1109 int idx;
1110 sb *in;
1111 sb *out;
1113 char buffer[20];
1115 while (idx < in->len)
1117 if (in->ptr[idx] == '\\'
1118 && idx + 1 < in->len
1119 && in->ptr[idx + 1] == '(')
1121 idx += 2;
1122 while (idx < in->len
1123 && in->ptr[idx] != ')')
1125 sb_add_char (out, in->ptr[idx]);
1126 idx++;
1128 if (idx < in->len)
1129 idx++;
1131 else if (idx < in->len - 1 && in->ptr[idx + 1] == '\'' && ! mri)
1133 int base;
1134 int value;
1135 switch (in->ptr[idx])
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;
1159 idx = sb_strtol (idx + 2, in, base, &value);
1160 sprintf (buffer, "%d", value);
1161 sb_add_string (out, buffer);
1163 else if (ISFIRSTCHAR (in->ptr[idx]))
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]))
1170 sb_add_char (out, in->ptr[idx]);
1171 idx++;
1174 else if (isdigit ((unsigned char) in->ptr[idx]))
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);
1183 /* skip all undigsested letters */
1184 while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
1186 sb_add_char (out, in->ptr[idx]);
1187 idx++;
1190 else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
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)
1198 sb_add_char (out, in->ptr[idx]);
1199 idx++;
1202 else
1204 /* nothing special, just pass it through */
1205 sb_add_char (out, in->ptr[idx]);
1206 idx++;
1212 /* .end */
1213 static void
1214 do_end (in)
1215 sb *in;
1217 had_end = 1;
1218 if (mri)
1219 fprintf (outfile, "%s\n", sb_name (in));
1222 /* .assign */
1224 static void
1225 do_assign (again, idx, in)
1226 int again;
1227 int idx;
1228 sb *in;
1230 /* stick label in symbol table with following value */
1231 exp_t e;
1232 sb acc;
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);
1242 /* .radix [b|q|d|h] */
1244 static
1245 void
1246 do_radix (ptr)
1247 sb *ptr;
1249 int idx = sb_skip_white (0, ptr);
1250 switch (ptr->ptr[idx])
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));
1274 /* Parse off a .b, .w or .l */
1276 static int
1277 get_opsize (idx, in, size)
1278 int idx;
1279 sb *in;
1280 int *size;
1282 *size = 4;
1283 if (in->ptr[idx] == '.')
1285 idx++;
1287 switch (in->ptr[idx])
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;
1308 idx++;
1310 return idx;
1313 static
1314 int eol(idx, line)
1315 int idx;
1316 sb *line;
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;
1327 /* .data [.b|.w|.l] <data>*
1328 or d[bwl] <data>* */
1330 static void
1331 do_data (idx, in, size)
1332 int idx;
1333 sb *in;
1334 int size;
1336 int opsize = 4;
1337 char *opname = ".yikes!";
1338 sb acc;
1339 sb_new (&acc);
1341 if (!size)
1343 idx = get_opsize (idx, in, &opsize);
1345 else {
1346 opsize = size;
1348 switch (opsize)
1350 case 4:
1351 opname = ".long";
1352 break;
1353 case 2:
1354 opname = ".short";
1355 break;
1356 case 1:
1357 opname = ".byte";
1358 break;
1362 fprintf (outfile, "%s\t", opname);
1364 idx = sb_skip_white (idx, in);
1366 if (alternate
1367 && idx < in->len
1368 && in->ptr[idx] == '"')
1370 int i;
1371 idx = getstring (idx, in, &acc);
1372 for (i = 0; i < acc.len; i++)
1374 if (i)
1375 fprintf(outfile,",");
1376 fprintf (outfile, "%d", acc.ptr[i]);
1379 else
1381 while (!eol (idx, in))
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] == ',')
1390 fprintf (outfile, ",");
1391 idx++;
1395 sb_kill (&acc);
1396 sb_print_at (outfile, idx, in);
1397 fprintf (outfile, "\n");
1400 /* .datab [.b|.w|.l] <repeat>,<fill> */
1402 static void
1403 do_datab (idx, in)
1404 int idx;
1405 sb *in;
1407 int opsize;
1408 int repeat;
1409 int fill;
1411 idx = get_opsize (idx, in, &opsize);
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);
1417 fprintf (outfile, ".fill\t%d,%d,%d\n", repeat, opsize, fill);
1420 /* .align <size> */
1422 static void
1423 do_align (idx, in)
1424 int idx;
1425 sb *in;
1427 int al, have_fill, fill;
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))
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;
1441 if (al != 1
1442 && al != 2
1443 && al != 4)
1444 WARNING ((stderr, _("alignment must be one of 1, 2 or 4.\n")));
1446 fprintf (outfile, ".align %d", al);
1447 if (have_fill)
1448 fprintf (outfile, ",%d", fill);
1449 fprintf (outfile, "\n");
1452 /* .res[.b|.w|.l] <size> */
1454 static void
1455 do_res (idx, in, type)
1456 int idx;
1457 sb *in;
1458 int type;
1460 int size = 4;
1461 int count = 0;
1463 idx = get_opsize (idx, in, &size);
1464 while (!eol(idx, in))
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);
1471 if (type == 'c' || type == 'z')
1472 count++;
1474 fprintf (outfile, ".space %d\n", count * size);
1479 /* .export */
1481 static void
1482 do_export (in)
1483 sb *in;
1485 fprintf (outfile, ".global %s\n", sb_name (in));
1488 /* .print [list] [nolist] */
1490 static void
1491 do_print (idx, in)
1492 int idx;
1493 sb *in;
1495 idx = sb_skip_white (idx, in);
1496 while (idx < in->len)
1498 if (strncasecmp (in->ptr + idx, "LIST", 4) == 0)
1500 fprintf (outfile, ".list\n");
1501 idx += 4;
1503 else if (strncasecmp (in->ptr + idx, "NOLIST", 6) == 0)
1505 fprintf (outfile, ".nolist\n");
1506 idx += 6;
1508 idx++;
1512 /* .head */
1513 static void
1514 do_heading (idx, in)
1515 int idx;
1516 sb *in;
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);
1525 /* .page */
1527 static void
1528 do_page ()
1530 fprintf (outfile, ".eject\n");
1533 /* .form [lin=<value>] [col=<value>] */
1534 static void
1535 do_form (idx, in)
1536 int idx;
1537 sb *in;
1539 int lines = 60;
1540 int columns = 132;
1541 idx = sb_skip_white (idx, in);
1543 while (idx < in->len)
1546 if (strncasecmp (in->ptr + idx, "LIN=", 4) == 0)
1548 idx += 4;
1549 idx = exp_get_abs (_("form LIN= needs absolute expresssion.\n"), idx, in, &lines);
1552 if (strncasecmp (in->ptr + idx, _("COL="), 4) == 0)
1554 idx += 4;
1555 idx = exp_get_abs (_("form COL= needs absolute expresssion.\n"), idx, in, &columns);
1558 idx++;
1560 fprintf (outfile, ".psize %d,%d\n", lines, columns);
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
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;
1580 sb_reset (out);
1581 idx = sb_skip_white (idx, in);
1583 if (idx < in->len)
1585 if (in->len > 2 && in->ptr[idx+1] == '\'' && ISBASE (in->ptr[idx]))
1587 while (!ISSEP (in->ptr[idx]))
1588 sb_add_char (out, in->ptr[idx++]);
1590 else if (in->ptr[idx] == '%'
1591 && alternate
1592 && expand)
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,
1600 &val);
1601 sprintf(buf, "%d", val);
1602 sb_add_string (out, buf);
1604 else if (in->ptr[idx] == '"'
1605 || in->ptr[idx] == '<'
1606 || (alternate && in->ptr[idx] == '\''))
1608 if (alternate && expand)
1610 /* Keep the quotes */
1611 sb_add_char (out, '\"');
1613 idx = getstring (idx, in, out);
1614 sb_add_char (out, '\"');
1617 else {
1618 idx = getstring (idx, in, out);
1621 else
1623 while (idx < in->len
1624 && (in->ptr[idx] == '"'
1625 || in->ptr[idx] == '\''
1626 || pretend_quoted
1627 || !ISSEP (in->ptr[idx])))
1629 if (in->ptr[idx] == '"'
1630 || in->ptr[idx] == '\'')
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;
1640 sb_add_char (out, in->ptr[idx++]);
1645 return idx;
1649 /* skip along sb in starting at idx, suck off whitespace a ( and more
1650 whitespace. return the idx of the next char */
1652 static int
1653 skip_openp (idx, in)
1654 int idx;
1655 sb *in;
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;
1664 /* skip along sb in starting at idx, suck off whitespace a ) and more
1665 whitespace. return the idx of the next char */
1667 static int
1668 skip_closep (idx, in)
1669 int idx;
1670 sb *in;
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;
1679 /* .len */
1681 static int
1682 dolen (idx, in, out)
1683 int idx;
1684 sb *in;
1685 sb *out;
1688 sb stringout;
1689 char buffer[10];
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);
1698 sb_kill (&stringout);
1699 return idx;
1703 /* .instr */
1705 static
1707 doinstr (idx, in, out)
1708 int idx;
1709 sb *in;
1710 sb *out;
1712 sb string;
1713 sb search;
1714 int i;
1715 int start;
1716 int res;
1717 char buffer[10];
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]))
1728 idx = exp_get_abs (_(".instr needs absolute expresson.\n"), idx, in, &start);
1730 else
1732 start = 0;
1734 idx = skip_closep (idx, in);
1735 res = -1;
1736 for (i = start; i < string.len; i++)
1738 if (strncmp (string.ptr + i, search.ptr, search.len) == 0)
1740 res = i;
1741 break;
1744 sprintf (buffer, "%d", res);
1745 sb_add_string (out, buffer);
1746 sb_kill (&string);
1747 sb_kill (&search);
1748 return idx;
1752 static int
1753 dosubstr (idx, in, out)
1754 int idx;
1755 sb *in;
1756 sb *out;
1758 sb string;
1759 int pos;
1760 int len;
1761 sb_new (&string);
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);
1772 if (len < 0 || pos < 0 ||
1773 pos > string.len
1774 || pos + len > string.len)
1776 sb_add_string (out, " ");
1778 else
1780 sb_add_char (out, '"');
1781 while (len > 0)
1783 sb_add_char (out, string.ptr[pos++]);
1784 len--;
1786 sb_add_char (out, '"');
1788 sb_kill(&string);
1789 return idx;
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;
1799 while (idx < in->len)
1801 hash_entry *ptr;
1802 if (in->ptr[idx] == '\\'
1803 && idx + 1 < in->len
1804 && in->ptr[idx + 1] == '(')
1808 sb_add_char (buf, in->ptr[idx]);
1809 idx++;
1811 while (idx < in->len && in->ptr[idx - 1] != ')');
1813 else if (in->ptr[idx] == '\\'
1814 && idx + 1 < in->len
1815 && in->ptr[idx + 1] == '&')
1817 idx = condass_lookup_name (in, idx + 2, buf, 1);
1819 else if (in->ptr[idx] == '\\'
1820 && idx + 1 < in->len
1821 && in->ptr[idx + 1] == '$')
1823 idx = condass_lookup_name (in, idx + 2, buf, 0);
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]))
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++;
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)
1862 /* Found a definition for it */
1863 sb_add_sb (buf, &ptr->value.s);
1865 else
1867 /* No definition, just copy the word */
1868 sb_add_sb (buf, &acc);
1870 sb_kill (&acc);
1871 idx = cur;
1873 else
1875 sb_add_char (buf, in->ptr[idx++]);
1880 static int
1881 get_and_process (idx, in, out)
1882 int idx;
1883 sb *in;
1884 sb *out;
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;
1894 static
1895 void
1896 process_file ()
1898 sb line;
1899 sb t1, t2;
1900 sb acc;
1901 sb label_in;
1902 int more;
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)
1913 /* Find any label and pseudo op that we're intested in */
1914 int l;
1915 if (line.len == 0)
1917 if (condass_on ())
1918 fprintf (outfile, "\n");
1920 else if (mri
1921 && (line.ptr[0] == '*'
1922 || line.ptr[0] == '!'))
1924 /* MRI line comment. */
1925 fprintf (outfile, sb_name (&line));
1927 else
1929 l = grab_label (&line, &label_in);
1930 sb_reset (&label);
1932 if (line.ptr[l] == ':')
1933 l++;
1934 while (ISWHITE (line.ptr[l]) && l < line.len)
1935 l++;
1937 if (label_in.len)
1939 int do_assigns;
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))
1946 int lx = l;
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;
1962 if (do_assigns)
1963 process_assigns (0, &label_in, &label);
1964 else
1965 sb_add_sb (&label, &label_in);
1968 if (l < line.len)
1970 if (process_pseudo_op (l, &line, &acc))
1976 else if (condass_on ())
1978 if (macro_op (l, &line))
1983 else
1986 if (label.len)
1988 fprintf (outfile, "%s:\t", sb_name (&label));
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));
2001 else {
2002 /* Only a label on this line */
2003 if (label.len && condass_on())
2005 fprintf (outfile, "%s:\n", sb_name (&label));
2010 if (had_end)
2011 break;
2012 sb_reset (&line);
2013 more = get_line (&line);
2016 if (!had_end && !mri)
2017 WARNING ((stderr, _("END missing from end of file.\n")));
2024 static void
2025 free_old_entry (ptr)
2026 hash_entry *ptr;
2028 if (ptr)
2030 if (ptr->type == hash_string)
2031 sb_kill(&ptr->value.s);
2035 /* name: .ASSIGNA <value> */
2037 static void
2038 do_assigna (idx, in)
2039 int idx;
2040 sb *in;
2042 sb tmp;
2043 int val;
2044 sb_new (&tmp);
2046 process_assigns (idx, in, &tmp);
2047 idx = exp_get_abs (_(".ASSIGNA needs constant expression argument.\n"), 0, &tmp, &val);
2049 if (!label.len)
2051 ERROR ((stderr, _(".ASSIGNA without label.\n")));
2053 else
2055 hash_entry *ptr = hash_create (&vars, &label);
2056 free_old_entry (ptr);
2057 ptr->type = hash_integer;
2058 ptr->value.i = val;
2060 sb_kill (&tmp);
2063 /* name: .ASSIGNC <string> */
2065 static void
2066 do_assignc (idx, in)
2067 int idx;
2068 sb *in;
2070 sb acc;
2071 sb_new (&acc);
2072 idx = getstring (idx, in, &acc);
2074 if (!label.len)
2076 ERROR ((stderr, _(".ASSIGNS without label.\n")));
2078 else
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);
2086 sb_kill (&acc);
2090 /* name: .REG (reg) */
2092 static void
2093 do_reg (idx, in)
2094 int idx;
2095 sb *in;
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] != ')'))
2109 sb_add_char (&what, in->ptr[idx]);
2110 idx++;
2112 hash_add_to_string_table (&assign_hash_table, &label, &what, 1);
2113 sb_kill (&what);
2117 static int
2118 condass_lookup_name (inbuf, idx, out, warn)
2119 sb *inbuf;
2120 int idx;
2121 sb *out;
2122 int warn;
2124 hash_entry *ptr;
2125 sb condass_acc;
2126 sb_new (&condass_acc);
2128 while (idx < inbuf->len
2129 && ISNEXTCHAR (inbuf->ptr[idx]))
2131 sb_add_char (&condass_acc, inbuf->ptr[idx++]);
2134 if (inbuf->ptr[idx] == '\'')
2135 idx++;
2136 ptr = hash_lookup (&vars, &condass_acc);
2139 if (!ptr)
2141 if (warn)
2143 WARNING ((stderr, _("Can't find preprocessor variable %s.\n"), sb_name (&condass_acc)));
2145 else
2147 sb_add_string (out, "0");
2150 else
2152 if (ptr->type == hash_integer)
2154 char buffer[30];
2155 sprintf (buffer, "%d", ptr->value.i);
2156 sb_add_string (out, buffer);
2158 else
2160 sb_add_sb (out, &ptr->value.s);
2163 sb_kill (&condass_acc);
2164 return idx;
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
2175 static int
2176 whatcond (idx, in, val)
2177 int idx;
2178 sb *in;
2179 int *val;
2181 int cond;
2183 idx = sb_skip_white (idx, in);
2184 cond = NEVER;
2185 if (idx + 1 < in->len)
2187 char *p;
2188 char a, b;
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;
2206 if (cond == NEVER)
2208 ERROR ((stderr, _("Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n")));
2209 cond = NEVER;
2211 idx = sb_skip_white (idx + 2, in);
2212 *val = cond;
2213 return idx;
2216 static int
2217 istrue (idx, in)
2218 int idx;
2219 sb *in;
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);
2230 if (in->ptr[idx] == '"')
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);
2240 if (cond != EQ && cond != NE)
2242 ERROR ((stderr, _("Comparison operator for strings must be EQ or NE\n")));
2243 res = 0;
2245 else
2246 res = (cond != EQ) ^ same;
2248 else
2249 /* This is a numeric expression */
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] == '"')
2259 WARNING ((stderr, _("String compared against expression.\n")));
2260 res = 0;
2262 else
2264 idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"), idx, in, &valb);
2265 switch (cond)
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;
2295 sb_kill (&acc_a);
2296 sb_kill (&cond);
2297 sb_kill (&acc_b);
2298 return res;
2301 /* .AIF */
2302 static void
2303 do_aif (idx, in)
2304 int idx;
2305 sb *in;
2307 if (ifi >= IFNESTING)
2309 FATAL ((stderr, _("AIF nesting unreasonable.\n")));
2311 ifi++;
2312 ifstack[ifi].on = ifstack[ifi-1].on ? istrue (idx, in) : 0;
2313 ifstack[ifi].hadelse = 0;
2317 /* .AELSE */
2318 static void
2319 do_aelse ()
2321 ifstack[ifi].on = ifstack[ifi-1].on ? !ifstack[ifi].on : 0;
2322 if (ifstack[ifi].hadelse)
2324 ERROR ((stderr, _("Multiple AELSEs in AIF.\n")));
2326 ifstack[ifi].hadelse = 1;
2330 /* .AENDI */
2331 static void
2332 do_aendi ()
2334 if (ifi != 0)
2336 ifi--;
2338 else
2340 ERROR ((stderr, _("AENDI without AIF.\n")));
2344 static int
2345 condass_on ()
2347 return ifstack[ifi].on;
2350 /* MRI IFEQ, IFNE, IFLT, IFLE, IFGE, IFGT. */
2352 static void
2353 do_if (idx, in, cond)
2354 int idx;
2355 sb *in;
2356 int cond;
2358 int val;
2359 int res;
2361 if (ifi >= IFNESTING)
2363 FATAL ((stderr, _("IF nesting unreasonable.\n")));
2366 idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"),
2367 idx, in, &val);
2368 switch (cond)
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;
2379 ifi++;
2380 ifstack[ifi].on = ifstack[ifi-1].on ? res: 0;
2381 ifstack[ifi].hadelse = 0;
2384 /* Get a string for the MRI IFC or IFNC pseudo-ops. */
2386 static int
2387 get_mri_string (idx, in, val, terminator)
2388 int idx;
2389 sb *in;
2390 sb *val;
2391 int terminator;
2393 idx = sb_skip_white (idx, in);
2395 if (idx < in->len
2396 && in->ptr[idx] == '\'')
2398 sb_add_char (val, '\'');
2399 for (++idx; idx < in->len; ++idx)
2401 sb_add_char (val, in->ptr[idx]);
2402 if (in->ptr[idx] == '\'')
2404 ++idx;
2405 if (idx >= in->len
2406 || in->ptr[idx] != '\'')
2407 break;
2410 idx = sb_skip_white (idx, in);
2412 else
2414 int i;
2416 while (idx < in->len
2417 && in->ptr[idx] != terminator)
2419 sb_add_char (val, in->ptr[idx]);
2420 ++idx;
2422 i = val->len - 1;
2423 while (i >= 0 && ISWHITE (val->ptr[i]))
2424 --i;
2425 val->len = i + 1;
2428 return idx;
2431 /* MRI IFC, IFNC. */
2433 static void
2434 do_ifc (idx, in, ifnc)
2435 int idx;
2436 sb *in;
2437 int ifnc;
2439 sb first;
2440 sb second;
2441 int res;
2443 if (ifi >= IFNESTING)
2445 FATAL ((stderr, _("IF nesting unreasonable.\n")));
2448 sb_new (&first);
2449 sb_new (&second);
2451 idx = get_mri_string (idx, in, &first, ',');
2453 if (idx >= in->len || in->ptr[idx] != ',')
2455 ERROR ((stderr, _("Bad format for IF or IFNC.\n")));
2456 return;
2459 idx = get_mri_string (idx + 1, in, &second, ';');
2461 res = (first.len == second.len
2462 && strncmp (first.ptr, second.ptr, first.len) == 0);
2463 res ^= ifnc;
2465 ifi++;
2466 ifstack[ifi].on = ifstack[ifi-1].on ? res : 0;
2467 ifstack[ifi].hadelse = 0;
2470 /* .ENDR */
2471 static void
2472 do_aendr ()
2474 if (!mri)
2475 ERROR ((stderr, _("AENDR without a AREPEAT.\n")));
2476 else
2477 ERROR ((stderr, _("ENDR without a REPT.\n")));
2480 /* .AWHILE */
2482 static
2483 void
2484 do_awhile (idx, in)
2485 int idx;
2486 sb *in;
2488 int line = linecount ();
2489 sb exp;
2490 sb sub;
2491 int doit;
2493 sb_new (&sub);
2494 sb_new (&exp);
2496 process_assigns (idx, in, &exp);
2497 doit = istrue (0, &exp);
2499 if (! buffer_and_nest ("AWHILE", "AENDW", &sub, get_line))
2500 FATAL ((stderr, _("AWHILE without a AENDW at %d.\n"), line - 1));
2502 /* Turn
2503 .AWHILE exp
2505 .AENDW
2506 into
2508 .AWHILE exp
2510 .ENDW
2513 if (doit)
2515 int index = include_next_index ();
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);
2528 sb_kill (&exp);
2529 sb_kill (&sub);
2533 /* .AENDW */
2535 static void
2536 do_aendw ()
2538 ERROR ((stderr, _("AENDW without a AENDW.\n")));
2542 /* .EXITM
2544 Pop things off the include stack until the type and index changes */
2546 static void
2547 do_exitm ()
2549 include_type type = sp->type;
2550 if (type == include_repeat
2551 || type == include_while
2552 || type == include_macro)
2554 int index = sp->index;
2555 include_pop ();
2556 while (sp->index == index
2557 && sp->type == type)
2559 include_pop ();
2564 /* .AREPEAT */
2566 static void
2567 do_arepeat (idx, in)
2568 int idx;
2569 sb *in;
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];
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)
2592 /* Push back the text following the repeat, and another repeat block
2594 .AREPEAT 20
2596 .AENDR
2597 gets turned into
2599 .AREPEAT 19
2601 .AENDR
2603 int index = include_next_index ();
2604 sb_add_sb (&copy, &sub);
2605 if (rc > 1)
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");
2619 include_buf (&exp, &copy, include_repeat, index);
2621 sb_kill (&exp);
2622 sb_kill (&sub);
2623 sb_kill (&copy);
2626 /* .ENDM */
2628 static void
2629 do_endm ()
2631 ERROR ((stderr, _(".ENDM without a matching .MACRO.\n")));
2634 /* MRI IRP pseudo-op. */
2636 static void
2637 do_irp (idx, in, irpc)
2638 int idx;
2639 sb *in;
2640 int irpc;
2642 const char *err;
2643 sb out;
2645 sb_new (&out);
2647 err = expand_irp (irpc, idx, in, &out, get_line, comment_char);
2648 if (err != NULL)
2649 ERROR ((stderr, "%s\n", err));
2651 fprintf (outfile, "%s", sb_terminate (&out));
2653 sb_kill (&out);
2656 /* MACRO PROCESSING */
2658 /* Parse off LOCAL n1, n2,... Invent a label name for it */
2659 static
2660 void
2661 do_local (idx, line)
2662 int idx;
2663 sb *line;
2665 ERROR ((stderr, _("LOCAL outside of MACRO")));
2668 static void
2669 do_macro (idx, in)
2670 int idx;
2671 sb *in;
2673 const char *err;
2674 int line = linecount ();
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));
2681 static int
2682 macro_op (idx, in)
2683 int idx;
2684 sb *in;
2686 const char *err;
2687 sb out;
2688 sb name;
2690 if (! macro_defined)
2691 return 0;
2693 sb_terminate (in);
2694 if (! check_macro (in->ptr + idx, &out, comment_char, &err))
2695 return 0;
2697 if (err != NULL)
2698 ERROR ((stderr, "%s\n", err));
2700 sb_new (&name);
2701 sb_add_string (&name, _("macro expansion"));
2703 include_buf (&name, &out, include_macro, include_next_index ());
2705 sb_kill (&name);
2706 sb_kill (&out);
2708 return 1;
2711 /* STRING HANDLING */
2713 static int
2714 getstring (idx, in, acc)
2715 int idx;
2716 sb *in;
2717 sb *acc;
2719 idx = sb_skip_white (idx, in);
2721 while (idx < in->len
2722 && (in->ptr[idx] == '"'
2723 || in->ptr[idx] == '<'
2724 || (in->ptr[idx] == '\'' && alternate)))
2726 if (in->ptr[idx] == '<')
2728 if (alternate || mri)
2730 int nest = 0;
2731 idx++;
2732 while ((in->ptr[idx] != '>' || nest)
2733 && idx < in->len)
2735 if (in->ptr[idx] == '!')
2737 idx++ ;
2738 sb_add_char (acc, in->ptr[idx++]);
2740 else {
2741 if (in->ptr[idx] == '>')
2742 nest--;
2743 if (in->ptr[idx] == '<')
2744 nest++;
2745 sb_add_char (acc, in->ptr[idx++]);
2748 idx++;
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);
2757 if (in->ptr[idx] != '>')
2758 ERROR ((stderr, _("Missing > for character code.\n")));
2759 idx++;
2762 else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
2764 char tchar = in->ptr[idx];
2765 idx++;
2766 while (idx < in->len)
2768 if (alternate && in->ptr[idx] == '!')
2770 idx++ ;
2771 sb_add_char (acc, in->ptr[idx++]);
2773 else {
2774 if (in->ptr[idx] == tchar)
2776 idx++;
2777 if (idx >= in->len || in->ptr[idx] != tchar)
2778 break;
2780 sb_add_char (acc, in->ptr[idx]);
2781 idx++;
2787 return idx;
2790 /* .SDATA[C|Z] <string> */
2792 static
2793 void
2794 do_sdata (idx, in, type)
2795 int idx;
2796 sb *in;
2797 int type;
2799 int nc = 0;
2800 int pidx = -1;
2801 sb acc;
2802 sb_new (&acc);
2803 fprintf (outfile, ".byte\t");
2805 while (!eol (idx, in))
2807 int i;
2808 sb_reset (&acc);
2809 idx = sb_skip_white (idx, in);
2810 while (!eol (idx, in))
2812 pidx = idx = get_any_string (idx, in, &acc, 0, 1);
2813 if (type == 'c')
2815 if (acc.len > 255)
2817 ERROR ((stderr, _("string for SDATAC longer than 255 characters (%d).\n"), acc.len));
2819 fprintf (outfile, "%d", acc.len);
2820 nc = 1;
2823 for (i = 0; i < acc.len; i++)
2825 if (nc)
2827 fprintf (outfile, ",");
2829 fprintf (outfile, "%d", acc.ptr[i]);
2830 nc = 1;
2833 if (type == 'z')
2835 if (nc)
2836 fprintf (outfile, ",");
2837 fprintf (outfile, "0");
2839 idx = sb_skip_comma (idx, in);
2840 if (idx == pidx) break;
2842 if (!alternate && in->ptr[idx] != ',' && idx != in->len)
2844 fprintf (outfile, "\n");
2845 ERROR ((stderr, _("illegal character in SDATA line (0x%x).\n"), in->ptr[idx]));
2846 break;
2848 idx++;
2850 sb_kill (&acc);
2851 fprintf (outfile, "\n");
2854 /* .SDATAB <count> <string> */
2856 static void
2857 do_sdatab (idx, in)
2858 int idx;
2859 sb *in;
2861 int repeat;
2862 int i;
2863 sb acc;
2864 sb_new (&acc);
2866 idx = exp_get_abs (_("Must have absolute SDATAB repeat count.\n"), idx, in, &repeat);
2867 if (repeat <= 0)
2869 ERROR ((stderr, _("Must have positive SDATAB repeat count (%d).\n"), repeat));
2870 repeat = 1;
2873 idx = sb_skip_comma (idx, in);
2874 idx = getstring (idx, in, &acc);
2876 for (i = 0; i < repeat; i++)
2878 if (i)
2879 fprintf (outfile, "\t");
2880 fprintf (outfile, ".byte\t");
2881 sb_print (outfile, &acc);
2882 fprintf (outfile, "\n");
2884 sb_kill (&acc);
2888 static int
2889 new_file (name)
2890 const char *name;
2892 FILE *newone = fopen (name, "r");
2893 if (!newone)
2894 return 0;
2896 if (isp == MAX_INCLUDES)
2897 FATAL ((stderr, _("Unreasonable include depth (%ld).\n"), (long) isp));
2899 sp++;
2900 sp->handle = newone;
2902 sb_new (&sp->name);
2903 sb_add_string (&sp->name, name);
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;
2913 static void
2914 do_include (idx, in)
2915 int idx;
2916 sb *in;
2918 sb t;
2919 sb cat;
2920 include_path *includes;
2922 sb_new (&t);
2923 sb_new (&cat);
2925 if (! mri)
2926 idx = getstring (idx, in, &t);
2927 else
2929 idx = sb_skip_white (idx, in);
2930 while (idx < in->len && ! ISWHITE (in->ptr[idx]))
2932 sb_add_char (&t, in->ptr[idx]);
2933 ++idx;
2937 for (includes = paths_head; includes; includes = includes->next)
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)))
2945 break;
2948 if (!includes)
2950 if (! new_file (sb_name (&t)))
2951 FATAL ((stderr, _("Can't open include file `%s'.\n"), sb_name (&t)));
2953 sb_kill (&cat);
2954 sb_kill (&t);
2957 static void
2958 include_pop ()
2960 if (sp != include_stack)
2962 if (sp->handle)
2963 fclose (sp->handle);
2964 sp--;
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. */
2972 static int
2973 get ()
2975 int r;
2977 if (sp->pushback.len != sp->pushback_index)
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)
2983 sp->pushback.len = 0;
2984 sp->pushback_index = 0;
2987 else if (sp->handle)
2989 r = getc (sp->handle);
2991 else
2992 r = EOF;
2994 if (r == EOF && isp)
2996 include_pop ();
2997 r = get ();
2998 while (r == EOF && isp)
3000 include_pop ();
3001 r = get ();
3003 return r;
3005 if (r == '\n')
3007 sp->linecount++;
3010 return r;
3013 static int
3014 linecount ()
3016 return sp->linecount;
3019 static int
3020 include_next_index ()
3022 static int index;
3023 if (!unreasonable
3024 && index > MAX_REASONABLE)
3025 FATAL ((stderr, _("Unreasonable expansion (-u turns off check).\n")));
3026 return ++index;
3030 /* Initialize the chartype vector. */
3032 static void
3033 chartype_init ()
3035 int x;
3036 for (x = 0; x < 256; x++)
3038 if (isalpha (x) || x == '_' || x == '$')
3039 chartype[x] |= FIRSTBIT;
3041 if (mri && x == '.')
3042 chartype[x] |= FIRSTBIT;
3044 if (isdigit (x) || isalpha (x) || x == '_' || x == '$')
3045 chartype[x] |= NEXTBIT;
3047 if (x == ' ' || x == '\t' || x == ',' || x == '"' || x == ';'
3048 || x == '"' || x == '<' || x == '>' || x == ')' || x == '(')
3049 chartype[x] |= SEPBIT;
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;
3057 if (x == ' ' || x == '\t')
3058 chartype[x] |= WHITEBIT;
3060 if (x == comment_char)
3061 chartype[x] |= COMMENTBIT;
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 */
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)
3127 struct keyword
3129 char *name;
3130 int code;
3131 int extra;
3134 static struct keyword kinfo[] =
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 }
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. */
3186 static struct keyword mrikinfo[] =
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 }
3206 /* Look for a pseudo op on the line. If one's there then call
3207 its handler. */
3209 static int
3210 process_pseudo_op (idx, line, acc)
3211 int idx;
3212 sb *line;
3213 sb *acc;
3215 int oidx = idx;
3217 if (line->ptr[idx] == '.' || alternate || mri)
3219 /* Scan forward and find pseudo name */
3220 char *in;
3221 hash_entry *ptr;
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);
3232 while (idx < line->len && *e && ISFIRSTCHAR (*e))
3234 sb_add_char (acc, *e);
3235 e++;
3236 idx++;
3239 ptr = hash_lookup (&keyword_hash_table, acc);
3241 if (!ptr)
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;
3250 if (ptr->value.i & LAB)
3251 { /* output the label */
3252 if (label.len)
3254 fprintf (outfile, "%s:\t", sb_name (&label));
3256 else
3257 fprintf (outfile, "\t");
3260 if (mri && ptr->value.i == K_END)
3262 sb t;
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);
3270 if (ptr->value.i & PROCESS)
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;
3282 if (!condass_on ())
3284 switch (ptr->value.i)
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;
3296 return 1;
3298 else
3300 switch (ptr->value.i)
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;
3461 return 0;
3466 /* Add a keyword to the hash table. */
3468 static void
3469 add_keyword (name, code)
3470 const char *name;
3471 int code;
3473 sb label;
3474 int j;
3476 sb_new (&label);
3477 sb_add_string (&label, name);
3479 hash_add_to_int_table (&keyword_hash_table, &label, code);
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);
3486 sb_kill (&label);
3489 /* Build the keyword hash table - put each keyword in the table twice,
3490 once upper and once lower case.*/
3492 static void
3493 process_init ()
3495 int i;
3497 for (i = 0; kinfo[i].name; i++)
3498 add_keyword (kinfo[i].name, kinfo[i].code);
3500 if (mri)
3502 for (i = 0; mrikinfo[i].name; i++)
3503 add_keyword (mrikinfo[i].name, mrikinfo[i].code);
3508 static void
3509 do_define (string)
3510 const char *string;
3512 sb label;
3513 int res = 1;
3514 hash_entry *ptr;
3515 sb_new (&label);
3518 while (*string)
3520 if (*string == '=')
3522 sb value;
3523 sb_new (&value);
3524 string++;
3525 while (*string)
3527 sb_add_char (&value, *string);
3528 string++;
3530 exp_get_abs (_("Invalid expression on command line.\n"), 0, &value, &res);
3531 sb_kill (&value);
3532 break;
3534 sb_add_char (&label, *string);
3536 string ++;
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);
3545 char *program_name;
3547 /* The list of long options. */
3548 static struct option long_options[] =
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 }
3565 /* Show a usage message and exit. */
3566 static void
3567 show_usage (file, status)
3568 FILE *file;
3569 int status;
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 bug-gnu-utils@gnu.org\n"));
3589 exit (status);
3592 /* Display a help message and exit. */
3593 static void
3594 show_help ()
3596 printf (_("%s: Gnu Assembler Macro Preprocessor\n"),
3597 program_name);
3598 show_usage (stdout, 0);
3602 main (argc, argv)
3603 int argc;
3604 char **argv;
3606 int opt;
3607 char *out_name = 0;
3608 sp = include_stack;
3610 ifstack[0].on = 1;
3611 ifi = 0;
3613 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
3614 setlocale (LC_MESSAGES, "");
3615 #endif
3616 bindtextdomain (PACKAGE, LOCALEDIR);
3617 textdomain (PACKAGE);
3619 program_name = argv[0];
3620 xmalloc_set_program_name (program_name);
3622 hash_new_table (101, &keyword_hash_table);
3623 hash_new_table (101, &assign_hash_table);
3624 hash_new_table (101, &vars);
3626 sb_new (&label);
3628 while ((opt = getopt_long (argc, argv, "I:sdhavc:upo:D:M", long_options,
3629 (int *) NULL))
3630 != EOF)
3632 switch (opt)
3634 case 'o':
3635 out_name = optarg;
3636 break;
3637 case 'u':
3638 unreasonable = 1;
3639 break;
3640 case 'I':
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;
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*/
3695 process_init ();
3697 macro_init (alternate, mri, 0, exp_get_abs);
3699 if (out_name) {
3700 outfile = fopen (out_name, "w");
3701 if (!outfile)
3703 fprintf (stderr, _("%s: Can't open output file `%s'.\n"),
3704 program_name, out_name);
3705 exit (1);
3708 else {
3709 outfile = stdout;
3712 chartype_init ();
3713 if (!outfile)
3714 outfile = stdout;
3716 /* Process all the input files */
3718 while (optind < argc)
3720 if (new_file (argv[optind]))
3722 process_file ();
3724 else
3726 fprintf (stderr, _("%s: Can't open input file `%s'.\n"),
3727 program_name, argv[optind]);
3728 exit (1);
3730 optind++;
3733 quit ();
3734 return 0;
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. */
3740 void
3741 as_abort (file, line, fn)
3742 const char *file, *fn;
3743 int line;
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);