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 *)));
587 /* calculate and return the hash value of the sb at key. */
596 for (i = 0; i < key->len; i++)
604 /* lookup key in hash_table tab, if present, then return it, otherwise
605 build a new one and fill it with hash_integer. */
609 hash_create (tab, key)
613 int k = hash (key) % tab->size;
615 hash_entry **table = tab->table;
623 hash_entry *n = (hash_entry *) xmalloc (sizeof (hash_entry));
626 sb_add_sb (&n->key, key);
628 n->type = hash_integer;
631 if (strncmp (table[k]->key.ptr, key->ptr, key->len) == 0)
639 /* add sb name with key into hash_table tab. if replacing old value
640 and again, then ERROR. */
644 hash_add_to_string_table (tab, key, name, again)
650 hash_entry *ptr = hash_create (tab, key);
651 if (ptr->type == hash_integer)
653 sb_new (&ptr->value.s);
655 if (ptr->value.s.len)
658 ERROR ((stderr, "redefintion not allowed"));
661 ptr->type = hash_string;
662 sb_reset (&ptr->value.s);
664 sb_add_sb (&ptr->value.s, name);
667 /* add integer name to hash_table tab with sb key. */
671 hash_add_to_int_table (tab, key, name)
676 hash_entry *ptr = hash_create (tab, key);
680 /* lookup sb key in hash_table tab. if found return hash_entry result,
685 hash_lookup (tab, key)
689 int k = hash (key) % tab->size;
690 hash_entry **table = tab->table;
691 hash_entry *p = table[k];
694 if (p->key.len == key->len
695 && strncmp (p->key.ptr, key->ptr, key->len) == 0)
705 are handled in a really simple recursive decent way. each bit of
706 the machine takes an index into an sb and a pointer to an exp_t,
707 modifies the *exp_t and returns the index of the first character
708 past the part of the expression parsed.
710 expression precedence:
721 /* make sure that the exp_t at term is constant, if not the give the op ERROR. */
725 checkconst (op, term)
729 if (term->add_symbol.len
730 || term->sub_symbol.len)
732 ERROR ((stderr, "the %c operator cannot take non-absolute arguments.\n", op));
736 /* turn the number in string at idx into a number of base,
737 fill in ptr and return the index of the first character not in the
742 sb_strtol (idx, string, base, ptr)
749 idx = sb_skip_white (idx, string);
751 while (idx < string->len)
753 int ch = string->ptr[idx];
757 else if (ch >= 'a' && ch <= 'f')
759 else if (ch >= 'A' && ch <= 'F')
767 value = value * base + dig;
774 static int level_5 ();
777 level_0 (idx, string, lhs)
782 lhs->add_symbol.len = 0;
783 lhs->add_symbol.name = 0;
785 lhs->sub_symbol.len = 0;
786 lhs->sub_symbol.name = 0;
788 idx = sb_skip_white (idx, string);
792 if (isdigit (string->ptr[idx]))
794 idx = sb_strtol (idx, string, 10, &lhs->value);
796 else if (ISFIRSTCHAR (string->ptr[idx]))
799 lhs->add_symbol.name = string->ptr + idx;
800 while (idx < string->len && ISNEXTCHAR (string->ptr[idx]))
805 lhs->add_symbol.len = len;
807 else if (string->ptr[idx] == '"')
811 ERROR ((stderr, "string where expression expected.\n"));
812 idx = getstring (idx, string, &acc);
817 ERROR ((stderr, "can't find primary in expression.\n"));
820 return sb_skip_white (idx, string);
826 level_1 (idx, string, lhs)
831 idx = sb_skip_white (idx, string);
833 switch (string->ptr[idx])
836 idx = level_1 (idx + 1, string, lhs);
839 idx = level_1 (idx + 1, string, lhs);
840 checkconst ('~', lhs);
841 lhs->value = ~lhs->value;
846 idx = level_1 (idx + 1, string, lhs);
847 lhs->value = -lhs->value;
849 lhs->add_symbol = lhs->sub_symbol;
855 idx = level_5 (sb_skip_white (idx, string), string, lhs);
856 if (string->ptr[idx] != ')')
857 ERROR ((stderr, "misplaced closing parens.\n"));
862 idx = level_0 (idx, string, lhs);
865 return sb_skip_white (idx, string);
869 level_2 (idx, string, lhs)
876 idx = level_1 (idx, string, lhs);
878 while (idx < string->len && (string->ptr[idx] == '*'
879 || string->ptr[idx] == '/'))
881 char op = string->ptr[idx++];
882 idx = level_1 (idx, string, &rhs);
886 checkconst ('*', lhs);
887 checkconst ('*', &rhs);
888 lhs->value *= rhs.value;
891 checkconst ('/', lhs);
892 checkconst ('/', &rhs);
894 ERROR ((stderr, "attempt to divide by zero.\n"));
896 lhs->value /= rhs.value;
900 return sb_skip_white (idx, string);
905 level_3 (idx, string, lhs)
912 idx = level_2 (idx, string, lhs);
914 while (idx < string->len
915 && (string->ptr[idx] == '+'
916 || string->ptr[idx] == '-'))
918 char op = string->ptr[idx++];
919 idx = level_2 (idx, string, &rhs);
923 lhs->value += rhs.value;
924 if (lhs->add_symbol.name && rhs.add_symbol.name)
926 ERROR ((stderr, "can't add two relocatable expressions\n"));
928 /* change nn+symbol to symbol + nn */
929 if (rhs.add_symbol.name)
931 lhs->add_symbol = rhs.add_symbol;
935 lhs->value -= rhs.value;
936 lhs->sub_symbol = rhs.add_symbol;
940 return sb_skip_white (idx, string);
944 level_4 (idx, string, lhs)
951 idx = level_3 (idx, string, lhs);
953 while (idx < string->len &&
954 string->ptr[idx] == '&')
956 char op = string->ptr[idx++];
957 idx = level_3 (idx, string, &rhs);
961 checkconst ('&', lhs);
962 checkconst ('&', &rhs);
963 lhs->value &= rhs.value;
967 return sb_skip_white (idx, string);
971 level_5 (idx, string, lhs)
978 idx = level_4 (idx, string, lhs);
980 while (idx < string->len
981 && (string->ptr[idx] == '|' || string->ptr[idx] == '~'))
983 char op = string->ptr[idx++];
984 idx = level_4 (idx, string, &rhs);
988 checkconst ('|', lhs);
989 checkconst ('|', &rhs);
990 lhs->value |= rhs.value;
993 checkconst ('~', lhs);
994 checkconst ('~', &rhs);
995 lhs->value ^= rhs.value;
999 return sb_skip_white (idx, string);
1003 /* parse the expression at offset idx into string, fill up res with
1004 the result. return the index of the first char past the expression.
1008 exp_parse (idx, string, res)
1013 return level_5 (sb_skip_white (idx, string), string, res);
1017 /* turn the expression at exp into text and glue it onto the end of
1021 exp_string (exp, string)
1029 if (exp->add_symbol.len)
1031 sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
1039 sb_add_char (string, '+');
1040 sprintf (buf, "%d", exp->value);
1041 sb_add_string (string, buf);
1045 if (exp->sub_symbol.len)
1047 sb_add_char (string, '-');
1048 sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
1054 sb_add_char (string, '0');
1058 /* parse the expression at offset idx into sb in, return the value in val.
1059 if the expression is not constant, give ERROR emsg. returns the index
1060 of the first character past the end of the expression. */
1063 exp_get_abs (emsg, idx, in, val)
1070 idx = exp_parse (idx, in, &res);
1071 if (res.add_symbol.len || res.sub_symbol.len)
1072 ERROR ((stderr, emsg));
1078 sb label; /* current label parsed from line */
1079 hash_table assign_hash_table; /* hash table for all assigned variables */
1080 hash_table keyword_hash_table; /* hash table for keyword */
1081 hash_table vars; /* hash table for eq variables */
1083 #define in_comment ';'
1087 strip_comments (out)
1092 for (i = 0; i < out->len; i++)
1094 if (ISCOMMENTCHAR(s[i]))
1103 /* push back character ch so that it can be read again. */
1113 if (sp->pushback_index)
1114 sp->pushback_index--;
1116 sb_add_char (&sp->pushback, ch);
1119 /* push the sb ptr onto the include stack, with the given name, type and index. */
1123 include_buf (name, ptr, type, index)
1130 if (sp - include_stack >= MAX_INCLUDES)
1131 FATAL ((stderr, "unreasonable nesting.\n"));
1133 sb_add_sb (&sp->name, name);
1136 sp->pushback_index = 0;
1139 sb_new (&sp->pushback);
1140 sb_add_sb (&sp->pushback, ptr);
1144 /* used in ERROR messages, print info on where the include stack is onto file. */
1147 include_print_where_line (file)
1150 struct include_stack *p = include_stack + 1;
1154 fprintf (file, "%s:%d ", sb_name (&p->name), p->linecount - ((p == sp) ? 1 : 0));
1159 /* used in listings, print the line number onto file. */
1161 include_print_line (file)
1165 struct include_stack *p = include_stack + 1;
1167 n = fprintf (file, "%4d", p->linecount);
1171 n += fprintf (file, ".%d", p->linecount);
1176 fprintf (file, " ");
1182 /* read a line from the top of the include stack into sb in. */
1193 putc (comment_char, outfile);
1194 if (print_line_number)
1195 include_print_line (outfile);
1209 WARNING ((stderr, "End of file not at start of line.\n"));
1211 putc ('\n', outfile);
1230 /* continued line */
1233 putc (comment_char, outfile);
1234 putc ('+', outfile);
1247 sb_add_char (in, ch);
1255 /* find a label from sb in and put it in out. */
1258 grab_label (in, out)
1264 if (ISFIRSTCHAR (in->ptr[i]))
1266 sb_add_char (out, in->ptr[i]);
1268 while ((ISNEXTCHAR (in->ptr[i])
1269 || in->ptr[i] == '\\'
1270 || in->ptr[i] == '&')
1273 sb_add_char (out, in->ptr[i]);
1280 /* find all strange base stuff and turn into decimal. also
1281 find all the other numbers and convert them from the default radix */
1284 change_base (idx, in, out)
1291 while (idx < in->len)
1293 if (idx < in->len - 1 && in->ptr[idx + 1] == '\'')
1297 switch (in->ptr[idx])
1316 ERROR ((stderr, "Illegal base character %c.\n", in->ptr[idx]));
1321 idx = sb_strtol (idx + 2, in, base, &value);
1322 sprintf (buffer, "%d", value);
1323 sb_add_string (out, buffer);
1325 else if (ISFIRSTCHAR (in->ptr[idx]))
1327 /* copy entire names through quickly */
1328 sb_add_char (out, in->ptr[idx]);
1330 while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
1332 sb_add_char (out, in->ptr[idx]);
1336 else if (isdigit (in->ptr[idx]))
1339 /* all numbers must start with a digit, let's chew it and
1341 idx = sb_strtol (idx, in, radix, &value);
1342 sprintf (buffer, "%d", value);
1343 sb_add_string (out, buffer);
1345 /* skip all undigsested letters */
1346 while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
1348 sb_add_char (out, in->ptr[idx]);
1354 /* nothing special, just pass it through */
1355 sb_add_char (out, in->ptr[idx]);
1372 do_assign (again, idx, in)
1377 /* stick label in symbol table with following value */
1382 idx = exp_parse (idx, in, &e);
1383 exp_string (&e, &acc);
1384 hash_add_to_string_table (&assign_hash_table, &label, &acc, again);
1389 /* .radix [b|q|d|h] */
1396 int idx = sb_skip_white (0, ptr);
1397 switch (ptr->ptr[idx])
1416 ERROR ((stderr, "radix is %c must be one of b, q, d or h", radix));
1421 /* Parse off a .b, .w or .l */
1424 get_opsize (idx, in, size)
1430 if (in->ptr[idx] == '.')
1434 switch (in->ptr[idx])
1452 ERROR ((stderr, "size must be one of b, w or l, is %c.\n", in->ptr[idx]));
1465 idx = sb_skip_white (idx, line);
1467 && ISCOMMENTCHAR(line->ptr[idx]))
1469 if (idx >= line->len)
1474 /* .data [.b|.w|.l] <data>*
1475 or d[bwl] <data>* */
1478 do_data (idx, in, size)
1490 idx = get_opsize (idx, in, &opsize);
1509 fprintf (outfile, "%s\t", opname);
1511 idx = sb_skip_white (idx, in);
1515 && in->ptr[idx] == '"')
1518 idx = getstring (idx, in, &acc);
1519 for (i = 0; i < acc.len; i++)
1522 fprintf(outfile,",");
1523 fprintf (outfile, "%d", acc.ptr[i]);
1528 while (!eol (idx, in))
1531 idx = exp_parse (idx, in, &e);
1532 exp_string (&e, &acc);
1533 sb_add_char (&acc, 0);
1534 fprintf (outfile, acc.ptr);
1535 if (idx < in->len && in->ptr[idx] == ',')
1537 fprintf (outfile, ",");
1543 sb_print_at (idx, in);
1544 fprintf (outfile, "\n");
1547 /* .datab [.b|.w|.l] <repeat>,<fill> */
1558 idx = get_opsize (idx, in, &opsize);
1560 idx = exp_get_abs ("datab repeat must be constant.\n", idx, in, &repeat);
1561 idx = sb_skip_comma (idx, in);
1562 idx = exp_get_abs ("datab data must be absolute.\n", idx, in, &fill);
1564 fprintf (outfile, ".fill\t%d,%d,%d\n", repeat, opsize, fill);
1575 idx = exp_get_abs ("align needs absolute expression.\n", idx, in, &al);
1580 WARNING ((stderr, "alignment must be one of 1, 2 or 4.\n"));
1582 fprintf (outfile, ".align %d\n", al);
1585 /* .res[.b|.w|.l] <size> */
1588 do_res (idx, in, type)
1596 idx = get_opsize (idx, in, &size);
1597 while (!eol(idx, in))
1599 idx = sb_skip_white (idx, in);
1600 if (in->ptr[idx] == ',')
1602 idx = exp_get_abs ("res needs absolute expression for fill count.\n", idx, in, &count);
1604 if (type == 'c' || type == 'z')
1607 fprintf (outfile, ".space %d\n", count * size);
1618 fprintf (outfile, ".global %s\n", sb_name (in));
1621 /* .print [list] [nolist] */
1628 idx = sb_skip_white (idx, in);
1629 while (idx < in->len)
1631 if (strncmp (in->ptr + idx, "LIST", 4) == 0)
1633 fprintf (outfile, ".list\n");
1636 else if (strncmp (in->ptr + idx, "NOLIST", 6) == 0)
1638 fprintf (outfile, ".nolist\n");
1647 do_heading (idx, in)
1653 idx = getstring (idx, in, &head);
1654 fprintf (outfile, ".title \"%s\"\n", sb_name (&head));
1663 fprintf (outfile, ".eject\n");
1666 /* .form [lin=<value>] [col=<value>] */
1674 idx = sb_skip_white (idx, in);
1676 while (idx < in->len)
1679 if (strncmp (in->ptr + idx, "LIN=", 4) == 0)
1682 idx = exp_get_abs ("form LIN= needs absolute expresssion.\n", idx, in, &lines);
1685 if (strncmp (in->ptr + idx, "COL=", 4) == 0)
1688 idx = exp_get_abs ("form COL= needs absolute expresssion.\n", idx, in, &columns);
1693 fprintf (outfile, ".psize %d,%d\n", lines, columns);
1698 get_any_string (idx, in, out)
1704 idx = sb_skip_white (idx, in);
1709 if (in->ptr[idx] == '%'
1714 /* Turns the next expression into a string */
1715 idx = exp_get_abs ("% operator needs absolute expression",
1719 sprintf(buf, "\"%d\"", val);
1720 sb_add_string (out, buf);
1722 else if (in->ptr[idx] == '"'
1723 || in->ptr[idx] == '<'
1724 || (alternate && in->ptr[idx] == '\''))
1728 /* Keep the quotes */
1729 sb_add_char (out, '\"');
1730 idx = getstring (idx, in, out);
1731 sb_add_char (out, '\"');
1735 idx = getstring (idx, in, out);
1740 while (idx < in->len
1741 && (in->ptr[idx] == '"'
1742 || in->ptr[idx] == '\''
1743 || !ISSEP (in->ptr[idx])))
1745 if (in->ptr[idx] == '"'
1746 || in->ptr[idx] == '\'')
1748 char tchar = in->ptr[idx];
1749 sb_add_char (out, in->ptr[idx++]);
1750 while (idx < in->len
1751 && in->ptr[idx] != tchar)
1752 sb_add_char (out, in->ptr[idx++]);
1754 sb_add_char (out, in->ptr[idx++]);
1763 /* skip along sb in starting at idx, suck off whitespace a ( and more
1764 whitespace. return the idx of the next char */
1767 skip_openp (idx, in)
1771 idx = sb_skip_white (idx, in);
1772 if (in->ptr[idx] != '(')
1773 ERROR ((stderr, "misplaced ( .\n"));
1774 idx = sb_skip_white (idx + 1, in);
1778 /* skip along sb in starting at idx, suck off whitespace a ) and more
1779 whitespace. return the idx of the next char */
1782 skip_closep (idx, in)
1786 idx = sb_skip_white (idx, in);
1787 if (in->ptr[idx] != ')')
1788 ERROR ((stderr, "misplaced ).\n"));
1789 idx = sb_skip_white (idx + 1, in);
1796 dolen (idx, in, out)
1805 sb_new (&stringout);
1806 idx = skip_openp (idx, in);
1807 idx = get_and_process (idx, in, &stringout);
1808 idx = skip_closep (idx, in);
1809 sprintf (buffer, "%d", stringout.len);
1810 sb_add_string (out, buffer);
1812 sb_kill (&stringout);
1821 doinstr (idx, in, out)
1835 idx = skip_openp (idx, in);
1836 idx = get_and_process (idx, in, &string);
1837 idx = sb_skip_comma (idx, in);
1838 idx = get_and_process (idx, in, &search);
1839 idx = sb_skip_comma (idx, in);
1840 if (isdigit (in->ptr[idx]))
1842 idx = exp_get_abs (".instr needs absolute expresson.\n", idx, in, &start);
1848 idx = skip_closep (idx, in);
1850 for (i = start; i < string.len; i++)
1852 if (strncmp (string.ptr + i, search.ptr, search.len) == 0)
1858 sprintf (buffer, "%d", res);
1859 sb_add_string (out, buffer);
1867 dosubstr (idx, in, out)
1877 idx = skip_openp (idx, in);
1878 idx = get_and_process (idx, in, &string);
1879 idx = sb_skip_comma (idx, in);
1880 idx = exp_get_abs ("need absolute position.\n", idx, in, &pos);
1881 idx = sb_skip_comma (idx, in);
1882 idx = exp_get_abs ("need absolute length.\n", idx, in, &len);
1883 idx = skip_closep (idx, in);
1886 if (len < 0 || pos < 0 ||
1888 || pos + len > string.len)
1890 sb_add_string (out, " ");
1894 sb_add_char (out, '"');
1897 sb_add_char (out, string.ptr[pos++]);
1900 sb_add_char (out, '"');
1906 /* scan line, change tokens in the hash table to their replacements */
1908 process_assigns (idx, in, buf)
1913 while (idx < in->len)
1916 if (in->ptr[idx] == '\\'
1917 && in->ptr[idx + 1] == '&')
1919 idx = condass_lookup_name (in, idx + 2, buf, 1);
1921 else if (in->ptr[idx] == '\\'
1922 && in->ptr[idx + 1] == '$')
1924 idx = condass_lookup_name (in, idx + 2, buf, 0);
1926 else if (idx + 3 < in->len
1927 && in->ptr[idx] == '.'
1928 && in->ptr[idx + 1] == 'L'
1929 && in->ptr[idx + 2] == 'E'
1930 && in->ptr[idx + 3] == 'N')
1931 idx = dolen (idx + 4, in, buf);
1932 else if (idx + 6 < in->len
1933 && in->ptr[idx] == '.'
1934 && in->ptr[idx + 1] == 'I'
1935 && in->ptr[idx + 2] == 'N'
1936 && in->ptr[idx + 3] == 'S'
1937 && in->ptr[idx + 4] == 'T'
1938 && in->ptr[idx + 5] == 'R')
1939 idx = doinstr (idx + 6, in, buf);
1940 else if (idx + 7 < in->len
1941 && in->ptr[idx] == '.'
1942 && in->ptr[idx + 1] == 'S'
1943 && in->ptr[idx + 2] == 'U'
1944 && in->ptr[idx + 3] == 'B'
1945 && in->ptr[idx + 4] == 'S'
1946 && in->ptr[idx + 5] == 'T'
1947 && in->ptr[idx + 6] == 'R')
1948 idx = dosubstr (idx + 7, in, buf);
1949 else if (ISFIRSTCHAR (in->ptr[idx]))
1951 /* may be a simple name subsitution, see if we have a word */
1954 while (cur < in->len
1955 && (ISNEXTCHAR (in->ptr[cur])))
1959 sb_add_buffer (&acc, in->ptr + idx, cur - idx);
1960 ptr = hash_lookup (&assign_hash_table, &acc);
1963 /* Found a definition for it */
1964 sb_add_sb (buf, &ptr->value.s);
1968 /* No definition, just copy the word */
1969 sb_add_sb (buf, &acc);
1976 sb_add_char (buf, in->ptr[idx++]);
1982 get_and_process (idx, in, out)
1989 idx = get_any_string (idx, in, &t);
1990 process_assigns (0, &t, out);
2011 more = get_line (&line);
2014 /* Find any label and pseudo op that we're intested in */
2019 fprintf (outfile, "\n");
2023 l = grab_label (&line, &label_in);
2027 /* Munge any label */
2030 process_assigns (0, &label_in, &label);
2033 if (line.ptr[l] == ':')
2035 while (ISWHITE (line.ptr[l]) && l < line.len)
2040 if (process_pseudo_op (l, &line, &acc))
2046 else if (condass_on ())
2048 if (macro_op (l, &line))
2058 fprintf (outfile, "%s:\t", sb_name (&label));
2061 fprintf (outfile, "\t");
2063 process_assigns (l, &line, &t1);
2065 change_base (0, &t1, &t2);
2066 fprintf (outfile, "%s\n", sb_name (&t2));
2072 /* Only a label on this line */
2073 if (label.len && condass_on())
2075 fprintf (outfile, "%s:\n", sb_name (&label));
2083 more = get_line (&line);
2087 WARNING ((stderr, "END missing from end of file.\n"));
2095 free_old_entry (ptr)
2100 if (ptr->type == hash_string)
2101 sb_kill(&ptr->value.s);
2105 /* name: .ASSIGNA <value> */
2108 do_assigna (idx, in)
2116 process_assigns (idx, in, &tmp);
2117 idx = exp_get_abs (".ASSIGNA needs constant expression argument.\n", 0, &tmp, &val);
2121 ERROR ((stderr, ".ASSIGNA without label.\n"));
2125 hash_entry *ptr = hash_create (&vars, &label);
2126 free_old_entry (ptr);
2127 ptr->type = hash_integer;
2133 /* name: .ASSIGNC <string> */
2136 do_assignc (idx, in)
2142 idx = getstring (idx, in, &acc);
2146 ERROR ((stderr, ".ASSIGNS without label.\n"));
2150 hash_entry *ptr = hash_create (&vars, &label);
2151 free_old_entry (ptr);
2152 ptr->type = hash_string;
2153 sb_new (&ptr->value.s);
2154 sb_add_sb (&ptr->value.s, &acc);
2160 /* name: .REG (reg) */
2167 /* remove reg stuff from inside parens */
2169 idx = skip_openp (idx, in);
2171 while (idx < in->len && in->ptr[idx] != ')')
2173 sb_add_char (&what, in->ptr[idx]);
2176 hash_add_to_string_table (&assign_hash_table, &label, &what, 1);
2182 condass_lookup_name (inbuf, idx, out, warn)
2190 sb_new (&condass_acc);
2192 while (idx < inbuf->len
2193 && ISNEXTCHAR (inbuf->ptr[idx]))
2195 sb_add_char (&condass_acc, inbuf->ptr[idx++]);
2198 if (inbuf->ptr[idx] == '\'')
2200 ptr = hash_lookup (&vars, &condass_acc);
2207 WARNING ((stderr, "Can't find preprocessor variable %s.\n", sb_name (&condass_acc)));
2211 sb_add_string (out, "0");
2216 if (ptr->type == hash_integer)
2219 sprintf (buffer, "%d", ptr->value.i);
2220 sb_add_string (out, buffer);
2224 sb_add_sb (out, &ptr->value.s);
2227 sb_kill (&condass_acc);
2240 whatcond (idx, in, val)
2247 idx = sb_skip_white (idx, in);
2249 if (p[0] == 'E' && p[1] == 'Q')
2251 else if (p[0] == 'N' && p[1] == 'E')
2253 else if (p[0] == 'L' && p[1] == 'T')
2255 else if (p[0] == 'L' && p[1] == 'E')
2257 else if (p[0] == 'G' && p[1] == 'T')
2259 else if (p[0] == 'G' && p[1] == 'E')
2263 ERROR ((stderr, "Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n"));
2266 idx = sb_skip_white (idx + 2, in);
2283 idx = sb_skip_white (idx, in);
2285 if (in->ptr[idx] == '"')
2289 /* This is a string comparision */
2290 idx = getstring (idx, in, &acc_a);
2291 idx = whatcond (idx, in, &cond);
2292 idx = getstring (idx, in, &acc_b);
2293 same = acc_a.len == acc_b.len && (strncmp (acc_a.ptr, acc_b.ptr, acc_a.len) == 0);
2295 if (cond != EQ && cond != NE)
2297 ERROR ((stderr, "Comparison operator for strings must be EQ or NE\n"));
2301 res = cond == EQ && same;
2304 /* This is a numeric expression */
2309 idx = exp_get_abs ("Conditional operator must have absolute operands.\n", idx, in, &vala);
2310 idx = whatcond (idx, in, &cond);
2311 idx = sb_skip_white (idx, in);
2312 if (in->ptr[idx] == '"')
2314 WARNING ((stderr, "String compared against expression.\n"));
2319 idx = exp_get_abs ("Conditional operator must have absolute operands.\n", idx, in, &valb);
2359 if (ifi >= IFNESTING)
2361 FATAL ((stderr, "AIF nesting unreasonable.\n"));
2364 ifstack[ifi].on = istrue (idx, in);
2365 ifstack[ifi].hadelse = 0;
2373 ifstack[ifi].on = !ifstack[ifi].on;
2374 if (ifstack[ifi].hadelse)
2376 ERROR ((stderr, "Multiple AELSEs in AIF.\n"));
2378 ifstack[ifi].hadelse = 1;
2392 ERROR ((stderr, "AENDI without AIF.\n"));
2399 return ifstack[ifi].on;
2403 /* Read input lines till we get to a TO string.
2404 Increase nesting depth if we geta FROM string.
2405 Put the results into sb at PTR. */
2408 buffer_and_nest (from, to, ptr)
2413 int from_len = strlen (from);
2414 int to_len = strlen (to);
2416 int line_start = ptr->len;
2417 int line = linecount ();
2419 int more = get_line (ptr);
2423 /* Try and find the first pseudo op on the line */
2428 /* With normal syntax we can suck what we want till we get to the dot.
2429 With the alternate, labels have to start in the first column, since
2430 we cant tell what's a label and whats a pseudoop */
2432 /* Skip leading whitespace */
2434 && ISWHITE (ptr->ptr[i]))
2437 /* Skip over a label */
2439 && ISNEXTCHAR (ptr->ptr[i]))
2444 && ptr->ptr[i] == ':')
2448 /* Skip trailing whitespace */
2450 && ISWHITE (ptr->ptr[i]))
2453 if (i < ptr->len && (ptr->ptr[i] == '.'
2456 if (ptr->ptr[i] == '.')
2458 if (strncmp (ptr->ptr + i, from, from_len) == 0)
2460 if (strncmp (ptr->ptr + i, to, to_len) == 0)
2465 /* Reset the string to not include the ending rune */
2466 ptr->len = line_start;
2472 /* Add a CR to the end and keep running */
2473 sb_add_char (ptr, '\n');
2474 line_start = ptr->len;
2475 more = get_line (ptr);
2480 FATAL ((stderr, "End of file whilst inside %s, started on line %d.\n", from, line));
2488 ERROR ((stderr, "AENDR without a AREPEAT.\n"));
2507 process_assigns (idx, in, &exp);
2508 doit = istrue (0, &exp);
2510 buffer_and_nest ("AWHILE", "AENDW", &sub);
2525 int index = include_next_index ();
2529 sb_add_sb (©, &sub);
2530 sb_add_sb (©, in);
2531 sb_add_string (©, "\n");
2532 sb_add_sb (©, &sub);
2533 sb_add_string (©, "\t.AENDW\n");
2534 /* Push another WHILE */
2535 include_buf (&exp, ©, include_while, index);
2548 ERROR ((stderr, "AENDW without a AENDW.\n"));
2554 Pop things off the include stack until the type and index changes */
2559 include_type type = sp->type;
2560 if (type == include_repeat
2561 || type == include_while
2562 || type == include_macro)
2564 int index = sp->index;
2566 while (sp->index == index
2567 && sp->type == type)
2577 do_arepeat (idx, in)
2581 sb exp; /* buffer with expression in it */
2582 sb copy; /* expanded repeat block */
2583 sb sub; /* contents of AREPEAT */
2589 process_assigns (idx, in, &exp);
2590 idx = exp_get_abs ("AREPEAT must have absolute operand.\n", 0, &exp, &rc);
2591 buffer_and_nest ("AREPEAT", "AENDR", &sub);
2594 /* Push back the text following the repeat, and another repeat block
2605 int index = include_next_index ();
2606 sb_add_sb (©, &sub);
2609 sprintf (buffer, "\t.AREPEAT %d\n", rc - 1);
2610 sb_add_string (©, buffer);
2611 sb_add_sb (©, &sub);
2612 sb_add_string (©, " .AENDR\n");
2615 include_buf (&exp, ©, include_repeat, index);
2627 ERROR ((stderr, ".ENDM without a matching .MACRO.\n"));
2631 /* MARRO PROCESSING */
2634 hash_table macro_table;
2644 do_formals (macro, idx, in)
2649 formal_entry **p = ¯o->formals;
2650 macro->formal_count = 0;
2651 hash_new_table (5, ¯o->formal_hash);
2652 while (idx < in->len)
2654 formal_entry *formal;
2656 formal = (formal_entry *) xmalloc (sizeof (formal_entry));
2658 sb_new (&formal->name);
2659 sb_new (&formal->def);
2660 sb_new (&formal->actual);
2662 idx = sb_skip_white (idx, in);
2663 idx = get_token (idx, in, &formal->name);
2664 if (formal->name.len == 0)
2666 idx = sb_skip_white (idx, in);
2667 if (formal->name.len)
2669 /* This is a formal */
2670 if (idx < in->len && in->ptr[idx] == '=')
2673 idx = get_any_string (idx + 1, in, &formal->def);
2678 /* Add to macro's hash table */
2680 hash_entry *p = hash_create (¯o->formal_hash, &formal->name);
2681 p->type = hash_formal;
2682 p->value.f = formal;
2685 formal->index = macro->formal_count;
2686 idx = sb_skip_comma (idx, in);
2687 macro->formal_count++;
2694 /* Parse off LOCAL n1, n2,... Invent a label name for it */
2697 do_local (idx, line)
2707 idx = sb_skip_white (idx, line);
2708 while (!eol(idx, line))
2713 sprintf(subs, "LL%04x", ln);
2714 idx = get_token(idx, line, &acc);
2715 sb_add_string (&sub, subs);
2716 hash_add_to_string_table (&assign_hash_table, &acc, &sub, 1);
2717 idx = sb_skip_comma (idx, line);
2732 macro = (macro_entry *) xmalloc (sizeof (macro_entry));
2733 sb_new (¯o->sub);
2736 macro->formal_count = 0;
2739 idx = sb_skip_white (idx, in);
2740 buffer_and_nest ("MACRO", "ENDM", ¯o->sub);
2744 sb_add_sb (&name, &label);
2745 if (in->ptr[idx] == '(')
2747 /* It's the label: MACRO (formals,...) sort */
2748 idx = do_formals (macro, idx + 1, in);
2749 if (in->ptr[idx] != ')')
2750 ERROR ((stderr, "Missing ) after formals.\n"));
2753 /* It's the label: MACRO formals,... sort */
2754 idx = do_formals (macro, idx, in);
2759 idx = get_token (idx, in, &name);
2760 idx = sb_skip_white (idx, in);
2761 idx = do_formals (macro, idx, in);
2764 /* and stick it in the macro hash table */
2765 hash_create (¯o_table, &name)->value.m = macro;
2770 get_token (idx, in, name)
2776 && ISFIRSTCHAR (in->ptr[idx]))
2778 sb_add_char (name, in->ptr[idx++]);
2779 while (idx < in->len
2780 && ISNEXTCHAR (in->ptr[idx]))
2782 sb_add_char (name, in->ptr[idx++]);
2788 /* Scan a token, but stop if a ' is seen */
2790 get_apost_token (idx, in, name, kind)
2796 idx = get_token (idx, in, name);
2797 if (idx < in->len && in->ptr[idx] == kind)
2803 sub_actual (src, in, t, m, kind, out, copyifnotthere)
2812 /* This is something to take care of */
2814 src = get_apost_token (src, in, t, kind);
2815 /* See if it's in the macro's hash table */
2816 ptr = hash_lookup (&m->formal_hash, t);
2819 if (ptr->value.f->actual.len)
2821 sb_add_sb (out, &ptr->value.f->actual);
2825 sb_add_sb (out, &ptr->value.f->def);
2828 else if (copyifnotthere)
2834 sb_add_char (out, '\\');
2842 macro_expand (name, idx, in, m)
2852 int is_positional = 0;
2858 /* Reset any old value the actuals may have */
2859 for (f = m->formals; f; f = f->next)
2860 sb_reset (&f->actual);
2862 /* Peel off the actuals and store them away in the hash tables' actuals */
2863 while (!eol(idx, in))
2866 idx = sb_skip_white (idx, in);
2867 /* Look and see if it's a positional or keyword arg */
2869 while (scan < in->len
2870 && !ISSEP (in->ptr[scan])
2871 && in->ptr[scan] != '=')
2873 if (scan < in->len && in->ptr[scan] == '=')
2878 ERROR ((stderr, "Can't mix positional and keyword arguments.\n"));
2881 /* This is a keyword arg, fetch the formal name and
2882 then the actual stuff */
2884 idx = get_token (idx, in, &t);
2885 if (in->ptr[idx] != '=')
2886 ERROR ((stderr, "confused about formal params.\n"));
2888 /* Lookup the formal in the macro's list */
2889 ptr = hash_lookup (&m->formal_hash, &t);
2892 ERROR ((stderr, "MACRO formal argument %s does not exist.\n", sb_name (&t)));
2897 /* Insert this value into the right place */
2898 sb_reset (&ptr->value.f->actual);
2899 idx = get_any_string (idx + 1, in, &ptr->value.f->actual);
2904 /* This is a positional arg */
2908 ERROR ((stderr, "Can't mix positional and keyword arguments.\n"));
2913 ERROR ((stderr, "Too many positional arguments.\n"));
2917 sb_reset (&f->actual);
2918 idx = get_any_string (idx, in, &f->actual);
2921 idx = sb_skip_comma (idx, in);
2924 /* Copy the stuff from the macro buffer into a safe place and substitute any args */
2932 while (src < in->len)
2934 if (in->ptr[src] == '&')
2937 src = sub_actual (src + 1, in, &t, m, '&', &out, 0);
2939 else if (in->ptr[src] == '\\')
2942 if (in->ptr[src] == comment_char)
2944 /* This is a comment, just drop the rest of the line */
2945 while (src < in->len
2946 && in->ptr[src] != '\n')
2950 else if (in->ptr[src] == '(')
2952 /* Sub in till the next ')' literally */
2954 while (src < in->len && in->ptr[src] != ')')
2956 sb_add_char (&out, in->ptr[src++]);
2958 if (in->ptr[src] == ')')
2961 ERROR ((stderr, "Missplaced ).\n"));
2963 else if (in->ptr[src] == '@')
2965 /* Sub in the macro invocation number */
2969 sprintf (buffer, "%05d", number);
2970 sb_add_string (&out, buffer);
2972 else if (in->ptr[src] == '&')
2974 /* This is a preprocessor variable name, we don't do them
2976 sb_add_char (&out, '\\');
2977 sb_add_char (&out, '&');
2983 src = sub_actual (src, in, &t, m, '\'', &out, 0);
2986 else if (ISFIRSTCHAR (in->ptr[src]) && alternate)
2989 src = sub_actual (src, in, &t, m, '\'', &out, 1);
2991 else if (ISCOMMENTCHAR (in->ptr[src])
2992 && src + 1 < in->len
2993 && ISCOMMENTCHAR (in->ptr[src+1])
2996 /* Two comment chars in a row cause the rest of the line to be dropped */
2997 while (src < in->len && in->ptr[src] != '\n')
3000 else if (in->ptr[src] == '"')
3003 sb_add_char (&out, in->ptr[src++]);
3007 sb_add_char (&out, in->ptr[src++]);
3010 include_buf (name, &out, include_macro, include_next_index ());
3023 /* The macro name must be the first thing on the line */
3029 idx = get_token (idx, in, &name);
3033 /* Got a name, look it up */
3035 ptr = hash_lookup (¯o_table, &name);
3039 /* It's in the table, copy out the stuff and convert any macro args */
3040 macro_expand (&name, idx, in, ptr->value.m);
3052 /* STRING HANDLING */
3055 getstring (idx, in, acc)
3060 idx = sb_skip_white (idx, in);
3062 while (idx < in->len
3063 && (in->ptr[idx] == '"'
3064 || in->ptr[idx] == '<'
3065 || (in->ptr[idx] == '\'' && alternate)))
3067 if (in->ptr[idx] == '<')
3073 while ((in->ptr[idx] != '>' || nest)
3076 if (in->ptr[idx] == '!')
3079 sb_add_char (acc, in->ptr[idx++]);
3082 if (in->ptr[idx] == '>')
3084 if (in->ptr[idx] == '<')
3086 sb_add_char (acc, in->ptr[idx++]);
3094 idx = exp_get_abs ("Character code in string must be absolute expression.\n",
3096 sb_add_char (acc, code);
3098 if (in->ptr[idx] != '>')
3099 ERROR ((stderr, "Missing > for character code.\n"));
3103 else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
3105 char tchar = in->ptr[idx];
3107 while (idx < in->len)
3109 if (alternate && in->ptr[idx] == '!')
3112 sb_add_char (acc, in->ptr[idx++]);
3115 if (in->ptr[idx] == tchar)
3118 if (idx >= in->len || in->ptr[idx] != tchar)
3121 sb_add_char (acc, in->ptr[idx]);
3131 /* .SDATA[C|Z] <string> */
3135 do_sdata (idx, in, type)
3144 fprintf (outfile, ".byte\t");
3146 while (!eol (idx, in))
3150 idx = sb_skip_white (idx, in);
3151 while (!eol (idx, in))
3153 pidx = idx = get_any_string (idx, in, &acc);
3158 ERROR ((stderr, "string for SDATAC longer than 255 characters (%d).\n", acc.len));
3160 fprintf (outfile, "%d", acc.len);
3164 for (i = 0; i < acc.len; i++)
3168 fprintf (outfile, ",");
3170 fprintf (outfile, "%d", acc.ptr[i]);
3177 fprintf (outfile, ",");
3178 fprintf (outfile, "0");
3180 idx = sb_skip_comma (idx, in);
3181 if (idx == pidx) break;
3183 if (!alternate && in->ptr[idx] != ',' && idx != in->len)
3185 fprintf (outfile, "\n");
3186 ERROR ((stderr, "illegal character in SDATA line (0x%x).\n", in->ptr[idx]));
3192 fprintf (outfile, "\n");
3195 /* .SDATAB <count> <string> */
3207 idx = exp_get_abs ("Must have absolute SDATAB repeat count.\n", idx, in, &repeat);
3210 ERROR ((stderr, "Must have positive SDATAB repeat count (%d).\n", repeat));
3214 idx = sb_skip_comma (idx, in);
3215 idx = getstring (idx, in, &acc);
3217 for (i = 0; i < repeat; i++)
3220 fprintf (outfile, "\t");
3221 fprintf (outfile, ".byte\t");
3223 fprintf (outfile, "\n");
3233 FILE *newone = fopen (name, "r");
3237 if (isp == MAX_INCLUDES)
3238 FATAL ((stderr, "Unreasonable include depth (%d).\n", isp));
3241 sp->handle = newone;
3244 sb_add_string (&sp->name, name);
3247 sp->pushback_index = 0;
3248 sp->type = include_file;
3250 sb_new (&sp->pushback);
3255 do_include (idx, in)
3262 idx = getstring (idx, in, &t);
3263 text = sb_name (&t);
3264 if (!new_file (text))
3266 FATAL ((stderr, "Can't open include file `%s'.\n", text));
3274 if (sp != include_stack)
3277 fclose (sp->handle);
3282 /* Get the next character from the include stack. If there's anything
3283 in the pushback buffer, take that first. If we're at eof, pop from
3284 the stack and try again. Keep the linecount up to date. */
3291 if (sp->pushback.len != sp->pushback_index)
3293 r = (char) (sp->pushback.ptr[sp->pushback_index++]);
3294 /* When they've all gone, reset the pointer */
3295 if (sp->pushback_index == sp->pushback.len)
3297 sp->pushback.len = 0;
3298 sp->pushback_index = 0;
3301 else if (sp->handle)
3303 r = getc (sp->handle);
3308 if (r == EOF && isp)
3312 while (r == EOF && isp)
3330 return sp->linecount;
3334 include_next_index ()
3338 && index > MAX_REASONABLE)
3339 FATAL ((stderr, "Unreasonable expansion (-u turns off check).\n"));
3344 /* Initialize the chartype vector. */
3350 for (x = 0; x < 256; x++)
3352 if (isalpha (x) || x == '_' || x == '$')
3353 chartype[x] |= FIRSTBIT;
3355 if (isdigit (x) || isalpha (x) || x == '_' || x == '$')
3356 chartype[x] |= NEXTBIT;
3358 if (x == ' ' || x == '\t' || x == ',' || x == '"' || x == ';'
3359 || x == '"' || x == '<' || x == '>' || x == ')' || x == '(')
3360 chartype[x] |= SEPBIT;
3362 if (x == ' ' || x == '\t')
3363 chartype[x] |= WHITEBIT;
3365 if (x == comment_char)
3366 chartype[x] |= COMMENTBIT;
3372 /* What to do with all the keywords */
3373 #define PROCESS 0x1000 /* Run substitution over the line */
3374 #define LAB 0x2000 /* Spit out the label */
3376 #define K_EQU PROCESS|1
3377 #define K_ASSIGN PROCESS|2
3378 #define K_REG PROCESS|3
3379 #define K_ORG PROCESS|4
3380 #define K_RADIX PROCESS|5
3381 #define K_DATA LAB|PROCESS|6
3382 #define K_DATAB LAB|PROCESS|7
3383 #define K_SDATA LAB|PROCESS|8
3384 #define K_SDATAB LAB|PROCESS|9
3385 #define K_SDATAC LAB|PROCESS|10
3386 #define K_SDATAZ LAB|PROCESS|11
3387 #define K_RES LAB|PROCESS|12
3388 #define K_SRES LAB|PROCESS|13
3389 #define K_SRESC LAB|PROCESS|14
3390 #define K_SRESZ LAB|PROCESS|15
3391 #define K_EXPORT LAB|PROCESS|16
3392 #define K_GLOBAL LAB|PROCESS|17
3393 #define K_PRINT LAB|PROCESS|19
3394 #define K_FORM LAB|PROCESS|20
3395 #define K_HEADING LAB|PROCESS|21
3396 #define K_PAGE LAB|PROCESS|22
3397 #define K_IMPORT LAB|PROCESS|23
3398 #define K_PROGRAM LAB|PROCESS|24
3399 #define K_END PROCESS|25
3400 #define K_INCLUDE PROCESS|26
3401 #define K_IGNORED PROCESS|27
3402 #define K_ASSIGNA PROCESS|28
3403 #define K_ASSIGNC 29
3404 #define K_AIF PROCESS|30
3405 #define K_AELSE PROCESS|31
3406 #define K_AENDI PROCESS|32
3407 #define K_AREPEAT PROCESS|33
3408 #define K_AENDR PROCESS|34
3410 #define K_AENDW PROCESS|36
3412 #define K_MACRO PROCESS|38
3414 #define K_ALIGN PROCESS|LAB|40
3415 #define K_ALTERNATE 41
3416 #define K_DB LAB|PROCESS|42
3417 #define K_DW LAB|PROCESS|43
3418 #define K_DL LAB|PROCESS|44
3430 { "EQU", K_EQU, 0 },
3431 { "ALTERNATE", K_ALTERNATE, 0 },
3432 { "ASSIGN", K_ASSIGN, 0 },
3433 { "REG", K_REG, 0 },
3434 { "ORG", K_ORG, 0 },
3435 { "RADIX", K_RADIX, 0 },
3436 { "DATA", K_DATA, 0 },
3440 { "DATAB", K_DATAB, 0 },
3441 { "SDATA", K_SDATA, 0 },
3442 { "SDATAB", K_SDATAB, 0 },
3443 { "SDATAZ", K_SDATAZ, 0 },
3444 { "SDATAC", K_SDATAC, 0 },
3445 { "RES", K_RES, 0 },
3446 { "SRES", K_SRES, 0 },
3447 { "SRESC", K_SRESC, 0 },
3448 { "SRESZ", K_SRESZ, 0 },
3449 { "EXPORT", K_EXPORT, 0 },
3450 { "GLOBAL", K_GLOBAL, 0 },
3451 { "PRINT", K_PRINT, 0 },
3452 { "FORM", K_FORM, 0 },
3453 { "HEADING", K_HEADING, 0 },
3454 { "PAGE", K_PAGE, 0 },
3455 { "PROGRAM", K_IGNORED, 0 },
3456 { "END", K_END, 0 },
3457 { "INCLUDE", K_INCLUDE, 0 },
3458 { "ASSIGNA", K_ASSIGNA, 0 },
3459 { "ASSIGNC", K_ASSIGNC, 0 },
3460 { "AIF", K_AIF, 0 },
3461 { "AELSE", K_AELSE, 0 },
3462 { "AENDI", K_AENDI, 0 },
3463 { "AREPEAT", K_AREPEAT, 0 },
3464 { "AENDR", K_AENDR, 0 },
3465 { "EXITM", K_EXITM, 0 },
3466 { "MACRO", K_MACRO, 0 },
3467 { "ENDM", K_ENDM, 0 },
3468 { "AWHILE", K_AWHILE, 0 },
3469 { "ALIGN", K_ALIGN, 0 },
3470 { "AENDW", K_AENDW, 0 },
3471 { "ALTERNATE", K_ALTERNATE, 0 },
3472 { "LOCAL", K_LOCAL, 0 },
3476 /* Look for a pseudo op on the line. If one's there then call
3480 process_pseudo_op (idx, line, acc)
3487 if (line->ptr[idx] == '.' || alternate)
3489 /* Scan forward and find pseudo name */
3495 if (line->ptr[idx] == '.')
3497 in = line->ptr + idx;
3502 while (idx < line->len && *e && ISFIRSTCHAR (*e))
3504 sb_add_char (acc, *e);
3509 ptr = hash_lookup (&keyword_hash_table, acc);
3514 /* This one causes lots of pain when trying to preprocess
3516 WARNING ((stderr, "Unrecognised pseudo op `%s'.\n", sb_name (acc)));
3520 if (ptr->value.i & LAB)
3521 { /* output the label */
3524 fprintf (outfile, "%s:\t", sb_name (&label));
3527 fprintf (outfile, "\t");
3530 if (ptr->value.i & PROCESS)
3532 /* Polish the rest of the line before handling the pseudo op */
3534 strip_comments(line);
3537 process_assigns (idx, line, acc);
3539 change_base (0, acc, line);
3544 switch (ptr->value.i)
3557 switch (ptr->value.i)
3569 ERROR ((stderr, "ORG command not allowed.\n"));
3575 do_data (idx, line, 1);
3578 do_data (idx, line, 2);
3581 do_data (idx, line, 4);
3584 do_data (idx, line, 0);
3587 do_datab (idx, line);
3590 do_sdata (idx, line, 0);
3593 do_sdatab (idx, line);
3596 do_sdata (idx, line, 'c');
3599 do_sdata (idx, line, 'z');
3602 do_assign (1, 0, line);
3608 do_arepeat (idx, line);
3614 do_awhile (idx, line);
3620 do_assign (0, idx, line);
3623 do_align (idx, line);
3626 do_res (idx, line, 0);
3629 do_res (idx, line, 's');
3632 do_include (idx, line);
3635 do_local (idx, line);
3638 do_macro (idx, line);
3644 do_res (idx, line, 'c');
3647 do_print (idx, line);
3650 do_form (idx, line);
3653 do_heading (idx, line);
3665 do_res (idx, line, 'z');
3673 do_assigna (idx, line);
3676 do_assignc (idx, line);
3692 /* Build the keyword hash table - put each keyword in the table twice,
3693 once upper and once lower case.*/
3700 for (i = 0; kinfo[i].name; i++)
3705 sb_add_string (&label, kinfo[i].name);
3707 hash_add_to_int_table (&keyword_hash_table, &label, kinfo[i].code);
3710 for (j = 0; kinfo[i].name[j]; j++)
3711 sb_add_char (&label, kinfo[i].name[j] - 'A' + 'a');
3712 hash_add_to_int_table (&keyword_hash_table, &label, kinfo[i].code);
3738 sb_add_char (&value, *string);
3741 exp_get_abs ("Invalid expression on command line.\n", 0, &value, &res);
3745 sb_add_char (&label, *string);
3750 ptr = hash_create (&vars, &label);
3751 free_old_entry (ptr);
3752 ptr->type = hash_integer;
3758 /* The list of long options. */
3759 static struct option long_options[] =
3761 { "alternate", no_argument, 0, 'a' },
3762 { "commentchar", required_argument, 0, 'c' },
3763 { "copysource", no_argument, 0, 's' },
3764 { "debug", no_argument, 0, 'd' },
3765 { "help", no_argument, 0, 'h' },
3766 { "output", required_argument, 0, 'o' },
3767 { "print", no_argument, 0, 'p' },
3768 { "unreasonable", no_argument, 0, 'u' },
3769 { "version", no_argument, 0, 'v' },
3770 { "define", required_argument, 0, 'd' },
3771 { NULL, no_argument, 0, 0 }
3774 /* Show a usage message and exit. */
3776 show_usage (file, status)
3782 [-a] [--alternate] enter alternate macro mode\n\
3783 [-c char] [--commentchar char] change the comment character from !\n\
3784 [-d] [--debug] print some debugging info\n\
3785 [-h] [--help] print this message\n\
3786 [-o out] [--output out] set the output file\n\
3787 [-p] [--print] print line numbers\n\
3788 [-s] [--copysource] copy source through as comments \n\
3789 [-u] [--unreasonable] allow unreasonable nesting\n\
3790 [-v] [--version] print the program version\n\
3791 [-Dname=value] create preprocessor variable called name, with value\n\
3792 [in-file]\n", program_name);
3796 /* Display a help message and exit. */
3800 printf ("%s: Gnu Assembler Macro Preprocessor\n",
3802 show_usage (stdout, 0);
3819 program_name = argv[0];
3820 xmalloc_set_program_name (program_name);
3822 hash_new_table (101, ¯o_table);
3823 hash_new_table (101, &keyword_hash_table);
3824 hash_new_table (101, &assign_hash_table);
3825 hash_new_table (101, &vars);
3830 while ((opt = getopt_long (argc, argv, "sdhavc:upo:D:", long_options,
3843 print_line_number = 1;
3846 comment_char = optarg[0];
3864 printf ("GNU %s version %s\n", program_name, program_version);
3870 show_usage (stderr, 1);
3877 outfile = fopen (out_name, "w");
3880 fprintf (stderr, "%s: Can't open output file `%s'.\n",
3881 program_name, out_name);
3893 /* Process all the input files */
3895 while (optind < argc)
3897 if (new_file (argv[optind]))
3903 fprintf (stderr, "%s: Can't open input file `%s'.\n",
3904 program_name, argv[optind]);