1 /* gasp.c - Gnu assembler preprocessor main program.
2 Copyright (C) 1994 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
21 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
25 This program translates the input macros and stuff into a form
26 suitable for gas to consume.
29 gasp [-sdhau] [-c char] [-o <outfile>] <infile>*
31 -s copy source to output
32 -c <char> comments are started with <char> instead of !
33 -u allow unreasonable stuff
35 -d print debugging stats
36 -s semi colons start comments
37 -a use alternate syntax
38 Pseudo ops can start with or without a .
39 Labels have to be in first column.
40 Macro arg parameters subsituted by name, don't need the &.
41 String can start with ' too.
42 Strings can be surrounded by <..>
43 A %<exp> in a string evaluates the expression
44 Literal char in a string with !
55 #include "libiberty.h"
57 char *program_version = "1.2";
59 #define MAX_INCLUDES 30 /* Maximum include depth */
60 #define MAX_REASONABLE 1000 /* Maximum number of expansions */
62 int unreasonable; /* -u on command line */
63 int stats; /* -d on command line */
64 int print_line_number; /* -p flag on command line */
65 int copysource; /* -c flag on command line */
66 int warnings; /* Number of WARNINGs generated so far. */
67 int errors; /* Number of ERRORs generated so far. */
68 int fatals; /* Number of fatal ERRORs generated so far (either 0 or 1). */
69 int alternate = 0; /* -a on command line */
70 char comment_char = '!';
71 int radix = 10; /* Default radix */
73 int had_end; /* Seen .END */
75 /* The output stream */
79 /* Forward declarations. */
80 static int condass_lookup_name();
81 static int condass_on();
83 static int get_and_process();
84 static int get_token();
85 static int getstring();
86 static int include_next_index();
87 static int macro_op();
88 static int linecount();
89 static int process_pseudo_op();
90 static void include_pop();
91 static void include_print_where_line();
94 I had a couple of choices when deciding upon this data structure.
95 gas uses null terminated strings for all its internal work. This
96 often means that parts of the program that want to examine
97 substrings have to manipulate the data in the string to do the
98 right thing (a common operation is to single out a bit of text by
99 saving away the character after it, nulling it out, operating on
100 the substring and then replacing the character which was under the
101 null). This is a pain and I remember a load of problems that I had with
102 code in gas which almost got this right. Also, it's harder to grow and
103 allocate null terminated strings efficiently.
105 Obstacks provide all the functionality needed, but are too
106 complicated, hence the sb.
108 An sb is allocated by the caller, and is initialzed to point to an
109 sb_element. sb_elements are kept on a free lists, and used when
110 needed, replaced onto the free list when unused.
113 #define max_power_two 30 /* don't allow strings more than
114 2^max_power_two long */
115 /* structure of an sb */
118 char *ptr; /* points to the current block. */
119 int len; /* how much is used. */
120 int pot; /* the maximum length is 1<<pot */
125 /* Structure of the free list object of an sb */
137 sb_element *size[max_power_two];
140 sb_list_vector free_list;
142 int string_count[max_power_two];
144 /* the attributes of each character are stored as a bit pattern
145 chartype, which gives us quick tests. */
152 #define COMMENTBIT 16
154 #define ISCOMMENTCHAR(x) (chartype[(unsigned)(x)] & COMMENTBIT)
155 #define ISFIRSTCHAR(x) (chartype[(unsigned)(x)] & FIRSTBIT)
156 #define ISNEXTCHAR(x) (chartype[(unsigned)(x)] & NEXTBIT)
157 #define ISSEP(x) (chartype[(unsigned)(x)] & SEPBIT)
158 #define ISWHITE(x) (chartype[(unsigned)(x)] & WHITEBIT)
160 static char chartype[256];
163 /* Conditional assembly uses the `ifstack'. Each aif pushes another
164 entry onto the stack, and sets the on flag if it should. The aelse
165 sets hadelse, and toggles on. An aend pops a level. We limit to
166 100 levels of nesting, not because we're facists pigs with read
167 only minds, but because more than 100 levels of nesting is probably
168 a bug in the user's macro structure. */
170 #define IFNESTING 100
173 int on; /* is the level being output */
174 int hadelse; /* has an aelse been seen */
179 /* The final and intermediate results of expression evaluation are kept in
180 exp_t's. Note that a symbol is not an sb, but a pointer into the input
181 line. It must be coped somewhere safe before the next line is read in. */
192 int value; /* constant part */
193 symbol add_symbol; /* name part */
194 symbol sub_symbol; /* name part */
199 /* Hashing is done in a pretty standard way. A hash_table has a
200 pointer to a vector of pointers to hash_entrys, and the size of the
201 vector. A hash_entry contains a union of all the info we like to
202 store in hash table. If there is a hash collision, hash_entries
203 with the same hash are kept in a chain. */
205 /* What the data in a hash_entry means */
208 hash_integer, /* name->integer mapping */
209 hash_string, /* name->string mapping */
210 hash_macro, /* name is a macro */
211 hash_formal /* name is a formal argument */
216 sb key; /* symbol name */
217 hash_type type; /* symbol meaning */
222 struct macro_struct *m;
223 struct formal_struct *f;
225 struct hs *next; /* next hash_entry with same hash key */
235 /* Structures used to store macros.
237 Each macro knows its name and included text. It gets built with a
238 list of formal arguments, and also keeps a hash table which points
239 into the list to speed up formal search. Each formal knows its
240 name and its default value. Each time the macro is expanded, the
241 formals get the actual values attatched to them. */
243 /* describe the formal arguments to a macro */
245 typedef struct formal_struct
247 struct formal_struct *next; /* next formal in list */
248 sb name; /* name of the formal */
249 sb def; /* the default value */
250 sb actual; /* the actual argument (changed on each expansion) */
251 int index; /* the index of the formal 0..formal_count-1 */
255 /* describe the macro. */
257 typedef struct macro_struct
259 sb sub; /* substitution text. */
260 int formal_count; /* number of formal args. */
261 formal_entry *formals; /* pointer to list of formal_structs */
262 hash_table formal_hash; /* hash table of formals. */
266 /* how we nest files and expand macros etc.
268 we keep a stack of of include_stack structs. each include file
269 pushes a new level onto the stack. we keep an sb with a pushback
270 too. unget chars are pushed onto the pushback sb, getchars first
271 checks the pushback sb before reading from the input stream.
273 small things are expanded by adding the text of the item onto the
274 pushback sb. larger items are grown by pushing a new level and
275 allocating the entire pushback buf for the item. each time
276 something like a macro is expanded, the stack index is changed. we
277 can then perform an exitm by popping all entries off the stack with
278 the same stack index. if we're being reasonable, we can detect
279 recusive expansion by checking the index is reasonably small.
284 include_file, include_repeat, include_while, include_macro
289 sb pushback; /* current pushback stream */
290 int pushback_index; /* next char to read from stream */
291 FILE *handle; /* open file */
292 sb name; /* name of file */
293 int linecount; /* number of lines read so far */
295 int index; /* index of this layer */
297 include_stack[MAX_INCLUDES];
299 struct include_stack *sp;
300 #define isp (sp - include_stack)
305 void include_print_where_line ();
309 do { include_print_where_line (stderr); fprintf x ; fatals++; quit(); } while(0)
311 do { include_print_where_line (stderr); fprintf x; errors++; } while(0)
313 do { include_print_where_line (stderr); fprintf x; warnings++;} while(0)
317 /* exit the program and return the right ERROR code. */
330 for (i = 0; i < max_power_two; i++)
332 fprintf (stderr, "strings size %8d : %d\n", 1<<i, string_count[i]);
339 /* this program is about manipulating strings.
340 they are managed in things called `sb's which is an abbreviation
341 for string buffers. an sb has to be created, things can be glued
342 on to it, and at the end of it's life it should be freed. the
343 contents should never be pointed at whilst it is still growing,
344 since it could be moved at any time
348 sb_grow... (&foo,...);
354 /* initializes an sb. */
361 /* see if we can find one to allocate */
364 if (size > max_power_two)
366 FATAL ((stderr, "string longer than %d bytes requested.\n",
367 1 << max_power_two));
369 e = free_list.size[size];
372 /* nothing there, allocate one and stick into the free list */
373 e = (sb_element *) xmalloc (sizeof (sb_element) + (1 << size));
374 e->next = free_list.size[size];
376 free_list.size[size] = e;
377 string_count[size]++;
380 /* remove from free list */
382 free_list.size[size] = e->next;
384 /* copy into callers world */
396 sb_build (ptr, dsize);
399 /* deallocate the sb at ptr */
406 /* return item to free list */
407 ptr->item->next = free_list.size[ptr->pot];
408 free_list.size[ptr->pot] = ptr->item;
411 /* add the sb at s to the end of the sb at ptr */
413 static void sb_check ();
421 sb_check (ptr, s->len);
422 memcpy (ptr->ptr + ptr->len, s->ptr, s->len);
426 /* make sure that the sb at ptr has room for another len characters,
427 and grow it if it doesn't. */
434 if (ptr->len + len >= 1 << ptr->pot)
438 while (ptr->len + len >= 1 << pot)
440 sb_build (&tmp, pot);
441 sb_add_sb (&tmp, ptr);
447 /* make the sb at ptr point back to the beginning. */
456 /* add character c to the end of the sb at ptr. */
464 ptr->ptr[ptr->len++] = c;
467 /* add null terminated string s to the end of sb at ptr. */
470 sb_add_string (ptr, s)
474 int len = strlen (s);
476 memcpy (ptr->ptr + ptr->len, s, len);
480 /* add string at s of length len to sb at ptr */
483 sb_add_buffer (ptr, s, len)
489 memcpy (ptr->ptr + ptr->len, s, len);
494 /* print the sb at ptr to the output file */
504 for (i = 0; i < ptr->len; i++)
508 fprintf (outfile, ",");
510 fprintf (outfile, "%d", ptr->ptr[i]);
517 sb_print_at (idx, ptr)
522 for (i = idx; i < ptr->len; i++)
523 putc (ptr->ptr[i], outfile);
525 /* put a null at the end of the sb at in and return the start of the
526 string, so that it can be used as an arg to printf %s. */
533 /* stick a null on the end of the string */
538 /* start at the index idx into the string in sb at ptr and skip
539 whitespace. return the index of the first non whitespace character */
542 sb_skip_white (idx, ptr)
546 while (idx < ptr->len && ISWHITE (ptr->ptr[idx]))
551 /* start at the index idx into the sb at ptr. skips whitespace,
552 a comma and any following whitespace. returnes the index of the
556 sb_skip_comma (idx, ptr)
560 while (idx < ptr->len && ISWHITE (ptr->ptr[idx]))
564 && ptr->ptr[idx] == ',')
567 while (idx < ptr->len && ISWHITE (ptr->ptr[idx]))
574 /* hash table maintenance. */
576 /* build a new hash table with size buckets, and fill in the info at ptr. */
579 hash_new_table (size, ptr)
584 ptr->table = (hash_entry **) xmalloc (size * (sizeof (hash_entry *)));
585 /* Fill with null-pointer, not zero-bit-pattern. */
586 for (i = 0; i < size; i++)
590 /* calculate and return the hash value of the sb at key. */
599 for (i = 0; i < key->len; i++)
607 /* lookup key in hash_table tab, if present, then return it, otherwise
608 build a new one and fill it with hash_integer. */
612 hash_create (tab, key)
616 int k = hash (key) % tab->size;
618 hash_entry **table = tab->table;
626 hash_entry *n = (hash_entry *) xmalloc (sizeof (hash_entry));
629 sb_add_sb (&n->key, key);
631 n->type = hash_integer;
634 if (strncmp (table[k]->key.ptr, key->ptr, key->len) == 0)
642 /* add sb name with key into hash_table tab. if replacing old value
643 and again, then ERROR. */
647 hash_add_to_string_table (tab, key, name, again)
653 hash_entry *ptr = hash_create (tab, key);
654 if (ptr->type == hash_integer)
656 sb_new (&ptr->value.s);
658 if (ptr->value.s.len)
661 ERROR ((stderr, "redefintion not allowed"));
664 ptr->type = hash_string;
665 sb_reset (&ptr->value.s);
667 sb_add_sb (&ptr->value.s, name);
670 /* add integer name to hash_table tab with sb key. */
674 hash_add_to_int_table (tab, key, name)
679 hash_entry *ptr = hash_create (tab, key);
683 /* lookup sb key in hash_table tab. if found return hash_entry result,
688 hash_lookup (tab, key)
692 int k = hash (key) % tab->size;
693 hash_entry **table = tab->table;
694 hash_entry *p = table[k];
697 if (p->key.len == key->len
698 && strncmp (p->key.ptr, key->ptr, key->len) == 0)
708 are handled in a really simple recursive decent way. each bit of
709 the machine takes an index into an sb and a pointer to an exp_t,
710 modifies the *exp_t and returns the index of the first character
711 past the part of the expression parsed.
713 expression precedence:
724 /* make sure that the exp_t at term is constant, if not the give the op ERROR. */
728 checkconst (op, term)
732 if (term->add_symbol.len
733 || term->sub_symbol.len)
735 ERROR ((stderr, "the %c operator cannot take non-absolute arguments.\n", op));
739 /* turn the number in string at idx into a number of base,
740 fill in ptr and return the index of the first character not in the
745 sb_strtol (idx, string, base, ptr)
752 idx = sb_skip_white (idx, string);
754 while (idx < string->len)
756 int ch = string->ptr[idx];
760 else if (ch >= 'a' && ch <= 'f')
762 else if (ch >= 'A' && ch <= 'F')
770 value = value * base + dig;
777 static int level_5 ();
780 level_0 (idx, string, lhs)
785 lhs->add_symbol.len = 0;
786 lhs->add_symbol.name = 0;
788 lhs->sub_symbol.len = 0;
789 lhs->sub_symbol.name = 0;
791 idx = sb_skip_white (idx, string);
795 if (isdigit (string->ptr[idx]))
797 idx = sb_strtol (idx, string, 10, &lhs->value);
799 else if (ISFIRSTCHAR (string->ptr[idx]))
802 lhs->add_symbol.name = string->ptr + idx;
803 while (idx < string->len && ISNEXTCHAR (string->ptr[idx]))
808 lhs->add_symbol.len = len;
810 else if (string->ptr[idx] == '"')
814 ERROR ((stderr, "string where expression expected.\n"));
815 idx = getstring (idx, string, &acc);
820 ERROR ((stderr, "can't find primary in expression.\n"));
823 return sb_skip_white (idx, string);
829 level_1 (idx, string, lhs)
834 idx = sb_skip_white (idx, string);
836 switch (string->ptr[idx])
839 idx = level_1 (idx + 1, string, lhs);
842 idx = level_1 (idx + 1, string, lhs);
843 checkconst ('~', lhs);
844 lhs->value = ~lhs->value;
849 idx = level_1 (idx + 1, string, lhs);
850 lhs->value = -lhs->value;
852 lhs->add_symbol = lhs->sub_symbol;
858 idx = level_5 (sb_skip_white (idx, string), string, lhs);
859 if (string->ptr[idx] != ')')
860 ERROR ((stderr, "misplaced closing parens.\n"));
865 idx = level_0 (idx, string, lhs);
868 return sb_skip_white (idx, string);
872 level_2 (idx, string, lhs)
879 idx = level_1 (idx, string, lhs);
881 while (idx < string->len && (string->ptr[idx] == '*'
882 || string->ptr[idx] == '/'))
884 char op = string->ptr[idx++];
885 idx = level_1 (idx, string, &rhs);
889 checkconst ('*', lhs);
890 checkconst ('*', &rhs);
891 lhs->value *= rhs.value;
894 checkconst ('/', lhs);
895 checkconst ('/', &rhs);
897 ERROR ((stderr, "attempt to divide by zero.\n"));
899 lhs->value /= rhs.value;
903 return sb_skip_white (idx, string);
908 level_3 (idx, string, lhs)
915 idx = level_2 (idx, string, lhs);
917 while (idx < string->len
918 && (string->ptr[idx] == '+'
919 || string->ptr[idx] == '-'))
921 char op = string->ptr[idx++];
922 idx = level_2 (idx, string, &rhs);
926 lhs->value += rhs.value;
927 if (lhs->add_symbol.name && rhs.add_symbol.name)
929 ERROR ((stderr, "can't add two relocatable expressions\n"));
931 /* change nn+symbol to symbol + nn */
932 if (rhs.add_symbol.name)
934 lhs->add_symbol = rhs.add_symbol;
938 lhs->value -= rhs.value;
939 lhs->sub_symbol = rhs.add_symbol;
943 return sb_skip_white (idx, string);
947 level_4 (idx, string, lhs)
954 idx = level_3 (idx, string, lhs);
956 while (idx < string->len &&
957 string->ptr[idx] == '&')
959 char op = string->ptr[idx++];
960 idx = level_3 (idx, string, &rhs);
964 checkconst ('&', lhs);
965 checkconst ('&', &rhs);
966 lhs->value &= rhs.value;
970 return sb_skip_white (idx, string);
974 level_5 (idx, string, lhs)
981 idx = level_4 (idx, string, lhs);
983 while (idx < string->len
984 && (string->ptr[idx] == '|' || string->ptr[idx] == '~'))
986 char op = string->ptr[idx++];
987 idx = level_4 (idx, string, &rhs);
991 checkconst ('|', lhs);
992 checkconst ('|', &rhs);
993 lhs->value |= rhs.value;
996 checkconst ('~', lhs);
997 checkconst ('~', &rhs);
998 lhs->value ^= rhs.value;
1002 return sb_skip_white (idx, string);
1006 /* parse the expression at offset idx into string, fill up res with
1007 the result. return the index of the first char past the expression.
1011 exp_parse (idx, string, res)
1016 return level_5 (sb_skip_white (idx, string), string, res);
1020 /* turn the expression at exp into text and glue it onto the end of
1024 exp_string (exp, string)
1032 if (exp->add_symbol.len)
1034 sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
1042 sb_add_char (string, '+');
1043 sprintf (buf, "%d", exp->value);
1044 sb_add_string (string, buf);
1048 if (exp->sub_symbol.len)
1050 sb_add_char (string, '-');
1051 sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
1057 sb_add_char (string, '0');
1061 /* parse the expression at offset idx into sb in, return the value in val.
1062 if the expression is not constant, give ERROR emsg. returns the index
1063 of the first character past the end of the expression. */
1066 exp_get_abs (emsg, idx, in, val)
1073 idx = exp_parse (idx, in, &res);
1074 if (res.add_symbol.len || res.sub_symbol.len)
1075 ERROR ((stderr, emsg));
1081 sb label; /* current label parsed from line */
1082 hash_table assign_hash_table; /* hash table for all assigned variables */
1083 hash_table keyword_hash_table; /* hash table for keyword */
1084 hash_table vars; /* hash table for eq variables */
1086 #define in_comment ';'
1090 strip_comments (out)
1095 for (i = 0; i < out->len; i++)
1097 if (ISCOMMENTCHAR(s[i]))
1106 /* push back character ch so that it can be read again. */
1116 if (sp->pushback_index)
1117 sp->pushback_index--;
1119 sb_add_char (&sp->pushback, ch);
1122 /* push the sb ptr onto the include stack, with the given name, type and index. */
1126 include_buf (name, ptr, type, index)
1133 if (sp - include_stack >= MAX_INCLUDES)
1134 FATAL ((stderr, "unreasonable nesting.\n"));
1136 sb_add_sb (&sp->name, name);
1139 sp->pushback_index = 0;
1142 sb_new (&sp->pushback);
1143 sb_add_sb (&sp->pushback, ptr);
1147 /* used in ERROR messages, print info on where the include stack is onto file. */
1150 include_print_where_line (file)
1153 struct include_stack *p = include_stack + 1;
1157 fprintf (file, "%s:%d ", sb_name (&p->name), p->linecount - ((p == sp) ? 1 : 0));
1162 /* used in listings, print the line number onto file. */
1164 include_print_line (file)
1168 struct include_stack *p = include_stack + 1;
1170 n = fprintf (file, "%4d", p->linecount);
1174 n += fprintf (file, ".%d", p->linecount);
1179 fprintf (file, " ");
1185 /* read a line from the top of the include stack into sb in. */
1196 putc (comment_char, outfile);
1197 if (print_line_number)
1198 include_print_line (outfile);
1212 WARNING ((stderr, "End of file not at start of line.\n"));
1214 putc ('\n', outfile);
1233 /* continued line */
1236 putc (comment_char, outfile);
1237 putc ('+', outfile);
1250 sb_add_char (in, ch);
1258 /* find a label from sb in and put it in out. */
1261 grab_label (in, out)
1267 if (ISFIRSTCHAR (in->ptr[i]))
1269 sb_add_char (out, in->ptr[i]);
1271 while ((ISNEXTCHAR (in->ptr[i])
1272 || in->ptr[i] == '\\'
1273 || in->ptr[i] == '&')
1276 sb_add_char (out, in->ptr[i]);
1283 /* find all strange base stuff and turn into decimal. also
1284 find all the other numbers and convert them from the default radix */
1287 change_base (idx, in, out)
1294 while (idx < in->len)
1296 if (idx < in->len - 1 && in->ptr[idx + 1] == '\'')
1300 switch (in->ptr[idx])
1319 ERROR ((stderr, "Illegal base character %c.\n", in->ptr[idx]));
1324 idx = sb_strtol (idx + 2, in, base, &value);
1325 sprintf (buffer, "%d", value);
1326 sb_add_string (out, buffer);
1328 else if (ISFIRSTCHAR (in->ptr[idx]))
1330 /* copy entire names through quickly */
1331 sb_add_char (out, in->ptr[idx]);
1333 while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
1335 sb_add_char (out, in->ptr[idx]);
1339 else if (isdigit (in->ptr[idx]))
1342 /* all numbers must start with a digit, let's chew it and
1344 idx = sb_strtol (idx, in, radix, &value);
1345 sprintf (buffer, "%d", value);
1346 sb_add_string (out, buffer);
1348 /* skip all undigsested letters */
1349 while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
1351 sb_add_char (out, in->ptr[idx]);
1357 /* nothing special, just pass it through */
1358 sb_add_char (out, in->ptr[idx]);
1375 do_assign (again, idx, in)
1380 /* stick label in symbol table with following value */
1385 idx = exp_parse (idx, in, &e);
1386 exp_string (&e, &acc);
1387 hash_add_to_string_table (&assign_hash_table, &label, &acc, again);
1392 /* .radix [b|q|d|h] */
1399 int idx = sb_skip_white (0, ptr);
1400 switch (ptr->ptr[idx])
1419 ERROR ((stderr, "radix is %c must be one of b, q, d or h", radix));
1424 /* Parse off a .b, .w or .l */
1427 get_opsize (idx, in, size)
1433 if (in->ptr[idx] == '.')
1437 switch (in->ptr[idx])
1455 ERROR ((stderr, "size must be one of b, w or l, is %c.\n", in->ptr[idx]));
1468 idx = sb_skip_white (idx, line);
1470 && ISCOMMENTCHAR(line->ptr[idx]))
1472 if (idx >= line->len)
1477 /* .data [.b|.w|.l] <data>*
1478 or d[bwl] <data>* */
1481 do_data (idx, in, size)
1493 idx = get_opsize (idx, in, &opsize);
1512 fprintf (outfile, "%s\t", opname);
1514 idx = sb_skip_white (idx, in);
1518 && in->ptr[idx] == '"')
1521 idx = getstring (idx, in, &acc);
1522 for (i = 0; i < acc.len; i++)
1525 fprintf(outfile,",");
1526 fprintf (outfile, "%d", acc.ptr[i]);
1531 while (!eol (idx, in))
1534 idx = exp_parse (idx, in, &e);
1535 exp_string (&e, &acc);
1536 sb_add_char (&acc, 0);
1537 fprintf (outfile, acc.ptr);
1538 if (idx < in->len && in->ptr[idx] == ',')
1540 fprintf (outfile, ",");
1546 sb_print_at (idx, in);
1547 fprintf (outfile, "\n");
1550 /* .datab [.b|.w|.l] <repeat>,<fill> */
1561 idx = get_opsize (idx, in, &opsize);
1563 idx = exp_get_abs ("datab repeat must be constant.\n", idx, in, &repeat);
1564 idx = sb_skip_comma (idx, in);
1565 idx = exp_get_abs ("datab data must be absolute.\n", idx, in, &fill);
1567 fprintf (outfile, ".fill\t%d,%d,%d\n", repeat, opsize, fill);
1578 idx = exp_get_abs ("align needs absolute expression.\n", idx, in, &al);
1583 WARNING ((stderr, "alignment must be one of 1, 2 or 4.\n"));
1585 fprintf (outfile, ".align %d\n", al);
1588 /* .res[.b|.w|.l] <size> */
1591 do_res (idx, in, type)
1599 idx = get_opsize (idx, in, &size);
1600 while (!eol(idx, in))
1602 idx = sb_skip_white (idx, in);
1603 if (in->ptr[idx] == ',')
1605 idx = exp_get_abs ("res needs absolute expression for fill count.\n", idx, in, &count);
1607 if (type == 'c' || type == 'z')
1610 fprintf (outfile, ".space %d\n", count * size);
1621 fprintf (outfile, ".global %s\n", sb_name (in));
1624 /* .print [list] [nolist] */
1631 idx = sb_skip_white (idx, in);
1632 while (idx < in->len)
1634 if (strncmp (in->ptr + idx, "LIST", 4) == 0)
1636 fprintf (outfile, ".list\n");
1639 else if (strncmp (in->ptr + idx, "NOLIST", 6) == 0)
1641 fprintf (outfile, ".nolist\n");
1650 do_heading (idx, in)
1656 idx = getstring (idx, in, &head);
1657 fprintf (outfile, ".title \"%s\"\n", sb_name (&head));
1666 fprintf (outfile, ".eject\n");
1669 /* .form [lin=<value>] [col=<value>] */
1677 idx = sb_skip_white (idx, in);
1679 while (idx < in->len)
1682 if (strncmp (in->ptr + idx, "LIN=", 4) == 0)
1685 idx = exp_get_abs ("form LIN= needs absolute expresssion.\n", idx, in, &lines);
1688 if (strncmp (in->ptr + idx, "COL=", 4) == 0)
1691 idx = exp_get_abs ("form COL= needs absolute expresssion.\n", idx, in, &columns);
1696 fprintf (outfile, ".psize %d,%d\n", lines, columns);
1701 get_any_string (idx, in, out)
1707 idx = sb_skip_white (idx, in);
1712 if (in->ptr[idx] == '%'
1717 /* Turns the next expression into a string */
1718 idx = exp_get_abs ("% operator needs absolute expression",
1722 sprintf(buf, "\"%d\"", val);
1723 sb_add_string (out, buf);
1725 else if (in->ptr[idx] == '"'
1726 || in->ptr[idx] == '<'
1727 || (alternate && in->ptr[idx] == '\''))
1731 /* Keep the quotes */
1732 sb_add_char (out, '\"');
1733 idx = getstring (idx, in, out);
1734 sb_add_char (out, '\"');
1738 idx = getstring (idx, in, out);
1743 while (idx < in->len
1744 && (in->ptr[idx] == '"'
1745 || in->ptr[idx] == '\''
1746 || !ISSEP (in->ptr[idx])))
1748 if (in->ptr[idx] == '"'
1749 || in->ptr[idx] == '\'')
1751 char tchar = in->ptr[idx];
1752 sb_add_char (out, in->ptr[idx++]);
1753 while (idx < in->len
1754 && in->ptr[idx] != tchar)
1755 sb_add_char (out, in->ptr[idx++]);
1757 sb_add_char (out, in->ptr[idx++]);
1766 /* skip along sb in starting at idx, suck off whitespace a ( and more
1767 whitespace. return the idx of the next char */
1770 skip_openp (idx, in)
1774 idx = sb_skip_white (idx, in);
1775 if (in->ptr[idx] != '(')
1776 ERROR ((stderr, "misplaced ( .\n"));
1777 idx = sb_skip_white (idx + 1, in);
1781 /* skip along sb in starting at idx, suck off whitespace a ) and more
1782 whitespace. return the idx of the next char */
1785 skip_closep (idx, in)
1789 idx = sb_skip_white (idx, in);
1790 if (in->ptr[idx] != ')')
1791 ERROR ((stderr, "misplaced ).\n"));
1792 idx = sb_skip_white (idx + 1, in);
1799 dolen (idx, in, out)
1808 sb_new (&stringout);
1809 idx = skip_openp (idx, in);
1810 idx = get_and_process (idx, in, &stringout);
1811 idx = skip_closep (idx, in);
1812 sprintf (buffer, "%d", stringout.len);
1813 sb_add_string (out, buffer);
1815 sb_kill (&stringout);
1824 doinstr (idx, in, out)
1838 idx = skip_openp (idx, in);
1839 idx = get_and_process (idx, in, &string);
1840 idx = sb_skip_comma (idx, in);
1841 idx = get_and_process (idx, in, &search);
1842 idx = sb_skip_comma (idx, in);
1843 if (isdigit (in->ptr[idx]))
1845 idx = exp_get_abs (".instr needs absolute expresson.\n", idx, in, &start);
1851 idx = skip_closep (idx, in);
1853 for (i = start; i < string.len; i++)
1855 if (strncmp (string.ptr + i, search.ptr, search.len) == 0)
1861 sprintf (buffer, "%d", res);
1862 sb_add_string (out, buffer);
1870 dosubstr (idx, in, out)
1880 idx = skip_openp (idx, in);
1881 idx = get_and_process (idx, in, &string);
1882 idx = sb_skip_comma (idx, in);
1883 idx = exp_get_abs ("need absolute position.\n", idx, in, &pos);
1884 idx = sb_skip_comma (idx, in);
1885 idx = exp_get_abs ("need absolute length.\n", idx, in, &len);
1886 idx = skip_closep (idx, in);
1889 if (len < 0 || pos < 0 ||
1891 || pos + len > string.len)
1893 sb_add_string (out, " ");
1897 sb_add_char (out, '"');
1900 sb_add_char (out, string.ptr[pos++]);
1903 sb_add_char (out, '"');
1909 /* scan line, change tokens in the hash table to their replacements */
1911 process_assigns (idx, in, buf)
1916 while (idx < in->len)
1919 if (in->ptr[idx] == '\\'
1920 && in->ptr[idx + 1] == '&')
1922 idx = condass_lookup_name (in, idx + 2, buf, 1);
1924 else if (in->ptr[idx] == '\\'
1925 && in->ptr[idx + 1] == '$')
1927 idx = condass_lookup_name (in, idx + 2, buf, 0);
1929 else if (idx + 3 < in->len
1930 && in->ptr[idx] == '.'
1931 && in->ptr[idx + 1] == 'L'
1932 && in->ptr[idx + 2] == 'E'
1933 && in->ptr[idx + 3] == 'N')
1934 idx = dolen (idx + 4, in, buf);
1935 else if (idx + 6 < in->len
1936 && in->ptr[idx] == '.'
1937 && in->ptr[idx + 1] == 'I'
1938 && in->ptr[idx + 2] == 'N'
1939 && in->ptr[idx + 3] == 'S'
1940 && in->ptr[idx + 4] == 'T'
1941 && in->ptr[idx + 5] == 'R')
1942 idx = doinstr (idx + 6, in, buf);
1943 else if (idx + 7 < in->len
1944 && in->ptr[idx] == '.'
1945 && in->ptr[idx + 1] == 'S'
1946 && in->ptr[idx + 2] == 'U'
1947 && in->ptr[idx + 3] == 'B'
1948 && in->ptr[idx + 4] == 'S'
1949 && in->ptr[idx + 5] == 'T'
1950 && in->ptr[idx + 6] == 'R')
1951 idx = dosubstr (idx + 7, in, buf);
1952 else if (ISFIRSTCHAR (in->ptr[idx]))
1954 /* may be a simple name subsitution, see if we have a word */
1957 while (cur < in->len
1958 && (ISNEXTCHAR (in->ptr[cur])))
1962 sb_add_buffer (&acc, in->ptr + idx, cur - idx);
1963 ptr = hash_lookup (&assign_hash_table, &acc);
1966 /* Found a definition for it */
1967 sb_add_sb (buf, &ptr->value.s);
1971 /* No definition, just copy the word */
1972 sb_add_sb (buf, &acc);
1979 sb_add_char (buf, in->ptr[idx++]);
1985 get_and_process (idx, in, out)
1992 idx = get_any_string (idx, in, &t);
1993 process_assigns (0, &t, out);
2014 more = get_line (&line);
2017 /* Find any label and pseudo op that we're intested in */
2022 fprintf (outfile, "\n");
2026 l = grab_label (&line, &label_in);
2030 /* Munge any label */
2033 process_assigns (0, &label_in, &label);
2036 if (line.ptr[l] == ':')
2038 while (ISWHITE (line.ptr[l]) && l < line.len)
2043 if (process_pseudo_op (l, &line, &acc))
2049 else if (condass_on ())
2051 if (macro_op (l, &line))
2061 fprintf (outfile, "%s:\t", sb_name (&label));
2064 fprintf (outfile, "\t");
2066 process_assigns (l, &line, &t1);
2068 change_base (0, &t1, &t2);
2069 fprintf (outfile, "%s\n", sb_name (&t2));
2075 /* Only a label on this line */
2076 if (label.len && condass_on())
2078 fprintf (outfile, "%s:\n", sb_name (&label));
2086 more = get_line (&line);
2090 WARNING ((stderr, "END missing from end of file.\n"));
2098 free_old_entry (ptr)
2103 if (ptr->type == hash_string)
2104 sb_kill(&ptr->value.s);
2108 /* name: .ASSIGNA <value> */
2111 do_assigna (idx, in)
2119 process_assigns (idx, in, &tmp);
2120 idx = exp_get_abs (".ASSIGNA needs constant expression argument.\n", 0, &tmp, &val);
2124 ERROR ((stderr, ".ASSIGNA without label.\n"));
2128 hash_entry *ptr = hash_create (&vars, &label);
2129 free_old_entry (ptr);
2130 ptr->type = hash_integer;
2136 /* name: .ASSIGNC <string> */
2139 do_assignc (idx, in)
2145 idx = getstring (idx, in, &acc);
2149 ERROR ((stderr, ".ASSIGNS without label.\n"));
2153 hash_entry *ptr = hash_create (&vars, &label);
2154 free_old_entry (ptr);
2155 ptr->type = hash_string;
2156 sb_new (&ptr->value.s);
2157 sb_add_sb (&ptr->value.s, &acc);
2163 /* name: .REG (reg) */
2170 /* remove reg stuff from inside parens */
2172 idx = skip_openp (idx, in);
2174 while (idx < in->len && in->ptr[idx] != ')')
2176 sb_add_char (&what, in->ptr[idx]);
2179 hash_add_to_string_table (&assign_hash_table, &label, &what, 1);
2185 condass_lookup_name (inbuf, idx, out, warn)
2193 sb_new (&condass_acc);
2195 while (idx < inbuf->len
2196 && ISNEXTCHAR (inbuf->ptr[idx]))
2198 sb_add_char (&condass_acc, inbuf->ptr[idx++]);
2201 if (inbuf->ptr[idx] == '\'')
2203 ptr = hash_lookup (&vars, &condass_acc);
2210 WARNING ((stderr, "Can't find preprocessor variable %s.\n", sb_name (&condass_acc)));
2214 sb_add_string (out, "0");
2219 if (ptr->type == hash_integer)
2222 sprintf (buffer, "%d", ptr->value.i);
2223 sb_add_string (out, buffer);
2227 sb_add_sb (out, &ptr->value.s);
2230 sb_kill (&condass_acc);
2243 whatcond (idx, in, val)
2250 idx = sb_skip_white (idx, in);
2252 if (p[0] == 'E' && p[1] == 'Q')
2254 else if (p[0] == 'N' && p[1] == 'E')
2256 else if (p[0] == 'L' && p[1] == 'T')
2258 else if (p[0] == 'L' && p[1] == 'E')
2260 else if (p[0] == 'G' && p[1] == 'T')
2262 else if (p[0] == 'G' && p[1] == 'E')
2266 ERROR ((stderr, "Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n"));
2269 idx = sb_skip_white (idx + 2, in);
2286 idx = sb_skip_white (idx, in);
2288 if (in->ptr[idx] == '"')
2292 /* This is a string comparision */
2293 idx = getstring (idx, in, &acc_a);
2294 idx = whatcond (idx, in, &cond);
2295 idx = getstring (idx, in, &acc_b);
2296 same = acc_a.len == acc_b.len && (strncmp (acc_a.ptr, acc_b.ptr, acc_a.len) == 0);
2298 if (cond != EQ && cond != NE)
2300 ERROR ((stderr, "Comparison operator for strings must be EQ or NE\n"));
2304 res = cond == EQ && same;
2307 /* This is a numeric expression */
2312 idx = exp_get_abs ("Conditional operator must have absolute operands.\n", idx, in, &vala);
2313 idx = whatcond (idx, in, &cond);
2314 idx = sb_skip_white (idx, in);
2315 if (in->ptr[idx] == '"')
2317 WARNING ((stderr, "String compared against expression.\n"));
2322 idx = exp_get_abs ("Conditional operator must have absolute operands.\n", idx, in, &valb);
2362 if (ifi >= IFNESTING)
2364 FATAL ((stderr, "AIF nesting unreasonable.\n"));
2367 ifstack[ifi].on = istrue (idx, in);
2368 ifstack[ifi].hadelse = 0;
2376 ifstack[ifi].on = !ifstack[ifi].on;
2377 if (ifstack[ifi].hadelse)
2379 ERROR ((stderr, "Multiple AELSEs in AIF.\n"));
2381 ifstack[ifi].hadelse = 1;
2395 ERROR ((stderr, "AENDI without AIF.\n"));
2402 return ifstack[ifi].on;
2406 /* Read input lines till we get to a TO string.
2407 Increase nesting depth if we geta FROM string.
2408 Put the results into sb at PTR. */
2411 buffer_and_nest (from, to, ptr)
2416 int from_len = strlen (from);
2417 int to_len = strlen (to);
2419 int line_start = ptr->len;
2420 int line = linecount ();
2422 int more = get_line (ptr);
2426 /* Try and find the first pseudo op on the line */
2431 /* With normal syntax we can suck what we want till we get to the dot.
2432 With the alternate, labels have to start in the first column, since
2433 we cant tell what's a label and whats a pseudoop */
2435 /* Skip leading whitespace */
2437 && ISWHITE (ptr->ptr[i]))
2440 /* Skip over a label */
2442 && ISNEXTCHAR (ptr->ptr[i]))
2447 && ptr->ptr[i] == ':')
2451 /* Skip trailing whitespace */
2453 && ISWHITE (ptr->ptr[i]))
2456 if (i < ptr->len && (ptr->ptr[i] == '.'
2459 if (ptr->ptr[i] == '.')
2461 if (strncmp (ptr->ptr + i, from, from_len) == 0)
2463 if (strncmp (ptr->ptr + i, to, to_len) == 0)
2468 /* Reset the string to not include the ending rune */
2469 ptr->len = line_start;
2475 /* Add a CR to the end and keep running */
2476 sb_add_char (ptr, '\n');
2477 line_start = ptr->len;
2478 more = get_line (ptr);
2483 FATAL ((stderr, "End of file whilst inside %s, started on line %d.\n", from, line));
2491 ERROR ((stderr, "AENDR without a AREPEAT.\n"));
2510 process_assigns (idx, in, &exp);
2511 doit = istrue (0, &exp);
2513 buffer_and_nest ("AWHILE", "AENDW", &sub);
2528 int index = include_next_index ();
2532 sb_add_sb (©, &sub);
2533 sb_add_sb (©, in);
2534 sb_add_string (©, "\n");
2535 sb_add_sb (©, &sub);
2536 sb_add_string (©, "\t.AENDW\n");
2537 /* Push another WHILE */
2538 include_buf (&exp, ©, include_while, index);
2551 ERROR ((stderr, "AENDW without a AENDW.\n"));
2557 Pop things off the include stack until the type and index changes */
2562 include_type type = sp->type;
2563 if (type == include_repeat
2564 || type == include_while
2565 || type == include_macro)
2567 int index = sp->index;
2569 while (sp->index == index
2570 && sp->type == type)
2580 do_arepeat (idx, in)
2584 sb exp; /* buffer with expression in it */
2585 sb copy; /* expanded repeat block */
2586 sb sub; /* contents of AREPEAT */
2592 process_assigns (idx, in, &exp);
2593 idx = exp_get_abs ("AREPEAT must have absolute operand.\n", 0, &exp, &rc);
2594 buffer_and_nest ("AREPEAT", "AENDR", &sub);
2597 /* Push back the text following the repeat, and another repeat block
2608 int index = include_next_index ();
2609 sb_add_sb (©, &sub);
2612 sprintf (buffer, "\t.AREPEAT %d\n", rc - 1);
2613 sb_add_string (©, buffer);
2614 sb_add_sb (©, &sub);
2615 sb_add_string (©, " .AENDR\n");
2618 include_buf (&exp, ©, include_repeat, index);
2630 ERROR ((stderr, ".ENDM without a matching .MACRO.\n"));
2634 /* MARRO PROCESSING */
2637 hash_table macro_table;
2647 do_formals (macro, idx, in)
2652 formal_entry **p = ¯o->formals;
2653 macro->formal_count = 0;
2654 hash_new_table (5, ¯o->formal_hash);
2655 while (idx < in->len)
2657 formal_entry *formal;
2659 formal = (formal_entry *) xmalloc (sizeof (formal_entry));
2661 sb_new (&formal->name);
2662 sb_new (&formal->def);
2663 sb_new (&formal->actual);
2665 idx = sb_skip_white (idx, in);
2666 idx = get_token (idx, in, &formal->name);
2667 if (formal->name.len == 0)
2669 idx = sb_skip_white (idx, in);
2670 if (formal->name.len)
2672 /* This is a formal */
2673 if (idx < in->len && in->ptr[idx] == '=')
2676 idx = get_any_string (idx + 1, in, &formal->def);
2681 /* Add to macro's hash table */
2683 hash_entry *p = hash_create (¯o->formal_hash, &formal->name);
2684 p->type = hash_formal;
2685 p->value.f = formal;
2688 formal->index = macro->formal_count;
2689 idx = sb_skip_comma (idx, in);
2690 macro->formal_count++;
2697 /* Parse off LOCAL n1, n2,... Invent a label name for it */
2700 do_local (idx, line)
2710 idx = sb_skip_white (idx, line);
2711 while (!eol(idx, line))
2716 sprintf(subs, "LL%04x", ln);
2717 idx = get_token(idx, line, &acc);
2718 sb_add_string (&sub, subs);
2719 hash_add_to_string_table (&assign_hash_table, &acc, &sub, 1);
2720 idx = sb_skip_comma (idx, line);
2735 macro = (macro_entry *) xmalloc (sizeof (macro_entry));
2736 sb_new (¯o->sub);
2739 macro->formal_count = 0;
2742 idx = sb_skip_white (idx, in);
2743 buffer_and_nest ("MACRO", "ENDM", ¯o->sub);
2747 sb_add_sb (&name, &label);
2748 if (in->ptr[idx] == '(')
2750 /* It's the label: MACRO (formals,...) sort */
2751 idx = do_formals (macro, idx + 1, in);
2752 if (in->ptr[idx] != ')')
2753 ERROR ((stderr, "Missing ) after formals.\n"));
2756 /* It's the label: MACRO formals,... sort */
2757 idx = do_formals (macro, idx, in);
2762 idx = get_token (idx, in, &name);
2763 idx = sb_skip_white (idx, in);
2764 idx = do_formals (macro, idx, in);
2767 /* and stick it in the macro hash table */
2768 hash_create (¯o_table, &name)->value.m = macro;
2773 get_token (idx, in, name)
2779 && ISFIRSTCHAR (in->ptr[idx]))
2781 sb_add_char (name, in->ptr[idx++]);
2782 while (idx < in->len
2783 && ISNEXTCHAR (in->ptr[idx]))
2785 sb_add_char (name, in->ptr[idx++]);
2791 /* Scan a token, but stop if a ' is seen */
2793 get_apost_token (idx, in, name, kind)
2799 idx = get_token (idx, in, name);
2800 if (idx < in->len && in->ptr[idx] == kind)
2806 sub_actual (src, in, t, m, kind, out, copyifnotthere)
2815 /* This is something to take care of */
2817 src = get_apost_token (src, in, t, kind);
2818 /* See if it's in the macro's hash table */
2819 ptr = hash_lookup (&m->formal_hash, t);
2822 if (ptr->value.f->actual.len)
2824 sb_add_sb (out, &ptr->value.f->actual);
2828 sb_add_sb (out, &ptr->value.f->def);
2831 else if (copyifnotthere)
2837 sb_add_char (out, '\\');
2845 macro_expand (name, idx, in, m)
2855 int is_positional = 0;
2861 /* Reset any old value the actuals may have */
2862 for (f = m->formals; f; f = f->next)
2863 sb_reset (&f->actual);
2865 /* Peel off the actuals and store them away in the hash tables' actuals */
2866 while (!eol(idx, in))
2869 idx = sb_skip_white (idx, in);
2870 /* Look and see if it's a positional or keyword arg */
2872 while (scan < in->len
2873 && !ISSEP (in->ptr[scan])
2874 && in->ptr[scan] != '=')
2876 if (scan < in->len && in->ptr[scan] == '=')
2881 ERROR ((stderr, "Can't mix positional and keyword arguments.\n"));
2884 /* This is a keyword arg, fetch the formal name and
2885 then the actual stuff */
2887 idx = get_token (idx, in, &t);
2888 if (in->ptr[idx] != '=')
2889 ERROR ((stderr, "confused about formal params.\n"));
2891 /* Lookup the formal in the macro's list */
2892 ptr = hash_lookup (&m->formal_hash, &t);
2895 ERROR ((stderr, "MACRO formal argument %s does not exist.\n", sb_name (&t)));
2900 /* Insert this value into the right place */
2901 sb_reset (&ptr->value.f->actual);
2902 idx = get_any_string (idx + 1, in, &ptr->value.f->actual);
2907 /* This is a positional arg */
2911 ERROR ((stderr, "Can't mix positional and keyword arguments.\n"));
2916 ERROR ((stderr, "Too many positional arguments.\n"));
2920 sb_reset (&f->actual);
2921 idx = get_any_string (idx, in, &f->actual);
2924 idx = sb_skip_comma (idx, in);
2927 /* Copy the stuff from the macro buffer into a safe place and substitute any args */
2935 while (src < in->len)
2937 if (in->ptr[src] == '&')
2940 src = sub_actual (src + 1, in, &t, m, '&', &out, 0);
2942 else if (in->ptr[src] == '\\')
2945 if (in->ptr[src] == comment_char)
2947 /* This is a comment, just drop the rest of the line */
2948 while (src < in->len
2949 && in->ptr[src] != '\n')
2953 else if (in->ptr[src] == '(')
2955 /* Sub in till the next ')' literally */
2957 while (src < in->len && in->ptr[src] != ')')
2959 sb_add_char (&out, in->ptr[src++]);
2961 if (in->ptr[src] == ')')
2964 ERROR ((stderr, "Missplaced ).\n"));
2966 else if (in->ptr[src] == '@')
2968 /* Sub in the macro invocation number */
2972 sprintf (buffer, "%05d", number);
2973 sb_add_string (&out, buffer);
2975 else if (in->ptr[src] == '&')
2977 /* This is a preprocessor variable name, we don't do them
2979 sb_add_char (&out, '\\');
2980 sb_add_char (&out, '&');
2986 src = sub_actual (src, in, &t, m, '\'', &out, 0);
2989 else if (ISFIRSTCHAR (in->ptr[src]) && alternate)
2992 src = sub_actual (src, in, &t, m, '\'', &out, 1);
2994 else if (ISCOMMENTCHAR (in->ptr[src])
2995 && src + 1 < in->len
2996 && ISCOMMENTCHAR (in->ptr[src+1])
2999 /* Two comment chars in a row cause the rest of the line to be dropped */
3000 while (src < in->len && in->ptr[src] != '\n')
3003 else if (in->ptr[src] == '"')
3006 sb_add_char (&out, in->ptr[src++]);
3010 sb_add_char (&out, in->ptr[src++]);
3013 include_buf (name, &out, include_macro, include_next_index ());
3026 /* The macro name must be the first thing on the line */
3032 idx = get_token (idx, in, &name);
3036 /* Got a name, look it up */
3038 ptr = hash_lookup (¯o_table, &name);
3042 /* It's in the table, copy out the stuff and convert any macro args */
3043 macro_expand (&name, idx, in, ptr->value.m);
3055 /* STRING HANDLING */
3058 getstring (idx, in, acc)
3063 idx = sb_skip_white (idx, in);
3065 while (idx < in->len
3066 && (in->ptr[idx] == '"'
3067 || in->ptr[idx] == '<'
3068 || (in->ptr[idx] == '\'' && alternate)))
3070 if (in->ptr[idx] == '<')
3076 while ((in->ptr[idx] != '>' || nest)
3079 if (in->ptr[idx] == '!')
3082 sb_add_char (acc, in->ptr[idx++]);
3085 if (in->ptr[idx] == '>')
3087 if (in->ptr[idx] == '<')
3089 sb_add_char (acc, in->ptr[idx++]);
3097 idx = exp_get_abs ("Character code in string must be absolute expression.\n",
3099 sb_add_char (acc, code);
3101 if (in->ptr[idx] != '>')
3102 ERROR ((stderr, "Missing > for character code.\n"));
3106 else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
3108 char tchar = in->ptr[idx];
3110 while (idx < in->len)
3112 if (alternate && in->ptr[idx] == '!')
3115 sb_add_char (acc, in->ptr[idx++]);
3118 if (in->ptr[idx] == tchar)
3121 if (idx >= in->len || in->ptr[idx] != tchar)
3124 sb_add_char (acc, in->ptr[idx]);
3134 /* .SDATA[C|Z] <string> */
3138 do_sdata (idx, in, type)
3147 fprintf (outfile, ".byte\t");
3149 while (!eol (idx, in))
3153 idx = sb_skip_white (idx, in);
3154 while (!eol (idx, in))
3156 pidx = idx = get_any_string (idx, in, &acc);
3161 ERROR ((stderr, "string for SDATAC longer than 255 characters (%d).\n", acc.len));
3163 fprintf (outfile, "%d", acc.len);
3167 for (i = 0; i < acc.len; i++)
3171 fprintf (outfile, ",");
3173 fprintf (outfile, "%d", acc.ptr[i]);
3180 fprintf (outfile, ",");
3181 fprintf (outfile, "0");
3183 idx = sb_skip_comma (idx, in);
3184 if (idx == pidx) break;
3186 if (!alternate && in->ptr[idx] != ',' && idx != in->len)
3188 fprintf (outfile, "\n");
3189 ERROR ((stderr, "illegal character in SDATA line (0x%x).\n", in->ptr[idx]));
3195 fprintf (outfile, "\n");
3198 /* .SDATAB <count> <string> */
3210 idx = exp_get_abs ("Must have absolute SDATAB repeat count.\n", idx, in, &repeat);
3213 ERROR ((stderr, "Must have positive SDATAB repeat count (%d).\n", repeat));
3217 idx = sb_skip_comma (idx, in);
3218 idx = getstring (idx, in, &acc);
3220 for (i = 0; i < repeat; i++)
3223 fprintf (outfile, "\t");
3224 fprintf (outfile, ".byte\t");
3226 fprintf (outfile, "\n");
3236 FILE *newone = fopen (name, "r");
3240 if (isp == MAX_INCLUDES)
3241 FATAL ((stderr, "Unreasonable include depth (%d).\n", isp));
3244 sp->handle = newone;
3247 sb_add_string (&sp->name, name);
3250 sp->pushback_index = 0;
3251 sp->type = include_file;
3253 sb_new (&sp->pushback);
3258 do_include (idx, in)
3265 idx = getstring (idx, in, &t);
3266 text = sb_name (&t);
3267 if (!new_file (text))
3269 FATAL ((stderr, "Can't open include file `%s'.\n", text));
3277 if (sp != include_stack)
3280 fclose (sp->handle);
3285 /* Get the next character from the include stack. If there's anything
3286 in the pushback buffer, take that first. If we're at eof, pop from
3287 the stack and try again. Keep the linecount up to date. */
3294 if (sp->pushback.len != sp->pushback_index)
3296 r = (char) (sp->pushback.ptr[sp->pushback_index++]);
3297 /* When they've all gone, reset the pointer */
3298 if (sp->pushback_index == sp->pushback.len)
3300 sp->pushback.len = 0;
3301 sp->pushback_index = 0;
3304 else if (sp->handle)
3306 r = getc (sp->handle);
3311 if (r == EOF && isp)
3315 while (r == EOF && isp)
3333 return sp->linecount;
3337 include_next_index ()
3341 && index > MAX_REASONABLE)
3342 FATAL ((stderr, "Unreasonable expansion (-u turns off check).\n"));
3347 /* Initialize the chartype vector. */
3353 for (x = 0; x < 256; x++)
3355 if (isalpha (x) || x == '_' || x == '$')
3356 chartype[x] |= FIRSTBIT;
3358 if (isdigit (x) || isalpha (x) || x == '_' || x == '$')
3359 chartype[x] |= NEXTBIT;
3361 if (x == ' ' || x == '\t' || x == ',' || x == '"' || x == ';'
3362 || x == '"' || x == '<' || x == '>' || x == ')' || x == '(')
3363 chartype[x] |= SEPBIT;
3365 if (x == ' ' || x == '\t')
3366 chartype[x] |= WHITEBIT;
3368 if (x == comment_char)
3369 chartype[x] |= COMMENTBIT;
3375 /* What to do with all the keywords */
3376 #define PROCESS 0x1000 /* Run substitution over the line */
3377 #define LAB 0x2000 /* Spit out the label */
3379 #define K_EQU PROCESS|1
3380 #define K_ASSIGN PROCESS|2
3381 #define K_REG PROCESS|3
3382 #define K_ORG PROCESS|4
3383 #define K_RADIX PROCESS|5
3384 #define K_DATA LAB|PROCESS|6
3385 #define K_DATAB LAB|PROCESS|7
3386 #define K_SDATA LAB|PROCESS|8
3387 #define K_SDATAB LAB|PROCESS|9
3388 #define K_SDATAC LAB|PROCESS|10
3389 #define K_SDATAZ LAB|PROCESS|11
3390 #define K_RES LAB|PROCESS|12
3391 #define K_SRES LAB|PROCESS|13
3392 #define K_SRESC LAB|PROCESS|14
3393 #define K_SRESZ LAB|PROCESS|15
3394 #define K_EXPORT LAB|PROCESS|16
3395 #define K_GLOBAL LAB|PROCESS|17
3396 #define K_PRINT LAB|PROCESS|19
3397 #define K_FORM LAB|PROCESS|20
3398 #define K_HEADING LAB|PROCESS|21
3399 #define K_PAGE LAB|PROCESS|22
3400 #define K_IMPORT LAB|PROCESS|23
3401 #define K_PROGRAM LAB|PROCESS|24
3402 #define K_END PROCESS|25
3403 #define K_INCLUDE PROCESS|26
3404 #define K_IGNORED PROCESS|27
3405 #define K_ASSIGNA PROCESS|28
3406 #define K_ASSIGNC 29
3407 #define K_AIF PROCESS|30
3408 #define K_AELSE PROCESS|31
3409 #define K_AENDI PROCESS|32
3410 #define K_AREPEAT PROCESS|33
3411 #define K_AENDR PROCESS|34
3413 #define K_AENDW PROCESS|36
3415 #define K_MACRO PROCESS|38
3417 #define K_ALIGN PROCESS|LAB|40
3418 #define K_ALTERNATE 41
3419 #define K_DB LAB|PROCESS|42
3420 #define K_DW LAB|PROCESS|43
3421 #define K_DL LAB|PROCESS|44
3433 { "EQU", K_EQU, 0 },
3434 { "ALTERNATE", K_ALTERNATE, 0 },
3435 { "ASSIGN", K_ASSIGN, 0 },
3436 { "REG", K_REG, 0 },
3437 { "ORG", K_ORG, 0 },
3438 { "RADIX", K_RADIX, 0 },
3439 { "DATA", K_DATA, 0 },
3443 { "DATAB", K_DATAB, 0 },
3444 { "SDATA", K_SDATA, 0 },
3445 { "SDATAB", K_SDATAB, 0 },
3446 { "SDATAZ", K_SDATAZ, 0 },
3447 { "SDATAC", K_SDATAC, 0 },
3448 { "RES", K_RES, 0 },
3449 { "SRES", K_SRES, 0 },
3450 { "SRESC", K_SRESC, 0 },
3451 { "SRESZ", K_SRESZ, 0 },
3452 { "EXPORT", K_EXPORT, 0 },
3453 { "GLOBAL", K_GLOBAL, 0 },
3454 { "PRINT", K_PRINT, 0 },
3455 { "FORM", K_FORM, 0 },
3456 { "HEADING", K_HEADING, 0 },
3457 { "PAGE", K_PAGE, 0 },
3458 { "PROGRAM", K_IGNORED, 0 },
3459 { "END", K_END, 0 },
3460 { "INCLUDE", K_INCLUDE, 0 },
3461 { "ASSIGNA", K_ASSIGNA, 0 },
3462 { "ASSIGNC", K_ASSIGNC, 0 },
3463 { "AIF", K_AIF, 0 },
3464 { "AELSE", K_AELSE, 0 },
3465 { "AENDI", K_AENDI, 0 },
3466 { "AREPEAT", K_AREPEAT, 0 },
3467 { "AENDR", K_AENDR, 0 },
3468 { "EXITM", K_EXITM, 0 },
3469 { "MACRO", K_MACRO, 0 },
3470 { "ENDM", K_ENDM, 0 },
3471 { "AWHILE", K_AWHILE, 0 },
3472 { "ALIGN", K_ALIGN, 0 },
3473 { "AENDW", K_AENDW, 0 },
3474 { "ALTERNATE", K_ALTERNATE, 0 },
3475 { "LOCAL", K_LOCAL, 0 },
3479 /* Look for a pseudo op on the line. If one's there then call
3483 process_pseudo_op (idx, line, acc)
3490 if (line->ptr[idx] == '.' || alternate)
3492 /* Scan forward and find pseudo name */
3498 if (line->ptr[idx] == '.')
3500 in = line->ptr + idx;
3505 while (idx < line->len && *e && ISFIRSTCHAR (*e))
3507 sb_add_char (acc, *e);
3512 ptr = hash_lookup (&keyword_hash_table, acc);
3517 /* This one causes lots of pain when trying to preprocess
3519 WARNING ((stderr, "Unrecognised pseudo op `%s'.\n", sb_name (acc)));
3523 if (ptr->value.i & LAB)
3524 { /* output the label */
3527 fprintf (outfile, "%s:\t", sb_name (&label));
3530 fprintf (outfile, "\t");
3533 if (ptr->value.i & PROCESS)
3535 /* Polish the rest of the line before handling the pseudo op */
3537 strip_comments(line);
3540 process_assigns (idx, line, acc);
3542 change_base (0, acc, line);
3547 switch (ptr->value.i)
3560 switch (ptr->value.i)
3572 ERROR ((stderr, "ORG command not allowed.\n"));
3578 do_data (idx, line, 1);
3581 do_data (idx, line, 2);
3584 do_data (idx, line, 4);
3587 do_data (idx, line, 0);
3590 do_datab (idx, line);
3593 do_sdata (idx, line, 0);
3596 do_sdatab (idx, line);
3599 do_sdata (idx, line, 'c');
3602 do_sdata (idx, line, 'z');
3605 do_assign (1, 0, line);
3611 do_arepeat (idx, line);
3617 do_awhile (idx, line);
3623 do_assign (0, idx, line);
3626 do_align (idx, line);
3629 do_res (idx, line, 0);
3632 do_res (idx, line, 's');
3635 do_include (idx, line);
3638 do_local (idx, line);
3641 do_macro (idx, line);
3647 do_res (idx, line, 'c');
3650 do_print (idx, line);
3653 do_form (idx, line);
3656 do_heading (idx, line);
3668 do_res (idx, line, 'z');
3676 do_assigna (idx, line);
3679 do_assignc (idx, line);
3695 /* Build the keyword hash table - put each keyword in the table twice,
3696 once upper and once lower case.*/
3703 for (i = 0; kinfo[i].name; i++)
3708 sb_add_string (&label, kinfo[i].name);
3710 hash_add_to_int_table (&keyword_hash_table, &label, kinfo[i].code);
3713 for (j = 0; kinfo[i].name[j]; j++)
3714 sb_add_char (&label, kinfo[i].name[j] - 'A' + 'a');
3715 hash_add_to_int_table (&keyword_hash_table, &label, kinfo[i].code);
3741 sb_add_char (&value, *string);
3744 exp_get_abs ("Invalid expression on command line.\n", 0, &value, &res);
3748 sb_add_char (&label, *string);
3753 ptr = hash_create (&vars, &label);
3754 free_old_entry (ptr);
3755 ptr->type = hash_integer;
3761 /* The list of long options. */
3762 static struct option long_options[] =
3764 { "alternate", no_argument, 0, 'a' },
3765 { "commentchar", required_argument, 0, 'c' },
3766 { "copysource", no_argument, 0, 's' },
3767 { "debug", no_argument, 0, 'd' },
3768 { "help", no_argument, 0, 'h' },
3769 { "output", required_argument, 0, 'o' },
3770 { "print", no_argument, 0, 'p' },
3771 { "unreasonable", no_argument, 0, 'u' },
3772 { "version", no_argument, 0, 'v' },
3773 { "define", required_argument, 0, 'd' },
3774 { NULL, no_argument, 0, 0 }
3777 /* Show a usage message and exit. */
3779 show_usage (file, status)
3785 [-a] [--alternate] enter alternate macro mode\n\
3786 [-c char] [--commentchar char] change the comment character from !\n\
3787 [-d] [--debug] print some debugging info\n\
3788 [-h] [--help] print this message\n\
3789 [-o out] [--output out] set the output file\n\
3790 [-p] [--print] print line numbers\n\
3791 [-s] [--copysource] copy source through as comments \n\
3792 [-u] [--unreasonable] allow unreasonable nesting\n\
3793 [-v] [--version] print the program version\n\
3794 [-Dname=value] create preprocessor variable called name, with value\n\
3795 [in-file]\n", program_name);
3799 /* Display a help message and exit. */
3803 printf ("%s: Gnu Assembler Macro Preprocessor\n",
3805 show_usage (stdout, 0);
3822 program_name = argv[0];
3823 xmalloc_set_program_name (program_name);
3825 hash_new_table (101, ¯o_table);
3826 hash_new_table (101, &keyword_hash_table);
3827 hash_new_table (101, &assign_hash_table);
3828 hash_new_table (101, &vars);
3833 while ((opt = getopt_long (argc, argv, "sdhavc:upo:D:", long_options,
3846 print_line_number = 1;
3849 comment_char = optarg[0];
3867 printf ("GNU %s version %s\n", program_name, program_version);
3873 show_usage (stderr, 1);
3880 outfile = fopen (out_name, "w");
3883 fprintf (stderr, "%s: Can't open output file `%s'.\n",
3884 program_name, out_name);
3896 /* Process all the input files */
3898 while (optind < argc)
3900 if (new_file (argv[optind]))
3906 fprintf (stderr, "%s: Can't open input file `%s'.\n",
3907 program_name, argv[optind]);