1 /* gasp.c - Gnu assembler preprocessor main program.
2 Copyright (C) 1994, 95, 96, 1997 Free Software Foundation, Inc.
4 Written by Steve and Judy Chamberlain of Cygnus Support,
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)
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
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
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 !
62 #ifdef NEED_MALLOC_DECLARATION
63 extern char *malloc ();
67 #include "libiberty.h"
71 char *program_version = "1.2";
73 #define MAX_INCLUDES 30 /* Maximum include depth */
74 #define MAX_REASONABLE 1000 /* Maximum number of expansions */
76 int unreasonable; /* -u on command line */
77 int stats; /* -d on command line */
78 int print_line_number; /* -p flag on command line */
79 int copysource; /* -c flag on command line */
80 int warnings; /* Number of WARNINGs generated so far. */
81 int errors; /* Number of ERRORs generated so far. */
82 int fatals; /* Number of fatal ERRORs generated so far (either 0 or 1). */
83 int alternate = 0; /* -a on command line */
84 int mri = 0; /* -M on command line */
85 char comment_char = '!';
86 int radix = 10; /* Default radix */
88 int had_end; /* Seen .END */
90 /* The output stream */
93 /* the attributes of each character are stored as a bit pattern
94 chartype, which gives us quick tests. */
101 #define COMMENTBIT 16
103 #define ISCOMMENTCHAR(x) (chartype[(unsigned)(x)] & COMMENTBIT)
104 #define ISFIRSTCHAR(x) (chartype[(unsigned)(x)] & FIRSTBIT)
105 #define ISNEXTCHAR(x) (chartype[(unsigned)(x)] & NEXTBIT)
106 #define ISSEP(x) (chartype[(unsigned)(x)] & SEPBIT)
107 #define ISWHITE(x) (chartype[(unsigned)(x)] & WHITEBIT)
108 #define ISBASE(x) (chartype[(unsigned)(x)] & BASEBIT)
109 static char chartype[256];
112 /* Conditional assembly uses the `ifstack'. Each aif pushes another
113 entry onto the stack, and sets the on flag if it should. The aelse
114 sets hadelse, and toggles on. An aend pops a level. We limit to
115 100 levels of nesting, not because we're facists pigs with read
116 only minds, but because more than 100 levels of nesting is probably
117 a bug in the user's macro structure. */
119 #define IFNESTING 100
122 int on; /* is the level being output */
123 int hadelse; /* has an aelse been seen */
128 /* The final and intermediate results of expression evaluation are kept in
129 exp_t's. Note that a symbol is not an sb, but a pointer into the input
130 line. It must be coped somewhere safe before the next line is read in. */
141 int value; /* constant part */
142 symbol add_symbol; /* name part */
143 symbol sub_symbol; /* name part */
148 /* Hashing is done in a pretty standard way. A hash_table has a
149 pointer to a vector of pointers to hash_entrys, and the size of the
150 vector. A hash_entry contains a union of all the info we like to
151 store in hash table. If there is a hash collision, hash_entries
152 with the same hash are kept in a chain. */
154 /* What the data in a hash_entry means */
157 hash_integer, /* name->integer mapping */
158 hash_string, /* name->string mapping */
159 hash_macro, /* name is a macro */
160 hash_formal /* name is a formal argument */
165 sb key; /* symbol name */
166 hash_type type; /* symbol meaning */
171 struct macro_struct *m;
172 struct formal_struct *f;
174 struct hs *next; /* next hash_entry with same hash key */
184 /* Structures used to store macros.
186 Each macro knows its name and included text. It gets built with a
187 list of formal arguments, and also keeps a hash table which points
188 into the list to speed up formal search. Each formal knows its
189 name and its default value. Each time the macro is expanded, the
190 formals get the actual values attatched to them. */
192 /* describe the formal arguments to a macro */
194 typedef struct formal_struct
196 struct formal_struct *next; /* next formal in list */
197 sb name; /* name of the formal */
198 sb def; /* the default value */
199 sb actual; /* the actual argument (changed on each expansion) */
200 int index; /* the index of the formal 0..formal_count-1 */
204 /* describe the macro. */
206 typedef struct macro_struct
208 sb sub; /* substitution text. */
209 int formal_count; /* number of formal args. */
210 formal_entry *formals; /* pointer to list of formal_structs */
211 hash_table formal_hash; /* hash table of formals. */
215 /* how we nest files and expand macros etc.
217 we keep a stack of of include_stack structs. each include file
218 pushes a new level onto the stack. we keep an sb with a pushback
219 too. unget chars are pushed onto the pushback sb, getchars first
220 checks the pushback sb before reading from the input stream.
222 small things are expanded by adding the text of the item onto the
223 pushback sb. larger items are grown by pushing a new level and
224 allocating the entire pushback buf for the item. each time
225 something like a macro is expanded, the stack index is changed. we
226 can then perform an exitm by popping all entries off the stack with
227 the same stack index. if we're being reasonable, we can detect
228 recusive expansion by checking the index is reasonably small.
233 include_file, include_repeat, include_while, include_macro
238 sb pushback; /* current pushback stream */
239 int pushback_index; /* next char to read from stream */
240 FILE *handle; /* open file */
241 sb name; /* name of file */
242 int linecount; /* number of lines read so far */
244 int index; /* index of this layer */
246 include_stack[MAX_INCLUDES];
248 struct include_stack *sp;
249 #define isp (sp - include_stack)
251 /* Include file list */
253 typedef struct include_path
255 struct include_path *next;
259 include_path *paths_head;
260 include_path *paths_tail;
263 static void quit PARAMS ((void));
264 static void hash_new_table PARAMS ((int, hash_table *));
265 static int hash PARAMS ((sb *));
266 static hash_entry *hash_create PARAMS ((hash_table *, sb *));
267 static void hash_add_to_string_table PARAMS ((hash_table *, sb *, sb *, int));
268 static void hash_add_to_int_table PARAMS ((hash_table *, sb *, int));
269 static hash_entry *hash_lookup PARAMS ((hash_table *, sb *));
270 static void checkconst PARAMS ((int, exp_t *));
271 static int sb_strtol PARAMS ((int, sb *, int, int *));
272 static int level_0 PARAMS ((int, sb *, exp_t *));
273 static int level_1 PARAMS ((int, sb *, exp_t *));
274 static int level_2 PARAMS ((int, sb *, exp_t *));
275 static int level_3 PARAMS ((int, sb *, exp_t *));
276 static int level_4 PARAMS ((int, sb *, exp_t *));
277 static int level_5 PARAMS ((int, sb *, exp_t *));
278 static int exp_parse PARAMS ((int, sb *, exp_t *));
279 static void exp_string PARAMS ((exp_t *, sb *));
280 static int exp_get_abs PARAMS ((const char *, int, sb *, int *));
282 static void strip_comments PARAMS ((sb *));
284 static void unget PARAMS ((int));
285 static void include_buf PARAMS ((sb *, sb *, include_type, int));
286 static void include_print_where_line PARAMS ((FILE *));
287 static void include_print_line PARAMS ((FILE *));
288 static int get_line PARAMS ((sb *));
289 static int grab_label PARAMS ((sb *, sb *));
290 static void change_base PARAMS ((int, sb *, sb *));
291 static void do_end PARAMS ((sb *));
292 static void do_assign PARAMS ((int, int, sb *));
293 static void do_radix PARAMS ((sb *));
294 static int get_opsize PARAMS ((int, sb *, int *));
295 static int eol PARAMS ((int, sb *));
296 static void do_data PARAMS ((int, sb *, int));
297 static void do_datab PARAMS ((int, sb *));
298 static void do_align PARAMS ((int, sb *));
299 static void do_res PARAMS ((int, sb *, int));
300 static void do_export PARAMS ((sb *));
301 static void do_print PARAMS ((int, sb *));
302 static void do_heading PARAMS ((int, sb *));
303 static void do_page PARAMS ((void));
304 static void do_form PARAMS ((int, sb *));
305 static int get_any_string PARAMS ((int, sb *, sb *, int, int));
306 static int skip_openp PARAMS ((int, sb *));
307 static int skip_closep PARAMS ((int, sb *));
308 static int dolen PARAMS ((int, sb *, sb *));
309 static int doinstr PARAMS ((int, sb *, sb *));
310 static int dosubstr PARAMS ((int, sb *, sb *));
311 static void process_assigns PARAMS ((int, sb *, sb *));
312 static int get_and_process PARAMS ((int, sb *, sb *));
313 static void process_file PARAMS ((void));
314 static void free_old_entry PARAMS ((hash_entry *));
315 static void do_assigna PARAMS ((int, sb *));
316 static void do_assignc PARAMS ((int, sb *));
317 static void do_reg PARAMS ((int, sb *));
318 static int condass_lookup_name PARAMS ((sb *, int, sb *, int));
319 static int whatcond PARAMS ((int, sb *, int *));
320 static int istrue PARAMS ((int, sb *));
321 static void do_aif PARAMS ((int, sb *));
322 static void do_aelse PARAMS ((void));
323 static void do_aendi PARAMS ((void));
324 static int condass_on PARAMS ((void));
325 static void do_if PARAMS ((int, sb *, int));
326 static int get_mri_string PARAMS ((int, sb *, sb *, int));
327 static void do_ifc PARAMS ((int, sb *, int));
328 static void do_aendr PARAMS ((void));
329 static void do_awhile PARAMS ((int, sb *));
330 static void do_aendw PARAMS ((void));
331 static void do_exitm PARAMS ((void));
332 static void do_arepeat PARAMS ((int, sb *));
333 static void do_endm PARAMS ((void));
334 static void do_irp PARAMS ((int, sb *, int));
335 static void do_local PARAMS ((int, sb *));
336 static void do_macro PARAMS ((int, sb *));
337 static int macro_op PARAMS ((int, sb *));
338 static int getstring PARAMS ((int, sb *, sb *));
339 static void do_sdata PARAMS ((int, sb *, int));
340 static void do_sdatab PARAMS ((int, sb *));
341 static int new_file PARAMS ((const char *));
342 static void do_include PARAMS ((int, sb *));
343 static void include_pop PARAMS ((void));
344 static int get PARAMS ((void));
345 static int linecount PARAMS ((void));
346 static int include_next_index PARAMS ((void));
347 static void chartype_init PARAMS ((void));
348 static int process_pseudo_op PARAMS ((int, sb *, sb *));
349 static void add_keyword PARAMS ((const char *, int));
350 static void process_init PARAMS ((void));
351 static void do_define PARAMS ((const char *));
352 static void show_usage PARAMS ((FILE *, int));
353 static void show_help PARAMS ((void));
356 do { include_print_where_line (stderr); fprintf x ; fatals++; quit(); } while(0)
358 do { include_print_where_line (stderr); fprintf x; errors++; } while(0)
360 do { include_print_where_line (stderr); fprintf x; warnings++;} while(0)
364 /* exit the program and return the right ERROR code. */
377 for (i = 0; i < sb_max_power_two; i++)
379 fprintf (stderr, "strings size %8d : %d\n", 1<<i, string_count[i]);
385 /* hash table maintenance. */
387 /* build a new hash table with size buckets, and fill in the info at ptr. */
390 hash_new_table (size, ptr)
396 ptr->table = (hash_entry **) xmalloc (size * (sizeof (hash_entry *)));
397 /* Fill with null-pointer, not zero-bit-pattern. */
398 for (i = 0; i < size; i++)
402 /* calculate and return the hash value of the sb at key. */
411 for (i = 0; i < key->len; i++)
419 /* lookup key in hash_table tab, if present, then return it, otherwise
420 build a new one and fill it with hash_integer. */
424 hash_create (tab, key)
428 int k = hash (key) % tab->size;
430 hash_entry **table = tab->table;
438 hash_entry *n = (hash_entry *) xmalloc (sizeof (hash_entry));
441 sb_add_sb (&n->key, key);
443 n->type = hash_integer;
446 if (strncmp (table[k]->key.ptr, key->ptr, key->len) == 0)
454 /* add sb name with key into hash_table tab. if replacing old value
455 and again, then ERROR. */
459 hash_add_to_string_table (tab, key, name, again)
465 hash_entry *ptr = hash_create (tab, key);
466 if (ptr->type == hash_integer)
468 sb_new (&ptr->value.s);
470 if (ptr->value.s.len)
473 ERROR ((stderr, "redefinition not allowed\n"));
476 ptr->type = hash_string;
477 sb_reset (&ptr->value.s);
479 sb_add_sb (&ptr->value.s, name);
482 /* add integer name to hash_table tab with sb key. */
486 hash_add_to_int_table (tab, key, name)
491 hash_entry *ptr = hash_create (tab, key);
495 /* lookup sb key in hash_table tab. if found return hash_entry result,
500 hash_lookup (tab, key)
504 int k = hash (key) % tab->size;
505 hash_entry **table = tab->table;
506 hash_entry *p = table[k];
509 if (p->key.len == key->len
510 && strncmp (p->key.ptr, key->ptr, key->len) == 0)
520 are handled in a really simple recursive decent way. each bit of
521 the machine takes an index into an sb and a pointer to an exp_t,
522 modifies the *exp_t and returns the index of the first character
523 past the part of the expression parsed.
525 expression precedence:
536 /* make sure that the exp_t at term is constant, if not the give the op ERROR. */
540 checkconst (op, term)
544 if (term->add_symbol.len
545 || term->sub_symbol.len)
547 ERROR ((stderr, "the %c operator cannot take non-absolute arguments.\n", op));
551 /* turn the number in string at idx into a number of base,
552 fill in ptr and return the index of the first character not in the
557 sb_strtol (idx, string, base, ptr)
564 idx = sb_skip_white (idx, string);
566 while (idx < string->len)
568 int ch = string->ptr[idx];
572 else if (ch >= 'a' && ch <= 'f')
574 else if (ch >= 'A' && ch <= 'F')
582 value = value * base + dig;
590 level_0 (idx, string, lhs)
595 lhs->add_symbol.len = 0;
596 lhs->add_symbol.name = 0;
598 lhs->sub_symbol.len = 0;
599 lhs->sub_symbol.name = 0;
601 idx = sb_skip_white (idx, string);
605 if (isdigit (string->ptr[idx]))
607 idx = sb_strtol (idx, string, 10, &lhs->value);
609 else if (ISFIRSTCHAR (string->ptr[idx]))
612 lhs->add_symbol.name = string->ptr + idx;
613 while (idx < string->len && ISNEXTCHAR (string->ptr[idx]))
618 lhs->add_symbol.len = len;
620 else if (string->ptr[idx] == '"')
624 ERROR ((stderr, "string where expression expected.\n"));
625 idx = getstring (idx, string, &acc);
630 ERROR ((stderr, "can't find primary in expression.\n"));
633 return sb_skip_white (idx, string);
639 level_1 (idx, string, lhs)
644 idx = sb_skip_white (idx, string);
646 switch (string->ptr[idx])
649 idx = level_1 (idx + 1, string, lhs);
652 idx = level_1 (idx + 1, string, lhs);
653 checkconst ('~', lhs);
654 lhs->value = ~lhs->value;
659 idx = level_1 (idx + 1, string, lhs);
660 lhs->value = -lhs->value;
662 lhs->add_symbol = lhs->sub_symbol;
668 idx = level_5 (sb_skip_white (idx, string), string, lhs);
669 if (string->ptr[idx] != ')')
670 ERROR ((stderr, "misplaced closing parens.\n"));
675 idx = level_0 (idx, string, lhs);
678 return sb_skip_white (idx, string);
682 level_2 (idx, string, lhs)
689 idx = level_1 (idx, string, lhs);
691 while (idx < string->len && (string->ptr[idx] == '*'
692 || string->ptr[idx] == '/'))
694 char op = string->ptr[idx++];
695 idx = level_1 (idx, string, &rhs);
699 checkconst ('*', lhs);
700 checkconst ('*', &rhs);
701 lhs->value *= rhs.value;
704 checkconst ('/', lhs);
705 checkconst ('/', &rhs);
707 ERROR ((stderr, "attempt to divide by zero.\n"));
709 lhs->value /= rhs.value;
713 return sb_skip_white (idx, string);
718 level_3 (idx, string, lhs)
725 idx = level_2 (idx, string, lhs);
727 while (idx < string->len
728 && (string->ptr[idx] == '+'
729 || string->ptr[idx] == '-'))
731 char op = string->ptr[idx++];
732 idx = level_2 (idx, string, &rhs);
736 lhs->value += rhs.value;
737 if (lhs->add_symbol.name && rhs.add_symbol.name)
739 ERROR ((stderr, "can't add two relocatable expressions\n"));
741 /* change nn+symbol to symbol + nn */
742 if (rhs.add_symbol.name)
744 lhs->add_symbol = rhs.add_symbol;
748 lhs->value -= rhs.value;
749 lhs->sub_symbol = rhs.add_symbol;
753 return sb_skip_white (idx, string);
757 level_4 (idx, string, lhs)
764 idx = level_3 (idx, string, lhs);
766 while (idx < string->len &&
767 string->ptr[idx] == '&')
769 char op = string->ptr[idx++];
770 idx = level_3 (idx, string, &rhs);
774 checkconst ('&', lhs);
775 checkconst ('&', &rhs);
776 lhs->value &= rhs.value;
780 return sb_skip_white (idx, string);
784 level_5 (idx, string, lhs)
791 idx = level_4 (idx, string, lhs);
793 while (idx < string->len
794 && (string->ptr[idx] == '|' || string->ptr[idx] == '~'))
796 char op = string->ptr[idx++];
797 idx = level_4 (idx, string, &rhs);
801 checkconst ('|', lhs);
802 checkconst ('|', &rhs);
803 lhs->value |= rhs.value;
806 checkconst ('~', lhs);
807 checkconst ('~', &rhs);
808 lhs->value ^= rhs.value;
812 return sb_skip_white (idx, string);
816 /* parse the expression at offset idx into string, fill up res with
817 the result. return the index of the first char past the expression.
821 exp_parse (idx, string, res)
826 return level_5 (sb_skip_white (idx, string), string, res);
830 /* turn the expression at exp into text and glue it onto the end of
834 exp_string (exp, string)
842 if (exp->add_symbol.len)
844 sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
852 sb_add_char (string, '+');
853 sprintf (buf, "%d", exp->value);
854 sb_add_string (string, buf);
858 if (exp->sub_symbol.len)
860 sb_add_char (string, '-');
861 sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
867 sb_add_char (string, '0');
871 /* parse the expression at offset idx into sb in, return the value in val.
872 if the expression is not constant, give ERROR emsg. returns the index
873 of the first character past the end of the expression. */
876 exp_get_abs (emsg, idx, in, val)
883 idx = exp_parse (idx, in, &res);
884 if (res.add_symbol.len || res.sub_symbol.len)
885 ERROR ((stderr, emsg));
891 sb label; /* current label parsed from line */
892 hash_table assign_hash_table; /* hash table for all assigned variables */
893 hash_table keyword_hash_table; /* hash table for keyword */
894 hash_table vars; /* hash table for eq variables */
896 #define in_comment ';'
905 for (i = 0; i < out->len; i++)
907 if (ISCOMMENTCHAR(s[i]))
916 /* push back character ch so that it can be read again. */
926 if (sp->pushback_index)
927 sp->pushback_index--;
929 sb_add_char (&sp->pushback, ch);
932 /* push the sb ptr onto the include stack, with the given name, type and index. */
936 include_buf (name, ptr, type, index)
943 if (sp - include_stack >= MAX_INCLUDES)
944 FATAL ((stderr, "unreasonable nesting.\n"));
946 sb_add_sb (&sp->name, name);
949 sp->pushback_index = 0;
952 sb_new (&sp->pushback);
953 sb_add_sb (&sp->pushback, ptr);
957 /* used in ERROR messages, print info on where the include stack is onto file. */
960 include_print_where_line (file)
963 struct include_stack *p = include_stack + 1;
967 fprintf (file, "%s:%d ", sb_name (&p->name), p->linecount - 1);
972 /* used in listings, print the line number onto file. */
974 include_print_line (file)
978 struct include_stack *p = include_stack + 1;
980 n = fprintf (file, "%4d", p->linecount);
984 n += fprintf (file, ".%d", p->linecount);
995 /* read a line from the top of the include stack into sb in. */
1006 putc (comment_char, outfile);
1007 if (print_line_number)
1008 include_print_line (outfile);
1022 WARNING ((stderr, "End of file not at start of line.\n"));
1024 putc ('\n', outfile);
1043 /* continued line */
1046 putc (comment_char, outfile);
1047 putc ('+', outfile);
1060 sb_add_char (in, ch);
1068 /* find a label from sb in and put it in out. */
1071 grab_label (in, out)
1077 if (ISFIRSTCHAR (in->ptr[i]))
1079 sb_add_char (out, in->ptr[i]);
1081 while ((ISNEXTCHAR (in->ptr[i])
1082 || in->ptr[i] == '\\'
1083 || in->ptr[i] == '&')
1086 sb_add_char (out, in->ptr[i]);
1093 /* find all strange base stuff and turn into decimal. also
1094 find all the other numbers and convert them from the default radix */
1097 change_base (idx, in, out)
1104 while (idx < in->len)
1106 if (in->ptr[idx] == '\\'
1107 && idx + 1 < in->len
1108 && in->ptr[idx + 1] == '(')
1111 while (idx < in->len
1112 && in->ptr[idx] != ')')
1114 sb_add_char (out, in->ptr[idx]);
1120 else if (idx < in->len - 1 && in->ptr[idx + 1] == '\'' && ! mri)
1124 switch (in->ptr[idx])
1143 ERROR ((stderr, "Illegal base character %c.\n", in->ptr[idx]));
1148 idx = sb_strtol (idx + 2, in, base, &value);
1149 sprintf (buffer, "%d", value);
1150 sb_add_string (out, buffer);
1152 else if (ISFIRSTCHAR (in->ptr[idx]))
1154 /* copy entire names through quickly */
1155 sb_add_char (out, in->ptr[idx]);
1157 while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
1159 sb_add_char (out, in->ptr[idx]);
1163 else if (isdigit (in->ptr[idx]))
1166 /* all numbers must start with a digit, let's chew it and
1168 idx = sb_strtol (idx, in, radix, &value);
1169 sprintf (buffer, "%d", value);
1170 sb_add_string (out, buffer);
1172 /* skip all undigsested letters */
1173 while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
1175 sb_add_char (out, in->ptr[idx]);
1179 else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
1181 char tchar = in->ptr[idx];
1182 /* copy entire names through quickly */
1183 sb_add_char (out, in->ptr[idx]);
1185 while (idx < in->len && in->ptr[idx] != tchar)
1187 sb_add_char (out, in->ptr[idx]);
1193 /* nothing special, just pass it through */
1194 sb_add_char (out, in->ptr[idx]);
1208 fprintf (outfile, "%s\n", sb_name (in));
1214 do_assign (again, idx, in)
1219 /* stick label in symbol table with following value */
1224 idx = exp_parse (idx, in, &e);
1225 exp_string (&e, &acc);
1226 hash_add_to_string_table (&assign_hash_table, &label, &acc, again);
1231 /* .radix [b|q|d|h] */
1238 int idx = sb_skip_white (0, ptr);
1239 switch (ptr->ptr[idx])
1258 ERROR ((stderr, "radix is %c must be one of b, q, d or h", radix));
1263 /* Parse off a .b, .w or .l */
1266 get_opsize (idx, in, size)
1272 if (in->ptr[idx] == '.')
1276 switch (in->ptr[idx])
1294 ERROR ((stderr, "size must be one of b, w or l, is %c.\n", in->ptr[idx]));
1307 idx = sb_skip_white (idx, line);
1309 && ISCOMMENTCHAR(line->ptr[idx]))
1311 if (idx >= line->len)
1316 /* .data [.b|.w|.l] <data>*
1317 or d[bwl] <data>* */
1320 do_data (idx, in, size)
1326 char *opname = ".yikes!";
1332 idx = get_opsize (idx, in, &opsize);
1351 fprintf (outfile, "%s\t", opname);
1353 idx = sb_skip_white (idx, in);
1357 && in->ptr[idx] == '"')
1360 idx = getstring (idx, in, &acc);
1361 for (i = 0; i < acc.len; i++)
1364 fprintf(outfile,",");
1365 fprintf (outfile, "%d", acc.ptr[i]);
1370 while (!eol (idx, in))
1373 idx = exp_parse (idx, in, &e);
1374 exp_string (&e, &acc);
1375 sb_add_char (&acc, 0);
1376 fprintf (outfile, acc.ptr);
1377 if (idx < in->len && in->ptr[idx] == ',')
1379 fprintf (outfile, ",");
1385 sb_print_at (outfile, idx, in);
1386 fprintf (outfile, "\n");
1389 /* .datab [.b|.w|.l] <repeat>,<fill> */
1400 idx = get_opsize (idx, in, &opsize);
1402 idx = exp_get_abs ("datab repeat must be constant.\n", idx, in, &repeat);
1403 idx = sb_skip_comma (idx, in);
1404 idx = exp_get_abs ("datab data must be absolute.\n", idx, in, &fill);
1406 fprintf (outfile, ".fill\t%d,%d,%d\n", repeat, opsize, fill);
1416 int al, have_fill, fill;
1418 idx = exp_get_abs ("align needs absolute expression.\n", idx, in, &al);
1419 idx = sb_skip_white (idx, in);
1422 if (! eol (idx, in))
1424 idx = sb_skip_comma (idx, in);
1425 idx = exp_get_abs (".align needs absolute fill value.\n", idx, in,
1433 WARNING ((stderr, "alignment must be one of 1, 2 or 4.\n"));
1435 fprintf (outfile, ".align %d", al);
1437 fprintf (outfile, ",%d", fill);
1438 fprintf (outfile, "\n");
1441 /* .res[.b|.w|.l] <size> */
1444 do_res (idx, in, type)
1452 idx = get_opsize (idx, in, &size);
1453 while (!eol(idx, in))
1455 idx = sb_skip_white (idx, in);
1456 if (in->ptr[idx] == ',')
1458 idx = exp_get_abs ("res needs absolute expression for fill count.\n", idx, in, &count);
1460 if (type == 'c' || type == 'z')
1463 fprintf (outfile, ".space %d\n", count * size);
1474 fprintf (outfile, ".global %s\n", sb_name (in));
1477 /* .print [list] [nolist] */
1484 idx = sb_skip_white (idx, in);
1485 while (idx < in->len)
1487 if (strncasecmp (in->ptr + idx, "LIST", 4) == 0)
1489 fprintf (outfile, ".list\n");
1492 else if (strncasecmp (in->ptr + idx, "NOLIST", 6) == 0)
1494 fprintf (outfile, ".nolist\n");
1503 do_heading (idx, in)
1509 idx = getstring (idx, in, &head);
1510 fprintf (outfile, ".title \"%s\"\n", sb_name (&head));
1519 fprintf (outfile, ".eject\n");
1522 /* .form [lin=<value>] [col=<value>] */
1530 idx = sb_skip_white (idx, in);
1532 while (idx < in->len)
1535 if (strncasecmp (in->ptr + idx, "LIN=", 4) == 0)
1538 idx = exp_get_abs ("form LIN= needs absolute expresssion.\n", idx, in, &lines);
1541 if (strncasecmp (in->ptr + idx, "COL=", 4) == 0)
1544 idx = exp_get_abs ("form COL= needs absolute expresssion.\n", idx, in, &columns);
1549 fprintf (outfile, ".psize %d,%d\n", lines, columns);
1554 /* Fetch string from the input stream,
1556 'Bxyx<whitespace> -> return 'Bxyza
1557 %<char> -> return string of decimal value of x
1558 "<string>" -> return string
1559 xyx<whitespace> -> return xyz
1562 get_any_string (idx, in, out, expand, pretend_quoted)
1570 idx = sb_skip_white (idx, in);
1574 if (in->len > 2 && in->ptr[idx+1] == '\'' && ISBASE (in->ptr[idx]))
1576 while (!ISSEP (in->ptr[idx]))
1577 sb_add_char (out, in->ptr[idx++]);
1579 else if (in->ptr[idx] == '%'
1585 /* Turns the next expression into a string */
1586 idx = exp_get_abs ("% operator needs absolute expression",
1590 sprintf(buf, "%d", val);
1591 sb_add_string (out, buf);
1593 else if (in->ptr[idx] == '"'
1594 || in->ptr[idx] == '<'
1595 || (alternate && in->ptr[idx] == '\''))
1597 if (alternate && expand)
1599 /* Keep the quotes */
1600 sb_add_char (out, '\"');
1602 idx = getstring (idx, in, out);
1603 sb_add_char (out, '\"');
1607 idx = getstring (idx, in, out);
1612 while (idx < in->len
1613 && (in->ptr[idx] == '"'
1614 || in->ptr[idx] == '\''
1616 || !ISSEP (in->ptr[idx])))
1618 if (in->ptr[idx] == '"'
1619 || in->ptr[idx] == '\'')
1621 char tchar = in->ptr[idx];
1622 sb_add_char (out, in->ptr[idx++]);
1623 while (idx < in->len
1624 && in->ptr[idx] != tchar)
1625 sb_add_char (out, in->ptr[idx++]);
1629 sb_add_char (out, in->ptr[idx++]);
1638 /* skip along sb in starting at idx, suck off whitespace a ( and more
1639 whitespace. return the idx of the next char */
1642 skip_openp (idx, in)
1646 idx = sb_skip_white (idx, in);
1647 if (in->ptr[idx] != '(')
1648 ERROR ((stderr, "misplaced ( .\n"));
1649 idx = sb_skip_white (idx + 1, in);
1653 /* skip along sb in starting at idx, suck off whitespace a ) and more
1654 whitespace. return the idx of the next char */
1657 skip_closep (idx, in)
1661 idx = sb_skip_white (idx, in);
1662 if (in->ptr[idx] != ')')
1663 ERROR ((stderr, "misplaced ).\n"));
1664 idx = sb_skip_white (idx + 1, in);
1671 dolen (idx, in, out)
1680 sb_new (&stringout);
1681 idx = skip_openp (idx, in);
1682 idx = get_and_process (idx, in, &stringout);
1683 idx = skip_closep (idx, in);
1684 sprintf (buffer, "%d", stringout.len);
1685 sb_add_string (out, buffer);
1687 sb_kill (&stringout);
1696 doinstr (idx, in, out)
1710 idx = skip_openp (idx, in);
1711 idx = get_and_process (idx, in, &string);
1712 idx = sb_skip_comma (idx, in);
1713 idx = get_and_process (idx, in, &search);
1714 idx = sb_skip_comma (idx, in);
1715 if (isdigit (in->ptr[idx]))
1717 idx = exp_get_abs (".instr needs absolute expresson.\n", idx, in, &start);
1723 idx = skip_closep (idx, in);
1725 for (i = start; i < string.len; i++)
1727 if (strncmp (string.ptr + i, search.ptr, search.len) == 0)
1733 sprintf (buffer, "%d", res);
1734 sb_add_string (out, buffer);
1742 dosubstr (idx, in, out)
1752 idx = skip_openp (idx, in);
1753 idx = get_and_process (idx, in, &string);
1754 idx = sb_skip_comma (idx, in);
1755 idx = exp_get_abs ("need absolute position.\n", idx, in, &pos);
1756 idx = sb_skip_comma (idx, in);
1757 idx = exp_get_abs ("need absolute length.\n", idx, in, &len);
1758 idx = skip_closep (idx, in);
1761 if (len < 0 || pos < 0 ||
1763 || pos + len > string.len)
1765 sb_add_string (out, " ");
1769 sb_add_char (out, '"');
1772 sb_add_char (out, string.ptr[pos++]);
1775 sb_add_char (out, '"');
1781 /* scan line, change tokens in the hash table to their replacements */
1783 process_assigns (idx, in, buf)
1788 while (idx < in->len)
1791 if (in->ptr[idx] == '\\'
1792 && idx + 1 < in->len
1793 && in->ptr[idx + 1] == '(')
1797 sb_add_char (buf, in->ptr[idx]);
1800 while (idx < in->len && in->ptr[idx - 1] != ')');
1802 else if (in->ptr[idx] == '\\'
1803 && idx + 1 < in->len
1804 && in->ptr[idx + 1] == '&')
1806 idx = condass_lookup_name (in, idx + 2, buf, 1);
1808 else if (in->ptr[idx] == '\\'
1809 && idx + 1 < in->len
1810 && in->ptr[idx + 1] == '$')
1812 idx = condass_lookup_name (in, idx + 2, buf, 0);
1814 else if (idx + 3 < in->len
1815 && in->ptr[idx] == '.'
1816 && toupper ((unsigned char) in->ptr[idx + 1]) == 'L'
1817 && toupper ((unsigned char) in->ptr[idx + 2]) == 'E'
1818 && toupper ((unsigned char) in->ptr[idx + 3]) == 'N')
1819 idx = dolen (idx + 4, in, buf);
1820 else if (idx + 6 < in->len
1821 && in->ptr[idx] == '.'
1822 && toupper ((unsigned char) in->ptr[idx + 1]) == 'I'
1823 && toupper ((unsigned char) in->ptr[idx + 2]) == 'N'
1824 && toupper ((unsigned char) in->ptr[idx + 3]) == 'S'
1825 && toupper ((unsigned char) in->ptr[idx + 4]) == 'T'
1826 && toupper ((unsigned char) in->ptr[idx + 5]) == 'R')
1827 idx = doinstr (idx + 6, in, buf);
1828 else if (idx + 7 < in->len
1829 && in->ptr[idx] == '.'
1830 && toupper ((unsigned char) in->ptr[idx + 1]) == 'S'
1831 && toupper ((unsigned char) in->ptr[idx + 2]) == 'U'
1832 && toupper ((unsigned char) in->ptr[idx + 3]) == 'B'
1833 && toupper ((unsigned char) in->ptr[idx + 4]) == 'S'
1834 && toupper ((unsigned char) in->ptr[idx + 5]) == 'T'
1835 && toupper ((unsigned char) in->ptr[idx + 6]) == 'R')
1836 idx = dosubstr (idx + 7, in, buf);
1837 else if (ISFIRSTCHAR (in->ptr[idx]))
1839 /* may be a simple name subsitution, see if we have a word */
1842 while (cur < in->len
1843 && (ISNEXTCHAR (in->ptr[cur])))
1847 sb_add_buffer (&acc, in->ptr + idx, cur - idx);
1848 ptr = hash_lookup (&assign_hash_table, &acc);
1851 /* Found a definition for it */
1852 sb_add_sb (buf, &ptr->value.s);
1856 /* No definition, just copy the word */
1857 sb_add_sb (buf, &acc);
1864 sb_add_char (buf, in->ptr[idx++]);
1870 get_and_process (idx, in, out)
1877 idx = get_any_string (idx, in, &t, 1, 0);
1878 process_assigns (0, &t, out);
1899 more = get_line (&line);
1902 /* Find any label and pseudo op that we're intested in */
1907 fprintf (outfile, "\n");
1910 && (line.ptr[0] == '*'
1911 || line.ptr[0] == '!'))
1913 /* MRI line comment. */
1914 fprintf (outfile, sb_name (&line));
1918 l = grab_label (&line, &label_in);
1921 if (line.ptr[l] == ':')
1923 while (ISWHITE (line.ptr[l]) && l < line.len)
1930 /* Munge the label, unless this is EQU or ASSIGN. */
1933 && (line.ptr[l] == '.' || alternate || mri))
1937 if (line.ptr[lx] == '.')
1939 if (lx + 3 <= line.len
1940 && strncasecmp ("EQU", line.ptr + lx, 3) == 0
1941 && (lx + 3 == line.len
1942 || ! ISFIRSTCHAR (line.ptr[lx + 3])))
1944 else if (lx + 6 <= line.len
1945 && strncasecmp ("ASSIGN", line.ptr + lx, 6) == 0
1946 && (lx + 6 == line.len
1947 || ! ISFIRSTCHAR (line.ptr[lx + 6])))
1952 process_assigns (0, &label_in, &label);
1954 sb_add_sb (&label, &label_in);
1959 if (process_pseudo_op (l, &line, &acc))
1965 else if (condass_on ())
1967 if (macro_op (l, &line))
1977 fprintf (outfile, "%s:\t", sb_name (&label));
1980 fprintf (outfile, "\t");
1982 process_assigns (l, &line, &t1);
1984 change_base (0, &t1, &t2);
1985 fprintf (outfile, "%s\n", sb_name (&t2));
1991 /* Only a label on this line */
1992 if (label.len && condass_on())
1994 fprintf (outfile, "%s:\n", sb_name (&label));
2002 more = get_line (&line);
2005 if (!had_end && !mri)
2006 WARNING ((stderr, "END missing from end of file.\n"));
2014 free_old_entry (ptr)
2019 if (ptr->type == hash_string)
2020 sb_kill(&ptr->value.s);
2024 /* name: .ASSIGNA <value> */
2027 do_assigna (idx, in)
2035 process_assigns (idx, in, &tmp);
2036 idx = exp_get_abs (".ASSIGNA needs constant expression argument.\n", 0, &tmp, &val);
2040 ERROR ((stderr, ".ASSIGNA without label.\n"));
2044 hash_entry *ptr = hash_create (&vars, &label);
2045 free_old_entry (ptr);
2046 ptr->type = hash_integer;
2052 /* name: .ASSIGNC <string> */
2055 do_assignc (idx, in)
2061 idx = getstring (idx, in, &acc);
2065 ERROR ((stderr, ".ASSIGNS without label.\n"));
2069 hash_entry *ptr = hash_create (&vars, &label);
2070 free_old_entry (ptr);
2071 ptr->type = hash_string;
2072 sb_new (&ptr->value.s);
2073 sb_add_sb (&ptr->value.s, &acc);
2079 /* name: .REG (reg) */
2086 /* remove reg stuff from inside parens */
2089 idx = skip_openp (idx, in);
2091 idx = sb_skip_white (idx, in);
2093 while (idx < in->len
2096 : in->ptr[idx] != ')'))
2098 sb_add_char (&what, in->ptr[idx]);
2101 hash_add_to_string_table (&assign_hash_table, &label, &what, 1);
2107 condass_lookup_name (inbuf, idx, out, warn)
2115 sb_new (&condass_acc);
2117 while (idx < inbuf->len
2118 && ISNEXTCHAR (inbuf->ptr[idx]))
2120 sb_add_char (&condass_acc, inbuf->ptr[idx++]);
2123 if (inbuf->ptr[idx] == '\'')
2125 ptr = hash_lookup (&vars, &condass_acc);
2132 WARNING ((stderr, "Can't find preprocessor variable %s.\n", sb_name (&condass_acc)));
2136 sb_add_string (out, "0");
2141 if (ptr->type == hash_integer)
2144 sprintf (buffer, "%d", ptr->value.i);
2145 sb_add_string (out, buffer);
2149 sb_add_sb (out, &ptr->value.s);
2152 sb_kill (&condass_acc);
2165 whatcond (idx, in, val)
2172 idx = sb_skip_white (idx, in);
2174 if (idx + 1 < in->len)
2180 a = toupper ((unsigned char) p[0]);
2181 b = toupper ((unsigned char) p[1]);
2182 if (a == 'E' && b == 'Q')
2184 else if (a == 'N' && b == 'E')
2186 else if (a == 'L' && b == 'T')
2188 else if (a == 'L' && b == 'E')
2190 else if (a == 'G' && b == 'T')
2192 else if (a == 'G' && b == 'E')
2197 ERROR ((stderr, "Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n"));
2200 idx = sb_skip_white (idx + 2, in);
2217 idx = sb_skip_white (idx, in);
2219 if (in->ptr[idx] == '"')
2223 /* This is a string comparision */
2224 idx = getstring (idx, in, &acc_a);
2225 idx = whatcond (idx, in, &cond);
2226 idx = getstring (idx, in, &acc_b);
2227 same = acc_a.len == acc_b.len && (strncmp (acc_a.ptr, acc_b.ptr, acc_a.len) == 0);
2229 if (cond != EQ && cond != NE)
2231 ERROR ((stderr, "Comparison operator for strings must be EQ or NE\n"));
2235 res = (cond != EQ) ^ same;
2238 /* This is a numeric expression */
2243 idx = exp_get_abs ("Conditional operator must have absolute operands.\n", idx, in, &vala);
2244 idx = whatcond (idx, in, &cond);
2245 idx = sb_skip_white (idx, in);
2246 if (in->ptr[idx] == '"')
2248 WARNING ((stderr, "String compared against expression.\n"));
2253 idx = exp_get_abs ("Conditional operator must have absolute operands.\n", idx, in, &valb);
2296 if (ifi >= IFNESTING)
2298 FATAL ((stderr, "AIF nesting unreasonable.\n"));
2301 ifstack[ifi].on = ifstack[ifi-1].on ? istrue (idx, in) : 0;
2302 ifstack[ifi].hadelse = 0;
2310 ifstack[ifi].on = ifstack[ifi-1].on ? !ifstack[ifi].on : 0;
2311 if (ifstack[ifi].hadelse)
2313 ERROR ((stderr, "Multiple AELSEs in AIF.\n"));
2315 ifstack[ifi].hadelse = 1;
2329 ERROR ((stderr, "AENDI without AIF.\n"));
2336 return ifstack[ifi].on;
2339 /* MRI IFEQ, IFNE, IFLT, IFLE, IFGE, IFGT. */
2342 do_if (idx, in, cond)
2350 if (ifi >= IFNESTING)
2352 FATAL ((stderr, "IF nesting unreasonable.\n"));
2355 idx = exp_get_abs ("Conditional operator must have absolute operands.\n",
2360 case EQ: res = val == 0; break;
2361 case NE: res = val != 0; break;
2362 case LT: res = val < 0; break;
2363 case LE: res = val <= 0; break;
2364 case GE: res = val >= 0; break;
2365 case GT: res = val > 0; break;
2369 ifstack[ifi].on = ifstack[ifi-1].on ? res: 0;
2370 ifstack[ifi].hadelse = 0;
2373 /* Get a string for the MRI IFC or IFNC pseudo-ops. */
2376 get_mri_string (idx, in, val, terminator)
2382 idx = sb_skip_white (idx, in);
2385 && in->ptr[idx] == '\'')
2387 sb_add_char (val, '\'');
2388 for (++idx; idx < in->len; ++idx)
2390 sb_add_char (val, in->ptr[idx]);
2391 if (in->ptr[idx] == '\'')
2395 || in->ptr[idx] != '\'')
2399 idx = sb_skip_white (idx, in);
2405 while (idx < in->len
2406 && in->ptr[idx] != terminator)
2408 sb_add_char (val, in->ptr[idx]);
2412 while (i >= 0 && ISWHITE (val->ptr[i]))
2420 /* MRI IFC, IFNC. */
2423 do_ifc (idx, in, ifnc)
2432 if (ifi >= IFNESTING)
2434 FATAL ((stderr, "IF nesting unreasonable.\n"));
2440 idx = get_mri_string (idx, in, &first, ',');
2442 if (idx >= in->len || in->ptr[idx] != ',')
2444 ERROR ((stderr, "Bad format for IF or IFNC.\n"));
2448 idx = get_mri_string (idx + 1, in, &second, ';');
2450 res = (first.len == second.len
2451 && strncmp (first.ptr, second.ptr, first.len) == 0);
2455 ifstack[ifi].on = ifstack[ifi-1].on ? res : 0;
2456 ifstack[ifi].hadelse = 0;
2464 ERROR ((stderr, "AENDR without a AREPEAT.\n"));
2466 ERROR ((stderr, "ENDR without a REPT.\n"));
2477 int line = linecount ();
2485 process_assigns (idx, in, &exp);
2486 doit = istrue (0, &exp);
2488 if (! buffer_and_nest ("AWHILE", "AENDW", &sub, get_line))
2489 FATAL ((stderr, "AWHILE without a AENDW at %d.\n", line - 1));
2504 int index = include_next_index ();
2508 sb_add_sb (©, &sub);
2509 sb_add_sb (©, in);
2510 sb_add_string (©, "\n");
2511 sb_add_sb (©, &sub);
2512 sb_add_string (©, "\t.AENDW\n");
2513 /* Push another WHILE */
2514 include_buf (&exp, ©, include_while, index);
2527 ERROR ((stderr, "AENDW without a AENDW.\n"));
2533 Pop things off the include stack until the type and index changes */
2538 include_type type = sp->type;
2539 if (type == include_repeat
2540 || type == include_while
2541 || type == include_macro)
2543 int index = sp->index;
2545 while (sp->index == index
2546 && sp->type == type)
2556 do_arepeat (idx, in)
2560 int line = linecount ();
2561 sb exp; /* buffer with expression in it */
2562 sb copy; /* expanded repeat block */
2563 sb sub; /* contents of AREPEAT */
2571 process_assigns (idx, in, &exp);
2572 idx = exp_get_abs ("AREPEAT must have absolute operand.\n", 0, &exp, &rc);
2574 ret = buffer_and_nest ("AREPEAT", "AENDR", &sub, get_line);
2576 ret = buffer_and_nest ("REPT", "ENDR", &sub, get_line);
2578 FATAL ((stderr, "AREPEAT without a AENDR at %d.\n", line - 1));
2581 /* Push back the text following the repeat, and another repeat block
2592 int index = include_next_index ();
2593 sb_add_sb (©, &sub);
2597 sprintf (buffer, "\t.AREPEAT %d\n", rc - 1);
2599 sprintf (buffer, "\tREPT %d\n", rc - 1);
2600 sb_add_string (©, buffer);
2601 sb_add_sb (©, &sub);
2603 sb_add_string (©, " .AENDR\n");
2605 sb_add_string (©, " ENDR\n");
2608 include_buf (&exp, ©, include_repeat, index);
2620 ERROR ((stderr, ".ENDM without a matching .MACRO.\n"));
2623 /* MRI IRP pseudo-op. */
2626 do_irp (idx, in, irpc)
2636 err = expand_irp (irpc, idx, in, &out, get_line, comment_char);
2638 ERROR ((stderr, "%s\n", err));
2640 fprintf (outfile, "%s", sb_terminate (&out));
2645 /* MACRO PROCESSING */
2647 /* Parse off LOCAL n1, n2,... Invent a label name for it */
2650 do_local (idx, line)
2654 ERROR ((stderr, "LOCAL outside of MACRO"));
2663 int line = linecount ();
2665 err = define_macro (idx, in, &label, get_line, (const char **) NULL);
2667 ERROR ((stderr, "macro at line %d: %s\n", line - 1, err));
2679 if (! macro_defined)
2683 if (! check_macro (in->ptr + idx, &out, comment_char, &err))
2687 ERROR ((stderr, "%s\n", err));
2690 sb_add_string (&name, "macro expansion");
2692 include_buf (&name, &out, include_macro, include_next_index ());
2700 /* STRING HANDLING */
2703 getstring (idx, in, acc)
2708 idx = sb_skip_white (idx, in);
2710 while (idx < in->len
2711 && (in->ptr[idx] == '"'
2712 || in->ptr[idx] == '<'
2713 || (in->ptr[idx] == '\'' && alternate)))
2715 if (in->ptr[idx] == '<')
2717 if (alternate || mri)
2721 while ((in->ptr[idx] != '>' || nest)
2724 if (in->ptr[idx] == '!')
2727 sb_add_char (acc, in->ptr[idx++]);
2730 if (in->ptr[idx] == '>')
2732 if (in->ptr[idx] == '<')
2734 sb_add_char (acc, in->ptr[idx++]);
2742 idx = exp_get_abs ("Character code in string must be absolute expression.\n",
2744 sb_add_char (acc, code);
2746 if (in->ptr[idx] != '>')
2747 ERROR ((stderr, "Missing > for character code.\n"));
2751 else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
2753 char tchar = in->ptr[idx];
2755 while (idx < in->len)
2757 if (alternate && in->ptr[idx] == '!')
2760 sb_add_char (acc, in->ptr[idx++]);
2763 if (in->ptr[idx] == tchar)
2766 if (idx >= in->len || in->ptr[idx] != tchar)
2769 sb_add_char (acc, in->ptr[idx]);
2779 /* .SDATA[C|Z] <string> */
2783 do_sdata (idx, in, type)
2792 fprintf (outfile, ".byte\t");
2794 while (!eol (idx, in))
2798 idx = sb_skip_white (idx, in);
2799 while (!eol (idx, in))
2801 pidx = idx = get_any_string (idx, in, &acc, 0, 1);
2806 ERROR ((stderr, "string for SDATAC longer than 255 characters (%d).\n", acc.len));
2808 fprintf (outfile, "%d", acc.len);
2812 for (i = 0; i < acc.len; i++)
2816 fprintf (outfile, ",");
2818 fprintf (outfile, "%d", acc.ptr[i]);
2825 fprintf (outfile, ",");
2826 fprintf (outfile, "0");
2828 idx = sb_skip_comma (idx, in);
2829 if (idx == pidx) break;
2831 if (!alternate && in->ptr[idx] != ',' && idx != in->len)
2833 fprintf (outfile, "\n");
2834 ERROR ((stderr, "illegal character in SDATA line (0x%x).\n", in->ptr[idx]));
2840 fprintf (outfile, "\n");
2843 /* .SDATAB <count> <string> */
2855 idx = exp_get_abs ("Must have absolute SDATAB repeat count.\n", idx, in, &repeat);
2858 ERROR ((stderr, "Must have positive SDATAB repeat count (%d).\n", repeat));
2862 idx = sb_skip_comma (idx, in);
2863 idx = getstring (idx, in, &acc);
2865 for (i = 0; i < repeat; i++)
2868 fprintf (outfile, "\t");
2869 fprintf (outfile, ".byte\t");
2870 sb_print (outfile, &acc);
2871 fprintf (outfile, "\n");
2881 FILE *newone = fopen (name, "r");
2885 if (isp == MAX_INCLUDES)
2886 FATAL ((stderr, "Unreasonable include depth (%ld).\n", (long) isp));
2889 sp->handle = newone;
2892 sb_add_string (&sp->name, name);
2895 sp->pushback_index = 0;
2896 sp->type = include_file;
2898 sb_new (&sp->pushback);
2903 do_include (idx, in)
2909 include_path *includes;
2915 idx = getstring (idx, in, &t);
2918 idx = sb_skip_white (idx, in);
2919 while (idx < in->len && ! ISWHITE (in->ptr[idx]))
2921 sb_add_char (&t, in->ptr[idx]);
2926 for (includes = paths_head; includes; includes = includes->next)
2929 sb_add_sb (&cat, &includes->path);
2930 sb_add_char (&cat, '/');
2931 sb_add_sb (&cat, &t);
2932 if (new_file (sb_name (&cat)))
2939 if (! new_file (sb_name (&t)))
2940 FATAL ((stderr, "Can't open include file `%s'.\n", sb_name (&t)));
2949 if (sp != include_stack)
2952 fclose (sp->handle);
2957 /* Get the next character from the include stack. If there's anything
2958 in the pushback buffer, take that first. If we're at eof, pop from
2959 the stack and try again. Keep the linecount up to date. */
2966 if (sp->pushback.len != sp->pushback_index)
2968 r = (char) (sp->pushback.ptr[sp->pushback_index++]);
2969 /* When they've all gone, reset the pointer */
2970 if (sp->pushback_index == sp->pushback.len)
2972 sp->pushback.len = 0;
2973 sp->pushback_index = 0;
2976 else if (sp->handle)
2978 r = getc (sp->handle);
2983 if (r == EOF && isp)
2987 while (r == EOF && isp)
3005 return sp->linecount;
3009 include_next_index ()
3013 && index > MAX_REASONABLE)
3014 FATAL ((stderr, "Unreasonable expansion (-u turns off check).\n"));
3019 /* Initialize the chartype vector. */
3025 for (x = 0; x < 256; x++)
3027 if (isalpha (x) || x == '_' || x == '$')
3028 chartype[x] |= FIRSTBIT;
3030 if (mri && x == '.')
3031 chartype[x] |= FIRSTBIT;
3033 if (isdigit (x) || isalpha (x) || x == '_' || x == '$')
3034 chartype[x] |= NEXTBIT;
3036 if (x == ' ' || x == '\t' || x == ',' || x == '"' || x == ';'
3037 || x == '"' || x == '<' || x == '>' || x == ')' || x == '(')
3038 chartype[x] |= SEPBIT;
3040 if (x == 'b' || x == 'B'
3041 || x == 'q' || x == 'Q'
3042 || x == 'h' || x == 'H'
3043 || x == 'd' || x == 'D')
3044 chartype [x] |= BASEBIT;
3046 if (x == ' ' || x == '\t')
3047 chartype[x] |= WHITEBIT;
3049 if (x == comment_char)
3050 chartype[x] |= COMMENTBIT;
3056 /* What to do with all the keywords */
3057 #define PROCESS 0x1000 /* Run substitution over the line */
3058 #define LAB 0x2000 /* Spit out the label */
3060 #define K_EQU (PROCESS|1)
3061 #define K_ASSIGN (PROCESS|2)
3062 #define K_REG (PROCESS|3)
3063 #define K_ORG (PROCESS|4)
3064 #define K_RADIX (PROCESS|5)
3065 #define K_DATA (LAB|PROCESS|6)
3066 #define K_DATAB (LAB|PROCESS|7)
3067 #define K_SDATA (LAB|PROCESS|8)
3068 #define K_SDATAB (LAB|PROCESS|9)
3069 #define K_SDATAC (LAB|PROCESS|10)
3070 #define K_SDATAZ (LAB|PROCESS|11)
3071 #define K_RES (LAB|PROCESS|12)
3072 #define K_SRES (LAB|PROCESS|13)
3073 #define K_SRESC (LAB|PROCESS|14)
3074 #define K_SRESZ (LAB|PROCESS|15)
3075 #define K_EXPORT (LAB|PROCESS|16)
3076 #define K_GLOBAL (LAB|PROCESS|17)
3077 #define K_PRINT (LAB|PROCESS|19)
3078 #define K_FORM (LAB|PROCESS|20)
3079 #define K_HEADING (LAB|PROCESS|21)
3080 #define K_PAGE (LAB|PROCESS|22)
3081 #define K_IMPORT (LAB|PROCESS|23)
3082 #define K_PROGRAM (LAB|PROCESS|24)
3083 #define K_END (PROCESS|25)
3084 #define K_INCLUDE (PROCESS|26)
3085 #define K_IGNORED (PROCESS|27)
3086 #define K_ASSIGNA (PROCESS|28)
3087 #define K_ASSIGNC (29)
3088 #define K_AIF (PROCESS|30)
3089 #define K_AELSE (PROCESS|31)
3090 #define K_AENDI (PROCESS|32)
3091 #define K_AREPEAT (PROCESS|33)
3092 #define K_AENDR (PROCESS|34)
3093 #define K_AWHILE (35)
3094 #define K_AENDW (PROCESS|36)
3095 #define K_EXITM (37)
3096 #define K_MACRO (PROCESS|38)
3098 #define K_ALIGN (PROCESS|LAB|40)
3099 #define K_ALTERNATE (41)
3100 #define K_DB (LAB|PROCESS|42)
3101 #define K_DW (LAB|PROCESS|43)
3102 #define K_DL (LAB|PROCESS|44)
3103 #define K_LOCAL (45)
3104 #define K_IFEQ (PROCESS|46)
3105 #define K_IFNE (PROCESS|47)
3106 #define K_IFLT (PROCESS|48)
3107 #define K_IFLE (PROCESS|49)
3108 #define K_IFGE (PROCESS|50)
3109 #define K_IFGT (PROCESS|51)
3110 #define K_IFC (PROCESS|52)
3111 #define K_IFNC (PROCESS|53)
3112 #define K_IRP (PROCESS|54)
3113 #define K_IRPC (PROCESS|55)
3123 static struct keyword kinfo[] =
3125 { "EQU", K_EQU, 0 },
3126 { "ALTERNATE", K_ALTERNATE, 0 },
3127 { "ASSIGN", K_ASSIGN, 0 },
3128 { "REG", K_REG, 0 },
3129 { "ORG", K_ORG, 0 },
3130 { "RADIX", K_RADIX, 0 },
3131 { "DATA", K_DATA, 0 },
3135 { "DATAB", K_DATAB, 0 },
3136 { "SDATA", K_SDATA, 0 },
3137 { "SDATAB", K_SDATAB, 0 },
3138 { "SDATAZ", K_SDATAZ, 0 },
3139 { "SDATAC", K_SDATAC, 0 },
3140 { "RES", K_RES, 0 },
3141 { "SRES", K_SRES, 0 },
3142 { "SRESC", K_SRESC, 0 },
3143 { "SRESZ", K_SRESZ, 0 },
3144 { "EXPORT", K_EXPORT, 0 },
3145 { "GLOBAL", K_GLOBAL, 0 },
3146 { "PRINT", K_PRINT, 0 },
3147 { "FORM", K_FORM, 0 },
3148 { "HEADING", K_HEADING, 0 },
3149 { "PAGE", K_PAGE, 0 },
3150 { "PROGRAM", K_IGNORED, 0 },
3151 { "END", K_END, 0 },
3152 { "INCLUDE", K_INCLUDE, 0 },
3153 { "ASSIGNA", K_ASSIGNA, 0 },
3154 { "ASSIGNC", K_ASSIGNC, 0 },
3155 { "AIF", K_AIF, 0 },
3156 { "AELSE", K_AELSE, 0 },
3157 { "AENDI", K_AENDI, 0 },
3158 { "AREPEAT", K_AREPEAT, 0 },
3159 { "AENDR", K_AENDR, 0 },
3160 { "EXITM", K_EXITM, 0 },
3161 { "MACRO", K_MACRO, 0 },
3162 { "ENDM", K_ENDM, 0 },
3163 { "AWHILE", K_AWHILE, 0 },
3164 { "ALIGN", K_ALIGN, 0 },
3165 { "AENDW", K_AENDW, 0 },
3166 { "ALTERNATE", K_ALTERNATE, 0 },
3167 { "LOCAL", K_LOCAL, 0 },
3171 /* Although the conditional operators are handled by gas, we need to
3172 handle them here as well, in case they are used in a recursive
3173 macro to end the recursion. */
3175 static struct keyword mrikinfo[] =
3177 { "IFEQ", K_IFEQ, 0 },
3178 { "IFNE", K_IFNE, 0 },
3179 { "IFLT", K_IFLT, 0 },
3180 { "IFLE", K_IFLE, 0 },
3181 { "IFGE", K_IFGE, 0 },
3182 { "IFGT", K_IFGT, 0 },
3183 { "IFC", K_IFC, 0 },
3184 { "IFNC", K_IFNC, 0 },
3185 { "ELSEC", K_AELSE, 0 },
3186 { "ENDC", K_AENDI, 0 },
3187 { "MEXIT", K_EXITM, 0 },
3188 { "REPT", K_AREPEAT, 0 },
3189 { "IRP", K_IRP, 0 },
3190 { "IRPC", K_IRPC, 0 },
3191 { "ENDR", K_AENDR, 0 },
3195 /* Look for a pseudo op on the line. If one's there then call
3199 process_pseudo_op (idx, line, acc)
3206 if (line->ptr[idx] == '.' || alternate || mri)
3208 /* Scan forward and find pseudo name */
3214 if (line->ptr[idx] == '.')
3216 in = line->ptr + idx;
3221 while (idx < line->len && *e && ISFIRSTCHAR (*e))
3223 sb_add_char (acc, *e);
3228 ptr = hash_lookup (&keyword_hash_table, acc);
3233 /* This one causes lots of pain when trying to preprocess
3235 WARNING ((stderr, "Unrecognised pseudo op `%s'.\n", sb_name (acc)));
3239 if (ptr->value.i & LAB)
3240 { /* output the label */
3243 fprintf (outfile, "%s:\t", sb_name (&label));
3246 fprintf (outfile, "\t");
3249 if (mri && ptr->value.i == K_END)
3254 sb_add_buffer (&t, line->ptr + oidx, idx - oidx);
3255 fprintf (outfile, "\t%s", sb_name (&t));
3259 if (ptr->value.i & PROCESS)
3261 /* Polish the rest of the line before handling the pseudo op */
3263 strip_comments(line);
3266 process_assigns (idx, line, acc);
3268 change_base (0, acc, line);
3273 switch (ptr->value.i)
3289 switch (ptr->value.i)
3293 macro_init (1, mri, 0, exp_get_abs);
3302 ERROR ((stderr, "ORG command not allowed.\n"));
3308 do_data (idx, line, 1);
3311 do_data (idx, line, 2);
3314 do_data (idx, line, 4);
3317 do_data (idx, line, 0);
3320 do_datab (idx, line);
3323 do_sdata (idx, line, 0);
3326 do_sdatab (idx, line);
3329 do_sdata (idx, line, 'c');
3332 do_sdata (idx, line, 'z');
3335 do_assign (0, 0, line);
3341 do_arepeat (idx, line);
3347 do_awhile (idx, line);
3353 do_assign (1, idx, line);
3356 do_align (idx, line);
3359 do_res (idx, line, 0);
3362 do_res (idx, line, 's');
3365 do_include (idx, line);
3368 do_local (idx, line);
3371 do_macro (idx, line);
3377 do_res (idx, line, 'c');
3380 do_print (idx, line);
3383 do_form (idx, line);
3386 do_heading (idx, line);
3398 do_res (idx, line, 'z');
3406 do_assigna (idx, line);
3409 do_assignc (idx, line);
3418 do_if (idx, line, EQ);
3421 do_if (idx, line, NE);
3424 do_if (idx, line, LT);
3427 do_if (idx, line, LE);
3430 do_if (idx, line, GE);
3433 do_if (idx, line, GT);
3436 do_ifc (idx, line, 0);
3439 do_ifc (idx, line, 1);
3442 do_irp (idx, line, 0);
3445 do_irp (idx, line, 1);
3455 /* Add a keyword to the hash table. */
3458 add_keyword (name, code)
3466 sb_add_string (&label, name);
3468 hash_add_to_int_table (&keyword_hash_table, &label, code);
3471 for (j = 0; name[j]; j++)
3472 sb_add_char (&label, name[j] - 'A' + 'a');
3473 hash_add_to_int_table (&keyword_hash_table, &label, code);
3478 /* Build the keyword hash table - put each keyword in the table twice,
3479 once upper and once lower case.*/
3486 for (i = 0; kinfo[i].name; i++)
3487 add_keyword (kinfo[i].name, kinfo[i].code);
3491 for (i = 0; mrikinfo[i].name; i++)
3492 add_keyword (mrikinfo[i].name, mrikinfo[i].code);
3516 sb_add_char (&value, *string);
3519 exp_get_abs ("Invalid expression on command line.\n", 0, &value, &res);
3523 sb_add_char (&label, *string);
3528 ptr = hash_create (&vars, &label);
3529 free_old_entry (ptr);
3530 ptr->type = hash_integer;
3536 /* The list of long options. */
3537 static struct option long_options[] =
3539 { "alternate", no_argument, 0, 'a' },
3540 { "include", required_argument, 0, 'I' },
3541 { "commentchar", required_argument, 0, 'c' },
3542 { "copysource", no_argument, 0, 's' },
3543 { "debug", no_argument, 0, 'd' },
3544 { "help", no_argument, 0, 'h' },
3545 { "mri", no_argument, 0, 'M' },
3546 { "output", required_argument, 0, 'o' },
3547 { "print", no_argument, 0, 'p' },
3548 { "unreasonable", no_argument, 0, 'u' },
3549 { "version", no_argument, 0, 'v' },
3550 { "define", required_argument, 0, 'd' },
3551 { NULL, no_argument, 0, 0 }
3554 /* Show a usage message and exit. */
3556 show_usage (file, status)
3562 [-a] [--alternate] enter alternate macro mode\n\
3563 [-c char] [--commentchar char] change the comment character from !\n\
3564 [-d] [--debug] print some debugging info\n\
3565 [-h] [--help] print this message\n\
3566 [-M] [--mri] enter MRI compatibility mode\n\
3567 [-o out] [--output out] set the output file\n\
3568 [-p] [--print] print line numbers\n", program_name);
3570 [-s] [--copysource] copy source through as comments \n\
3571 [-u] [--unreasonable] allow unreasonable nesting\n\
3572 [-v] [--version] print the program version\n\
3573 [-Dname=value] create preprocessor variable called name, with value\n\
3574 [-Ipath] add to include path list\n\
3581 /* Display a help message and exit. */
3585 printf ("%s: Gnu Assembler Macro Preprocessor\n",
3587 show_usage (stdout, 0);
3604 program_name = argv[0];
3605 xmalloc_set_program_name (program_name);
3607 hash_new_table (101, &keyword_hash_table);
3608 hash_new_table (101, &assign_hash_table);
3609 hash_new_table (101, &vars);
3613 while ((opt = getopt_long (argc, argv, "I:sdhavc:upo:D:M", long_options,
3627 include_path *p = (include_path *) xmalloc (sizeof (include_path));
3629 sb_add_string (&p->path, optarg);
3631 paths_tail->next = p;
3638 print_line_number = 1;
3641 comment_char = optarg[0];
3663 /* This output is intended to follow the GNU standards document. */
3664 printf ("GNU assembler pre-processor %s\n", program_version);
3665 printf ("Copyright 1996 Free Software Foundation, Inc.\n");
3667 This program is free software; you may redistribute it under the terms of\n\
3668 the GNU General Public License. This program has absolutely no warranty.\n");
3674 show_usage (stderr, 1);
3681 macro_init (alternate, mri, 0, exp_get_abs);
3684 outfile = fopen (out_name, "w");
3687 fprintf (stderr, "%s: Can't open output file `%s'.\n",
3688 program_name, out_name);
3700 /* Process all the input files */
3702 while (optind < argc)
3704 if (new_file (argv[optind]))
3710 fprintf (stderr, "%s: Can't open input file `%s'.\n",
3711 program_name, argv[optind]);
3721 /* This function is used because an abort in some of the other files
3722 may be compiled into as_abort because they include as.h. */
3725 as_abort (file, line, fn)
3726 const char *file, *fn;
3729 fprintf (stderr, "Internal error, aborting at %s line %d", file, line);
3731 fprintf (stderr, " in %s", fn);
3732 fprintf (stderr, "\nPlease report this bug.\n");