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 [-c] [-o <outfile>] <infile>*
31 -c copy source to output
39 #define MAX_INCLUDES 30 /* Maximum include depth */
40 #define MAX_REASONABLE 1000 /* Maximum number of expansions */
42 int unreasonable; /* -u on command line */
43 int stats; /* -s on command line */
44 int print_line_number; /* -p flag on command line */
45 int copysource; /* -c flag on command line */
46 int warnings; /* Number of WARNINGs generated so far. */
47 int errors; /* Number of ERRORs generated so far. */
48 int fatals; /* Number of fatal ERRORs generated so far (either 0 or 1). */
52 int radix = 10; /* Default radix */
54 int had_end; /* Seen .END */
56 /* The output stream */
60 /* Forward declarations. */
61 static int condass_lookup_name();
62 static int condass_on();
64 static int get_and_process();
65 static int get_token();
66 static int getstring();
67 static int include_next_index();
68 static int macro_op();
69 static int linecount();
70 static int process_pseudo_op();
71 static void include_pop();
72 static void include_print_where_line();
75 I had a couple of choices when deciding upon this data structure.
76 gas uses null terminated strings for all its internal work. This
77 often means that parts of the program that want to examine
78 substrings have to manipulate the data in the string to do the
79 right thing (a common operation is to single out a bit of text by
80 saving away the character after it, nulling it out, operating on
81 the substring and then replacing the character which was under the
82 null). This is a pain and I remember a load of problems that I had with
83 code in gas which almost got this right. Also, it's harder to grow and
84 allocate null terminated strings efficiently.
86 Obstacks provide all the functionality needed, but are too
87 complicated, hence the sb.
89 An sb is allocated by the caller, and is initialzed to point to an
90 sb_element. sb_elements are kept on a free lists, and used when
91 needed, replaced onto the free list when unused.
94 #define max_power_two 30 /* don't allow strings more than
95 2^max_power_two long */
96 /* structure of an sb */
99 char *ptr; /* points to the current block. */
100 int len; /* how much is used. */
101 int pot; /* the maximum length is 1<<pot */
106 /* Structure of the free list object of an sb */
118 sb_element *size[max_power_two];
121 sb_list_vector free_list;
123 int string_count[max_power_two];
125 /* the attributes of each character are stored as a bit pattern
126 chartype, which gives us quick tests. */
133 #define ISFIRSTCHAR(x) (chartype[(unsigned)(x)] & FIRSTBIT)
134 #define ISNEXTCHAR(x) (chartype[(unsigned)(x)] & NEXTBIT)
135 #define ISSEP(x) (chartype[(unsigned)(x)] & SEPBIT)
136 #define ISWHITE(x) (chartype[(unsigned)(x)] & WHITEBIT)
138 static char chartype[256];
141 /* Conditional assembly uses the `ifstack'. Each aif pushes another
142 entry onto the stack, and sets the on flag if it should. The aelse
143 sets hadelse, and toggles on. An aend pops a level. We limit to
144 100 levels of nesting, not because we're facists pigs with read
145 only minds, but because more than 100 levels of nesting is probably
146 a bug in the user's macro structure. */
148 #define IFNESTING 100
151 int on; /* is the level being output */
152 int hadelse; /* has an aelse been seen */
157 /* The final and intermediate results of expression evaluation are kept in
158 exp_t's. Note that a symbol is not an sb, but a pointer into the input
159 line. It must be coped somewhere safe before the next line is read in. */
170 int value; /* constant part */
171 symbol add_symbol; /* name part */
172 symbol sub_symbol; /* name part */
177 /* Hashing is done in a pretty standard way. A hash_table has a
178 pointer to a vector of pointers to hash_entrys, and the size of the
179 vector. A hash_entry contains a union of all the info we like to
180 store in hash table. If there is a hash collision, hash_entries
181 with the same hash are kept in a chain. */
183 /* What the data in a hash_entry means */
186 hash_integer, /* name->integer mapping */
187 hash_string, /* name->string mapping */
188 hash_macro, /* name is a macro */
189 hash_formal /* name is a formal argument */
194 sb key; /* symbol name */
195 hash_type type; /* symbol meaning */
200 struct macro_struct *m;
201 struct formal_struct *f;
203 struct hs *next; /* next hash_entry with same hash key */
213 /* Structures used to store macros.
215 Each macro knows its name and included text. It gets built with a
216 list of formal arguments, and also keeps a hash table which points
217 into the list to speed up formal search. Each formal knows its
218 name and its default value. Each time the macro is expanded, the
219 formals get the actual values attatched to them. */
221 /* describe the formal arguments to a macro */
223 typedef struct formal_struct
225 struct formal_struct *next; /* next formal in list */
226 sb name; /* name of the formal */
227 sb def; /* the default value */
228 sb actual; /* the actual argument (changed on each expansion) */
229 int index; /* the index of the formal 0..formal_count-1 */
233 /* describe the macro. */
235 typedef struct macro_struct
237 sb sub; /* substitution text. */
238 int formal_count; /* number of formal args. */
239 formal_entry *formals; /* pointer to list of formal_structs */
240 hash_table formal_hash; /* hash table of formals. */
244 /* how we nest files and expand macros etc.
246 we keep a stack of of include_stack structs. each include file
247 pushes a new level onto the stack. we keep an sb with a pushback
248 too. unget chars are pushed onto the pushback sb, getchars first
249 checks the pushback sb before reading from the input stream.
251 small things are expanded by adding the text of the item onto the
252 pushback sb. larger items are grown by pushing a new level and
253 allocating the entire pushback buf for the item. each time
254 something like a macro is expanded, the stack index is changed. we
255 can then perform an exitm by popping all entries off the stack with
256 the same stack index. if we're being reasonable, we can detect
257 recusive expansion by checking the index is reasonably small.
262 include_file, include_repeat, include_while, include_macro
267 sb pushback; /* current pushback stream */
268 int pushback_index; /* next char to read from stream */
269 FILE *handle; /* open file */
270 sb name; /* name of file */
271 int linecount; /* number of lines read so far */
273 int index; /* index of this layer */
275 include_stack[MAX_INCLUDES];
277 struct include_stack *sp;
278 #define isp (sp - include_stack)
283 void include_print_where_line ();
287 do { include_print_where_line (stderr); fprintf x ; fatals++; quit(); } while(0)
289 do { include_print_where_line (stderr); fprintf x; errors++; } while(0)
291 do { include_print_where_line (stderr); fprintf x; warnings++;} while(0)
295 /* exit the program and return the right ERROR code. */
308 for (i = 0; i < max_power_two; i++)
310 fprintf (stderr, "strings size %8d : %d\n", 1<<i, string_count[i]);
321 char *p = malloc (x);
323 FATAL ((stderr, "out of memory\n"));
328 /* this program is about manipulating strings.
329 they are managed in things called `sb's which is an abbreviation
330 for string buffers. an sb has to be created, things can be glued
331 on to it, and at the end of it's life it should be freed. the
332 contents should never be pointed at whilst it is still growing,
333 since it could be moved at any time
337 sb_grow... (&foo,...);
343 /* initializes an sb. */
350 /* see if we can find one to allocate */
353 if (size > max_power_two)
355 FATAL ((stderr, "string longer than %d bytes requested.\n",
356 1 << max_power_two));
358 e = free_list.size[size];
361 /* nothing there, allocate one and stick into the free list */
362 e = (sb_element *) xmalloc (sizeof (sb_element) + (1 << size));
363 e->next = free_list.size[size];
365 free_list.size[size] = e;
366 string_count[size]++;
369 /* remove from free list */
371 free_list.size[size] = e->next;
373 /* copy into callers world */
385 sb_build (ptr, dsize);
388 /* deallocate the sb at ptr */
395 /* return item to free list */
396 ptr->item->next = free_list.size[ptr->pot];
397 free_list.size[ptr->pot] = ptr->item;
400 /* add the sb at s to the end of the sb at ptr */
402 static void sb_check ();
410 sb_check (ptr, s->len);
411 memcpy (ptr->ptr + ptr->len, s->ptr, s->len);
415 /* make sure that the sb at ptr has room for another len characters,
416 and grow it if it doesn't. */
423 if (ptr->len + len >= 1 << ptr->pot)
427 while (ptr->len + len >= 1 << pot)
429 sb_build (&tmp, pot);
430 sb_add_sb (&tmp, ptr);
436 /* make the sb at ptr point back to the beginning. */
445 /* add character c to the end of the sb at ptr. */
453 ptr->ptr[ptr->len++] = c;
456 /* add null terminated string s to the end of sb at ptr. */
459 sb_add_string (ptr, s)
463 int len = strlen (s);
465 memcpy (ptr->ptr + ptr->len, s, len);
469 /* add string at s of length len to sb at ptr */
472 sb_add_buffer (ptr, s, len)
478 memcpy (ptr->ptr + ptr->len, s, len);
483 /* print the sb at ptr to the output file */
493 for (i = 0; i < ptr->len; i++)
497 fprintf (outfile, ",");
499 fprintf (outfile, "%d", ptr->ptr[i]);
504 /* put a null at the end of the sb at in and return the start of the
505 string, so that it can be used as an arg to printf %s. */
512 /* stick a null on the end of the string */
517 /* start at the index idx into the string in sb at ptr and skip
518 whitespace. return the index of the first non whitespace character */
521 sb_skip_white (idx, ptr)
525 while (idx < ptr->len && ISWHITE (ptr->ptr[idx]))
530 /* start at the index idx into the sb at ptr. skips whitespace,
531 a comma and any following whitespace. returnes the index of the
535 sb_skip_comma (idx, ptr)
539 while (idx < ptr->len && ISWHITE (ptr->ptr[idx]))
543 && ptr->ptr[idx] == ',')
546 while (idx < ptr->len && ISWHITE (ptr->ptr[idx]))
553 /* hash table maintenance. */
555 /* build a new hash table with size buckets, and fill in the info at ptr. */
558 hash_new_table (size, ptr)
563 ptr->table = (hash_entry **) xmalloc (size * (sizeof (hash_entry *)));
566 /* calculate and return the hash value of the sb at key. */
575 for (i = 0; i < key->len; i++)
583 /* lookup key in hash_table tab, if present, then return it, otherwise
584 build a new one and fill it with hash_integer. */
588 hash_create (tab, key)
592 int k = hash (key) % tab->size;
594 hash_entry **table = tab->table;
602 hash_entry *n = (hash_entry *) xmalloc (sizeof (hash_entry));
605 sb_add_sb (&n->key, key);
607 n->type = hash_integer;
610 if (strncmp (table[k]->key.ptr, key->ptr, key->len) == 0)
618 /* add sb name with key into hash_table tab. if replacing old value
619 and again, then ERROR. */
623 hash_add_to_string_table (tab, key, name, again)
629 hash_entry *ptr = hash_create (tab, key);
630 if (ptr->type == hash_integer)
632 sb_new (&ptr->value.s);
634 if (ptr->value.s.len)
637 ERROR ((stderr, "redefintion not allowed"));
639 sb_reset (&ptr->value.s);
640 sb_add_sb (&ptr->value.s, name);
643 /* add integer name to hash_table tab with sb key. */
647 hash_add_to_int_table (tab, key, name)
652 hash_entry *ptr = hash_create (tab, key);
656 /* lookup sb key in hash_table tab. if found return hash_entry result,
661 hash_lookup (tab, key)
665 int k = hash (key) % tab->size;
666 hash_entry **table = tab->table;
667 hash_entry *p = table[k];
670 if (p->key.len == key->len
671 && strncmp (p->key.ptr, key->ptr, key->len) == 0)
681 are handled in a really simple recursive decent way. each bit of
682 the machine takes an index into an sb and a pointer to an exp_t,
683 modifies the *exp_t and returns the index of the first character
684 past the part of the expression parsed.
686 expression precedence:
697 /* make sure that the exp_t at term is constant, if not the give the op ERROR. */
701 checkconst (op, term)
705 if (term->add_symbol.len
706 || term->sub_symbol.len)
708 ERROR ((stderr, "the %c operator cannot take non-absolute arguments.\n", op));
712 /* turn the number in string at idx into a number of base,
713 fill in ptr and return the index of the first character not in the
718 sb_strtol (idx, string, base, ptr)
725 idx = sb_skip_white (idx, string);
727 while (idx < string->len)
729 int ch = string->ptr[idx];
733 else if (ch >= 'a' && ch <= 'f')
735 else if (ch >= 'a' && ch <= 'f')
743 value = value * base + dig;
750 static int level_5 ();
753 level_0 (idx, string, lhs)
758 lhs->add_symbol.len = 0;
759 lhs->add_symbol.name = 0;
761 lhs->sub_symbol.len = 0;
762 lhs->sub_symbol.name = 0;
764 idx = sb_skip_white (idx, string);
768 if (isdigit (string->ptr[idx]))
770 idx = sb_strtol (idx, string, 10, &lhs->value);
772 else if (ISFIRSTCHAR (string->ptr[idx]))
775 lhs->add_symbol.name = string->ptr + idx;
776 while (idx < string->len && ISNEXTCHAR (string->ptr[idx]))
781 lhs->add_symbol.len = len;
783 else if (string->ptr[idx] == '"')
787 ERROR ((stderr, "string where expression expected.\n"));
788 idx = getstring (idx, string, &acc);
793 ERROR ((stderr, "can't find primary in expression.\n"));
796 return sb_skip_white (idx, string);
802 level_1 (idx, string, lhs)
807 idx = sb_skip_white (idx, string);
809 switch (string->ptr[idx])
812 idx = level_1 (idx + 1, string, lhs);
815 idx = level_1 (idx + 1, string, lhs);
816 checkconst ('~', lhs);
817 lhs->value = ~lhs->value;
822 idx = level_1 (idx + 1, string, lhs);
823 lhs->value = -lhs->value;
825 lhs->add_symbol = lhs->sub_symbol;
831 idx = level_5 (sb_skip_white (idx, string), string, lhs);
832 if (string->ptr[idx] != ')')
833 ERROR ((stderr, "misplaced closing parens.\n"));
838 idx = level_0 (idx, string, lhs);
841 return sb_skip_white (idx, string);
845 level_2 (idx, string, lhs)
852 idx = level_1 (idx, string, lhs);
854 while (idx < string->len && (string->ptr[idx] == '*'
855 || string->ptr[idx] == '/'))
857 char op = string->ptr[idx++];
858 idx = level_1 (idx, string, &rhs);
862 checkconst ('*', lhs);
863 checkconst ('*', &rhs);
864 lhs->value *= rhs.value;
867 checkconst ('/', lhs);
868 checkconst ('/', &rhs);
870 ERROR ((stderr, "attempt to divide by zero.\n"));
872 lhs->value /= rhs.value;
876 return sb_skip_white (idx, string);
881 level_3 (idx, string, lhs)
888 idx = level_2 (idx, string, lhs);
890 while (idx < string->len
891 && (string->ptr[idx] == '+'
892 || string->ptr[idx] == '-'))
894 char op = string->ptr[idx++];
895 idx = level_2 (idx, string, &rhs);
899 lhs->value += rhs.value;
900 if (lhs->add_symbol.name && rhs.add_symbol.name)
902 ERROR ((stderr, "can't add two relocatable expressions\n"));
904 /* change nn+symbol to symbol + nn */
905 if (rhs.add_symbol.name)
907 lhs->add_symbol = rhs.add_symbol;
911 lhs->value -= rhs.value;
912 lhs->sub_symbol = rhs.add_symbol;
916 return sb_skip_white (idx, string);
920 level_4 (idx, string, lhs)
927 idx = level_3 (idx, string, lhs);
929 while (idx < string->len &&
930 string->ptr[idx] == '&')
932 char op = string->ptr[idx++];
933 idx = level_3 (idx, string, &rhs);
937 checkconst ('&', lhs);
938 checkconst ('&', &rhs);
939 lhs->value &= rhs.value;
943 return sb_skip_white (idx, string);
947 level_5 (idx, string, lhs)
954 idx = level_4 (idx, string, lhs);
956 while (idx < string->len
957 && (string->ptr[idx] == '|' || string->ptr[idx] == '~'))
959 char op = string->ptr[idx++];
960 idx = level_4 (idx, string, &rhs);
964 checkconst ('|', lhs);
965 checkconst ('|', &rhs);
966 lhs->value |= rhs.value;
969 checkconst ('~', lhs);
970 checkconst ('~', &rhs);
971 lhs->value ^= rhs.value;
975 return sb_skip_white (idx, string);
979 /* parse the expression at offset idx into string, fill up res with
980 the result. return the index of the first char past the expression.
984 exp_parse (idx, string, res)
989 return level_5 (sb_skip_white (idx, string), string, res);
993 /* turn the expression at exp into text and glue it onto the end of
997 exp_string (exp, string)
1005 if (exp->add_symbol.len)
1007 sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
1015 sb_add_char (string, '+');
1016 sprintf (buf, "%d", exp->value);
1017 sb_add_string (string, buf);
1021 if (exp->sub_symbol.len)
1023 sb_add_char (string, '-');
1024 sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
1030 sb_add_char (string, '0');
1034 /* parse the expression at offset idx into sb in, return the value in val.
1035 if the expression is not constant, give ERROR emsg. returns the index
1036 of the first character past the end of the expression. */
1039 exp_get_abs (emsg, idx, in, val)
1046 idx = exp_parse (idx, in, &res);
1047 if (res.add_symbol.len || res.sub_symbol.len)
1048 ERROR ((stderr, emsg));
1054 sb label; /* current label parsed from line */
1055 hash_table assign_hash_table; /* hash table for all assigned variables */
1056 hash_table keyword_hash_table; /* hash table for keyword */
1057 hash_table vars; /* hash table for eq variables */
1059 #define in_comment ';'
1063 strip_comments (out)
1068 for (i = 0; i < out->len; i++)
1070 if (s[i] == in_comment)
1079 /* push back character ch so that it can be read again. */
1089 if (sp->pushback_index)
1090 sp->pushback_index--;
1092 sb_add_char (&sp->pushback, ch);
1095 /* push the sb ptr onto the include stack, with the given name, type and index. */
1099 include_buf (name, ptr, type, index)
1106 if (sp - include_stack >= MAX_INCLUDES)
1107 FATAL ((stderr, "unreasonable nesting.\n"));
1109 sb_add_sb (&sp->name, name);
1112 sp->pushback_index = 0;
1115 sb_new (&sp->pushback);
1116 sb_add_sb (&sp->pushback, ptr);
1120 /* used in ERROR messages, print info on where the include stack is onto file. */
1123 include_print_where_line (file)
1126 struct include_stack *p = include_stack + 1;
1130 fprintf (file, "%s:%d ", sb_name (&p->name), p->linecount - ((p == sp) ? 1 : 0));
1135 /* used in listings, print the line number onto file. */
1137 include_print_line (file)
1141 struct include_stack *p = include_stack + 1;
1143 n = fprintf (file, "%4d", p->linecount);
1147 n += fprintf (file, ".%d", p->linecount);
1152 fprintf (file, " ");
1158 /* read a line from the top of the include stack into sb in. */
1169 putc ('!', outfile);
1170 if (print_line_number)
1171 include_print_line (outfile);
1185 WARNING ((stderr, "end of file not at start of line.\n"));
1187 putc ('\n', outfile);
1204 /* continued line */
1207 putc ('!', outfile);
1208 putc ('+', outfile);
1221 sb_add_char (in, ch);
1229 /* find a label from sb in and put it in out. */
1232 grab_label (in, out)
1238 if (ISFIRSTCHAR (in->ptr[i]))
1240 sb_add_char (out, in->ptr[i]);
1242 while (ISNEXTCHAR (in->ptr[i]) && i < in->len)
1244 sb_add_char (out, in->ptr[i]);
1251 /* find all strange base stuff and turn into decimal. also
1252 find all the other numbers and convert them from the default radix */
1255 change_base (idx, in, out)
1262 while (idx < in->len)
1264 if (idx < in->len - 1 && in->ptr[idx + 1] == '\'')
1268 switch (in->ptr[idx])
1287 ERROR ((stderr, "Illegal base character %c.\n", in->ptr[idx]));
1292 idx = sb_strtol (idx + 2, in, base, &value);
1293 sprintf (buffer, "%d", value);
1294 sb_add_string (out, buffer);
1296 else if (ISFIRSTCHAR (in->ptr[idx]))
1298 /* copy entire names through quickly */
1299 sb_add_char (out, in->ptr[idx]);
1301 while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
1303 sb_add_char (out, in->ptr[idx]);
1307 else if (isdigit (in->ptr[idx]))
1310 /* all numbers must start with a digit, let's chew it and
1312 idx = sb_strtol (idx, in, radix, &value);
1313 sprintf (buffer, "%d", value);
1314 sb_add_string (out, buffer);
1316 /* skip all undigsested letters */
1317 while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
1319 sb_add_char (out, in->ptr[idx]);
1325 /* nothing special, just pass it through */
1326 sb_add_char (out, in->ptr[idx]);
1343 do_assign (again, idx, in)
1348 /* stick label in symbol table with following value */
1353 idx = exp_parse (idx, in, &e);
1354 exp_string (&e, &acc);
1355 hash_add_to_string_table (&assign_hash_table, &label, &acc, again);
1360 /* .radix [b|q|d|h] */
1367 int idx = sb_skip_white (0, ptr);
1368 switch (ptr->ptr[idx])
1387 ERROR ((stderr, "radix is %c must be one of b, q, d or h", radix));
1392 /* Parse off a .b, .w or .l */
1395 get_opsize (idx, in, size)
1401 if (in->ptr[idx] == '.')
1404 switch (in->ptr[idx])
1419 ERROR ((stderr, "size must be one of b, w or l, is %c.\n", in->ptr[idx]));
1427 /* .data [.b|.w|.l] <data>* */
1439 idx = get_opsize (idx, in, &opsize);
1454 fprintf (outfile, "%s\t", opname);
1455 while (idx < in->len)
1458 idx = exp_parse (idx, in, &e);
1459 exp_string (&e, &acc);
1460 sb_add_char (&acc, 0);
1461 fprintf (outfile, acc.ptr);
1462 if (idx < in->len && in->ptr[idx] == ',')
1464 fprintf (outfile, ",");
1469 fprintf (outfile, "\n");
1472 /* .datab [.b|.w|.l] <repeat>,<fill> */
1483 idx = get_opsize (idx, in, &opsize);
1485 idx = exp_get_abs ("datab repeat must be constant.\n", idx, in, &repeat);
1486 idx = sb_skip_comma (idx, in);
1487 idx = exp_get_abs ("datab data must be absolute.\n", idx, in, &fill);
1489 fprintf (outfile, ".fill\t%d,%d,%d\n", repeat, opsize, fill);
1500 idx = exp_get_abs ("align needs absolute expression.\n", idx, in, &al);
1505 WARNING ((stderr, "alignment must be one of 1, 2 or 4.\n"));
1507 fprintf (outfile, ".align %d\n", al);
1510 /* .res[.b|.w|.l] <size> */
1513 do_res (idx, in, type)
1521 idx = get_opsize (idx, in, &size);
1522 while (idx < in->len)
1524 idx = sb_skip_white (idx, in);
1525 if (in->ptr[idx] == ',')
1527 idx = exp_get_abs ("res needs absolute expression for fill count.\n", idx, in, &count);
1529 if (type == 'c' || type == 'z')
1532 fprintf (outfile, ".space %d\n", count * size);
1543 fprintf (outfile, ".global %s\n", sb_name (in));
1546 /* .print [list] [nolist] */
1553 idx = sb_skip_white (idx, in);
1554 while (idx < in->len)
1556 if (strncmp (in->ptr + idx, "LIST", 4) == 0)
1558 fprintf (outfile, ".list\n");
1561 else if (strncmp (in->ptr + idx, "NOLIST", 6) == 0)
1563 fprintf (outfile, ".nolist\n");
1572 do_heading (idx, in)
1578 idx = getstring (idx, in, &head);
1579 fprintf (outfile, ".title \"%s\"\n", sb_name (&head));
1588 fprintf (outfile, ".eject\n");
1591 /* .form [lin=<value>] [col=<value>] */
1599 idx = sb_skip_white (idx, in);
1601 while (idx < in->len)
1604 if (strncmp (in->ptr + idx, "LIN=", 4) == 0)
1607 idx = exp_get_abs ("form LIN= needs absolute expresssion.\n", idx, in, &lines);
1610 if (strncmp (in->ptr + idx, "COL=", 4) == 0)
1613 idx = exp_get_abs ("form COL= needs absolute expresssion.\n", idx, in, &columns);
1618 fprintf (outfile, ".psize %d,%d\n", lines, columns);
1623 get_any_string (idx, in, out)
1628 idx = sb_skip_white (idx, in);
1629 if (idx < in->len && (in->ptr[idx] == '"'
1630 || in->ptr[idx] == '<'))
1631 return getstring (idx, in, out);
1635 while (idx < in->len && !ISSEP (in->ptr[idx]))
1637 sb_add_char (out, in->ptr[idx++]);
1643 /* skip along sb in starting at idx, suck off whitespace a ( and more
1644 whitespace. return the idx of the next char */
1647 skip_openp (idx, in)
1651 idx = sb_skip_white (idx, in);
1652 if (in->ptr[idx] != '(')
1653 ERROR ((stderr, "misplaced ( .\n"));
1654 idx = sb_skip_white (idx + 1, in);
1658 /* skip along sb in starting at idx, suck off whitespace a ) and more
1659 whitespace. return the idx of the next char */
1662 skip_closep (idx, in)
1666 idx = sb_skip_white (idx, in);
1667 if (in->ptr[idx] != ')')
1668 ERROR ((stderr, "misplaced ).\n"));
1669 idx = sb_skip_white (idx + 1, in);
1676 dolen (idx, in, out)
1685 sb_new (&stringout);
1686 idx = skip_openp (idx, in);
1687 idx = get_and_process (idx, in, &stringout);
1688 idx = skip_closep (idx, in);
1689 sprintf (buffer, "%d", stringout.len);
1690 sb_add_string (out, buffer);
1692 sb_kill (&stringout);
1701 doinstr (idx, in, out)
1715 idx = skip_openp (idx, in);
1716 idx = get_and_process (idx, in, &string);
1717 idx = sb_skip_comma (idx, in);
1718 idx = get_and_process (idx, in, &search);
1719 idx = sb_skip_comma (idx, in);
1720 if (isdigit (in->ptr[idx]))
1722 idx = exp_get_abs (".instr needs absolute expresson.\n", idx, in, &start);
1728 idx = skip_closep (idx, in);
1730 for (i = start; i < string.len; i++)
1732 if (strncmp (string.ptr + i, search.ptr, search.len) == 0)
1738 sprintf (buffer, "%d", res);
1739 sb_add_string (out, buffer);
1747 dosubstr (idx, in, out)
1757 idx = skip_openp (idx, in);
1758 idx = get_and_process (idx, in, &string);
1759 idx = sb_skip_comma (idx, in);
1760 idx = exp_get_abs ("need absolute position.\n", idx, in, &pos);
1761 idx = sb_skip_comma (idx, in);
1762 idx = exp_get_abs ("need absolute length.\n", idx, in, &len);
1763 idx = skip_closep (idx, in);
1766 if (len < 0 || pos < 0 ||
1768 || pos + len > string.len)
1770 sb_add_string (out, " ");
1774 sb_add_char (out, '"');
1777 sb_add_char (out, string.ptr[pos++]);
1780 sb_add_char (out, '"');
1786 /* scan line, change tokens in the hash table to their replacements */
1788 process_assigns (idx, in, buf)
1793 while (idx < in->len)
1796 if (in->ptr[idx] == '\\'
1797 && in->ptr[idx + 1] == '&')
1799 idx = condass_lookup_name (in, idx + 2, buf);
1801 else if (idx + 3 < in->len
1802 && in->ptr[idx] == '.'
1803 && in->ptr[idx + 1] == 'L'
1804 && in->ptr[idx + 2] == 'E'
1805 && in->ptr[idx + 3] == 'N')
1806 idx = dolen (idx + 4, in, buf);
1807 else if (idx + 6 < in->len
1808 && in->ptr[idx] == '.'
1809 && in->ptr[idx + 1] == 'I'
1810 && in->ptr[idx + 2] == 'N'
1811 && in->ptr[idx + 3] == 'S'
1812 && in->ptr[idx + 4] == 'T'
1813 && in->ptr[idx + 5] == 'R')
1814 idx = doinstr (idx + 6, in, buf);
1815 else if (idx + 7 < in->len
1816 && in->ptr[idx] == '.'
1817 && in->ptr[idx + 1] == 'S'
1818 && in->ptr[idx + 2] == 'U'
1819 && in->ptr[idx + 3] == 'B'
1820 && in->ptr[idx + 4] == 'S'
1821 && in->ptr[idx + 5] == 'T'
1822 && in->ptr[idx + 6] == 'R')
1823 idx = dosubstr (idx + 7, in, buf);
1824 else if (ISFIRSTCHAR (in->ptr[idx]))
1826 /* may be a simple name subsitution, see if we have a word */
1829 while (cur < in->len
1830 && (ISNEXTCHAR (in->ptr[cur])))
1834 sb_add_buffer (&acc, in->ptr + idx, cur - idx);
1835 ptr = hash_lookup (&assign_hash_table, &acc);
1838 /* Found a definition for it */
1839 sb_add_sb (buf, &ptr->value.s);
1843 /* No definition, just copy the word */
1844 sb_add_sb (buf, &acc);
1851 sb_add_char (buf, in->ptr[idx++]);
1857 get_and_process (idx, in, out)
1864 idx = get_any_string (idx, in, &t);
1865 process_assigns (0, &t, out);
1885 more = get_line (&line);
1888 /* Find any label and pseudo op that we're intested in */
1893 fprintf (outfile, "\n");
1898 l = grab_label (&line, &label);
1899 if (line.ptr[l] == ':')
1901 while (ISWHITE (line.ptr[l]) && l < line.len)
1906 if (process_pseudo_op (l, &line, &acc))
1912 else if (condass_on ())
1914 if (macro_op (l, &line))
1924 fprintf (outfile, "%s:\t", sb_name (&label));
1927 fprintf (outfile, "\t");
1929 process_assigns (l, &line, &t1);
1931 change_base (0, &t1, &t2);
1932 fprintf (outfile, "%s\n", sb_name (&t2));
1942 more = get_line (&line);
1946 WARNING ((stderr, ".END missing from end of file.\n"));
1954 free_old_entry (ptr)
1959 if (ptr->type == hash_string)
1960 sb_kill(&ptr->value.s);
1964 /* name: .ASSIGNA <value> */
1967 do_assigna (idx, in)
1975 process_assigns (idx, in, &tmp);
1976 idx = exp_get_abs (".ASSIGNA needs constant expression argument.\n", 0, &tmp, &val);
1980 ERROR ((stderr, ".ASSIGNA without label.\n"));
1984 hash_entry *ptr = hash_create (&vars, &label);
1985 free_old_entry (ptr);
1986 ptr->type = hash_integer;
1992 /* name: .ASSIGNC <string> */
1995 do_assignc (idx, in)
2001 idx = getstring (idx, in, &acc);
2005 ERROR ((stderr, ".ASSIGNS without label.\n"));
2009 hash_entry *ptr = hash_create (&vars, &label);
2010 free_old_entry (ptr);
2011 ptr->type = hash_string;
2012 sb_new (&ptr->value.s);
2013 sb_add_sb (&ptr->value.s, &acc);
2019 /* name: .REG (reg) */
2026 /* remove reg stuff from inside parens */
2028 idx = skip_openp (idx, in);
2030 while (idx < in->len && in->ptr[idx] != ')')
2032 sb_add_char (&what, in->ptr[idx]);
2035 hash_add_to_string_table (&assign_hash_table, &label, &what, 1);
2041 condass_lookup_name (inbuf, idx, out)
2048 sb_new (&condass_acc);
2050 while (idx < inbuf->len
2051 && ISNEXTCHAR (inbuf->ptr[idx]))
2053 sb_add_char (&condass_acc, inbuf->ptr[idx++]);
2056 if (inbuf->ptr[idx] == '\'')
2058 ptr = hash_lookup (&vars, &condass_acc);
2061 WARNING ((stderr, "Can't find preprocessor variable %s.\n", sb_name (&condass_acc)));
2065 if (ptr->type == hash_integer)
2068 sprintf (buffer, "%d", ptr->value.i);
2069 sb_add_string (out, buffer);
2073 sb_add_sb (out, &ptr->value.s);
2076 sb_kill (&condass_acc);
2089 whatcond (idx, in, val)
2096 idx = sb_skip_white (idx, in);
2098 if (p[0] == 'E' && p[1] == 'Q')
2100 else if (p[0] == 'N' && p[1] == 'E')
2102 else if (p[0] == 'L' && p[1] == 'T')
2104 else if (p[0] == 'L' && p[1] == 'E')
2106 else if (p[0] == 'G' && p[1] == 'T')
2108 else if (p[0] == 'G' && p[1] == 'E')
2112 ERROR ((stderr, "Comparison operator must be one of EQ, NE, LT, LE, GT or GE"));
2115 idx = sb_skip_white (idx + 2, in);
2132 idx = sb_skip_white (idx, in);
2134 if (in->ptr[idx] == '"')
2138 /* This is a string comparision */
2139 idx = getstring (idx, in, &acc_a);
2140 idx = whatcond (idx, in, &cond);
2141 idx = getstring (idx, in, &acc_b);
2142 same = acc_a.len == acc_b.len && (strncmp (acc_a.ptr, acc_b.ptr, acc_a.len) == 0);
2144 if (cond != EQ && cond != NE)
2146 ERROR ((stderr, "Comparison operator for strings must be EQ or NE"));
2150 res = cond == EQ && same;
2153 /* This is a numeric expression */
2158 idx = exp_get_abs ("Conditional operator must have absolute operands.\n", idx, in, &vala);
2159 idx = whatcond (idx, in, &cond);
2160 idx = sb_skip_white (idx, in);
2161 if (in->ptr[idx] == '"')
2163 WARNING ((stderr, "String compared against expression.\n"));
2168 idx = exp_get_abs ("Conditional operator must have absolute operands.\n", idx, in, &valb);
2208 if (ifi >= IFNESTING)
2210 FATAL ((stderr, "AIF nesting unreasonable.\n"));
2213 ifstack[ifi].on = istrue (idx, in);
2214 ifstack[ifi].hadelse = 0;
2222 ifstack[ifi].on = !ifstack[ifi].on;
2223 if (ifstack[ifi].hadelse)
2225 ERROR ((stderr, "Multiple AELSEs in AIF.\n"));
2227 ifstack[ifi].hadelse = 1;
2241 ERROR ((stderr, "AENDI without AIF.\n"));
2248 return ifstack[ifi].on;
2252 /* Read input lines till we get to a TO string.
2253 Increase nesting depth if we geta FROM string.
2254 Put the results into sb at PTR. */
2257 buffer_and_nest (from, to, ptr)
2262 int from_len = strlen (from);
2263 int to_len = strlen (to);
2265 int line_start = ptr->len;
2266 int line = linecount ();
2268 int more = get_line (ptr);
2272 /* Try and find the first pseudo op on the line */
2275 /* Skip leading whitespace */
2277 && ISWHITE (ptr->ptr[i]))
2280 /* Skip over a label */
2282 && ISNEXTCHAR (ptr->ptr[i]))
2287 && ptr->ptr[i] == ':')
2290 /* Skip trailing whitespace */
2292 && ISWHITE (ptr->ptr[i]))
2296 && ptr->ptr[i] == '.')
2298 if (strncmp (ptr->ptr + i, from, from_len) == 0)
2300 if (strncmp (ptr->ptr + i, to, to_len) == 0)
2305 /* Reset the string to not include the ending rune */
2306 ptr->len = line_start;
2312 /* Add a CR to the end and keep running */
2313 sb_add_char (ptr, '\n');
2314 line_start = ptr->len;
2315 more = get_line (ptr);
2320 FATAL ((stderr, "End of file whilst inside %s, started on line %d.\n", from, line));
2328 ERROR ((stderr, "AENDR without a AREPEAT.\n"));
2347 process_assigns (idx, in, &exp);
2348 doit = istrue (0, &exp);
2350 buffer_and_nest (".AWHILE", ".AENDW", &sub);
2365 int index = include_next_index ();
2369 sb_add_sb (©, &sub);
2370 sb_add_sb (©, in);
2371 sb_add_string (©, "\n");
2372 sb_add_sb (©, &sub);
2373 sb_add_string (©, "\t.AENDW\n");
2374 /* Push another WHILE */
2375 include_buf (&exp, ©, include_while, index);
2388 ERROR ((stderr, "AENDW without a AENDW.\n"));
2394 Pop things off the include stack until the type and index changes */
2399 include_type type = sp->type;
2400 if (type == include_repeat
2401 || type == include_while
2402 || type == include_macro)
2404 int index = sp->index;
2406 while (sp->index == index
2407 && sp->type == type)
2417 do_arepeat (idx, in)
2421 sb exp; /* buffer with expression in it */
2422 sb copy; /* expanded repeat block */
2423 sb sub; /* contents of AREPEAT */
2429 process_assigns (idx, in, &exp);
2430 idx = exp_get_abs ("AREPEAT must have absolute operand.\n", 0, &exp, &rc);
2431 buffer_and_nest (".AREPEAT", ".AENDR", &sub);
2434 /* Push back the text following the repeat, and another repeat block
2445 int index = include_next_index ();
2446 sb_add_sb (©, &sub);
2449 sprintf (buffer, "\t.AREPEAT %d\n", rc - 1);
2450 sb_add_string (©, buffer);
2451 sb_add_sb (©, &sub);
2452 sb_add_string (©, " .AENDR\n");
2455 include_buf (&exp, ©, include_repeat, index);
2467 ERROR ((stderr, ".ENDM without a matching .MACRO.\n"));
2471 /* MARRO PROCESSING */
2474 hash_table macro_table;
2484 do_formals (macro, idx, in)
2489 formal_entry **p = ¯o->formals;
2490 macro->formal_count = 0;
2491 hash_new_table (5, ¯o->formal_hash);
2492 while (idx < in->len)
2494 formal_entry *formal;
2496 formal = (formal_entry *) xmalloc (sizeof (formal_entry));
2498 sb_new (&formal->name);
2499 sb_new (&formal->def);
2500 sb_new (&formal->actual);
2502 idx = sb_skip_white (idx, in);
2503 idx = get_token (idx, in, &formal->name);
2504 if (formal->name.len == 0)
2506 idx = sb_skip_white (idx, in);
2507 if (formal->name.len)
2509 /* This is a formal */
2510 if (idx < in->len && in->ptr[idx] == '=')
2513 idx = get_any_string (idx + 1, in, &formal->def);
2518 /* Add to macro's hash table */
2520 hash_entry *p = hash_create (¯o->formal_hash, &formal->name);
2521 p->type = hash_formal;
2522 p->value.f = formal;
2525 formal->index = macro->formal_count;
2526 idx = sb_skip_comma (idx, in);
2527 macro->formal_count++;
2543 macro = (macro_entry *) xmalloc (sizeof (macro_entry));
2544 sb_new (¯o->sub);
2547 macro->formal_count = 0;
2550 idx = sb_skip_white (idx, in);
2551 buffer_and_nest (".MACRO", ".ENDM", ¯o->sub);
2554 /* It's the label: MACRO (formals,...) sort */
2555 sb_add_sb (&name, &label);
2556 if (in->ptr[idx] == '(')
2558 /* Got some formals */
2559 idx = do_formals (macro, idx + 1, in);
2560 if (in->ptr[idx] != ')')
2561 ERROR ((stderr, "Missing ) after formals.\n"));
2566 idx = get_token (idx, in, &name);
2567 idx = sb_skip_white (idx, in);
2568 idx = do_formals (macro, idx, in);
2571 /* and stick it in the macro hash table */
2572 hash_create (¯o_table, &name)->value.m = macro;
2577 get_token (idx, in, name)
2583 && ISFIRSTCHAR (in->ptr[idx]))
2585 sb_add_char (name, in->ptr[idx++]);
2586 while (idx < in->len
2587 && ISNEXTCHAR (in->ptr[idx]))
2589 sb_add_char (name, in->ptr[idx++]);
2595 /* Scan a token, but stop if a ' is seen */
2597 get_apost_token (idx, in, name, kind)
2603 idx = get_token (idx, in, name);
2604 if (idx < in->len && in->ptr[idx] == kind)
2610 sub_actual (src, in, t, m, kind, out)
2618 /* This is something to take care of */
2620 src = get_apost_token (src, in, t, kind);
2621 /* See if it's in the macro's hash table */
2622 ptr = hash_lookup (&m->formal_hash, t);
2625 if (ptr->value.f->actual.len)
2627 sb_add_sb (out, &ptr->value.f->actual);
2631 sb_add_sb (out, &ptr->value.f->def);
2636 sb_add_char (out, '\\');
2644 macro_expand (name, idx, in, m)
2655 int is_positional = 0;
2661 /* Reset any old value the actuals may have */
2662 for (f = m->formals; f; f = f->next)
2663 sb_reset (&f->actual);
2665 /* Peel off the actuals and store them away in the hash tables' actuals */
2666 while (idx < in->len)
2669 idx = sb_skip_white (idx, in);
2670 /* Look and see if it's a positional or keyword arg */
2672 while (scan < in->len
2673 && !ISSEP (in->ptr[scan])
2674 && in->ptr[scan] != '=')
2676 if (scan < in->len && in->ptr[scan] == '=')
2681 ERROR ((stderr, "Can't mix positional and keyword arguments.\n"));
2684 /* This is a keyword arg, fetch the formal name and
2685 then the actual stuff */
2687 idx = get_token (idx, in, &t);
2688 if (in->ptr[idx] != '=')
2689 ERROR ((stderr, "confused about formal params.\n"));
2691 /* Lookup the formal in the macro's list */
2692 ptr = hash_lookup (&m->formal_hash, &t);
2695 ERROR ((stderr, "MACRO formal argument %s does not exist.\n", sb_name (&t)));
2700 /* Insert this value into the right place */
2701 sb_reset (&ptr->value.f->actual);
2702 idx = get_any_string (idx + 1, in, &ptr->value.f->actual);
2707 /* This is a positional arg */
2711 ERROR ((stderr, "Can't mix positional and keyword arguments.\n"));
2716 ERROR ((stderr, "Too many positional arguments.\n"));
2720 sb_reset (&f->actual);
2721 idx = get_any_string (idx, in, &f->actual);
2724 idx = sb_skip_comma (idx, in);
2727 /* Copy the stuff from the macro buffer into a safe place and substitute any args */
2734 while (src < in->len)
2736 if (in->ptr[src] == '&')
2739 src = sub_actual (src + 1, in, &t, m, '&', &out);
2741 else if (in->ptr[src] == '\\')
2744 if (in->ptr[src] == ';')
2746 /* This is a comment, just drop the rest of the line */
2747 while (src < in->len
2748 && in->ptr[src] != '\n')
2752 else if (in->ptr[src] == '(')
2754 /* Sub in till the next ')' literally */
2756 while (src < in->len && in->ptr[src] != ')')
2758 sb_add_char (&out, in->ptr[src++]);
2760 if (in->ptr[src] == ')')
2763 ERROR ((stderr, "Missplaced ).\n"));
2765 else if (in->ptr[src] == '@')
2767 /* Sub in the macro invocation number */
2771 sprintf (buffer, "%05d", number);
2772 sb_add_string (&out, buffer);
2774 else if (in->ptr[src] == '&')
2776 /* This is a preprocessor variable name, we don't do them
2778 sb_add_char (&out, '\\');
2779 sb_add_char (&out, '&');
2785 src = sub_actual (src, in, &t, m, '\'', &out);
2790 sb_add_char (&out, in->ptr[src++]);
2793 include_buf (name, &out, include_macro, include_next_index ());
2806 /* The macro name must be the first thing on the line */
2812 idx = get_token (idx, in, &name);
2816 /* Got a name, look it up */
2818 ptr = hash_lookup (¯o_table, &name);
2822 /* It's in the table, copy out the stuff and convert any macro args */
2823 macro_expand (&name, idx, in, ptr->value.m);
2835 /* STRING HANDLING */
2838 getstring (idx, in, acc)
2843 idx = sb_skip_white (idx, in);
2845 while (idx < in->len
2846 && (in->ptr[idx] == '"' || in->ptr[idx] == '<'))
2848 if (in->ptr[idx] == '<')
2852 idx = exp_get_abs ("Character code in string must be absolute expression.\n",
2854 sb_add_char (acc, code);
2856 if (in->ptr[idx] != '>')
2857 ERROR ((stderr, "Missing > for character code.\n"));
2860 else if (in->ptr[idx] == '"')
2863 while (idx < in->len)
2865 if (in->ptr[idx] == '"')
2868 if (idx >= in->len || in->ptr[idx] != '"')
2871 sb_add_char (acc, in->ptr[idx]);
2880 /* .SDATA[C|Z] <string> */
2884 do_sdata (idx, in, type)
2892 fprintf (outfile, ".byte\t");
2894 while (idx < in->len)
2898 idx = sb_skip_white (idx, in);
2899 while ((in->ptr[idx] == '"'
2900 || in->ptr[idx] == '<')
2903 idx = getstring (idx, in, &acc);
2908 ERROR ((stderr, "string for SDATAC longer than 255 characters (%d).\n", acc.len));
2910 fprintf (outfile, "%d", acc.len);
2914 for (i = 0; i < acc.len; i++)
2918 fprintf (outfile, ",");
2920 fprintf (outfile, "%d", acc.ptr[i]);
2927 fprintf (outfile, ",");
2928 fprintf (outfile, "0");
2930 idx = sb_skip_white (idx, in);
2932 if (in->ptr[idx] != ',' && idx != in->len)
2934 fprintf (outfile, "\n");
2935 ERROR ((stderr, "illegal character in SDATA line (0x%x).\n", in->ptr[idx]));
2941 fprintf (outfile, "\n");
2944 /* .SDATAB <count> <string> */
2956 idx = exp_get_abs ("Must have absolute SDATAB repeat count.\n", idx, in, &repeat);
2959 ERROR ((stderr, "Must have positive SDATAB repeat count (%d).\n", repeat));
2963 idx = sb_skip_comma (idx, in);
2964 idx = getstring (idx, in, &acc);
2966 for (i = 0; i < repeat; i++)
2969 fprintf (outfile, "\t");
2970 fprintf (outfile, ".byte\t");
2972 fprintf (outfile, "\n");
2982 FILE *newone = fopen (name, "r");
2986 if (isp == MAX_INCLUDES)
2987 FATAL ((stderr, "Unreasonable include depth (%d).\n", isp));
2990 sp->handle = newone;
2993 sb_add_string (&sp->name, name);
2996 sp->pushback_index = 0;
2997 sp->type = include_file;
2999 sb_new (&sp->pushback);
3004 do_include (idx, in)
3011 idx = getstring (idx, in, &t);
3012 text = sb_name (&t);
3013 if (!new_file (text))
3015 FATAL ((stderr, "Can't open include file `%s'.\n", text));
3023 if (sp != include_stack)
3026 fclose (sp->handle);
3031 /* Get the next character from the include stack. If there's anything
3032 in the pushback buffer, take that first. If we're at eof, pop from
3033 the stack and try again. Keep the linecount up to date. */
3040 if (sp->pushback.len != sp->pushback_index)
3042 r = (char) (sp->pushback.ptr[sp->pushback_index++]);
3043 /* When they've all gone, reset the pointer */
3044 if (sp->pushback_index == sp->pushback.len)
3046 sp->pushback.len = 0;
3047 sp->pushback_index = 0;
3050 else if (sp->handle)
3052 r = getc (sp->handle);
3057 if (r == EOF && isp)
3061 while (r == EOF && isp)
3079 return sp->linecount;
3083 include_next_index ()
3087 && index > MAX_REASONABLE)
3088 FATAL ((stderr, "Unreasonable expansion (-u turns off check).\n"));
3093 /* Initialize the chartype vector. */
3099 for (x = 0; x < 256; x++)
3101 if (isalpha (x) || x == '_' || x == '$')
3102 chartype[x] |= FIRSTBIT;
3104 if (isdigit (x) || isalpha (x) || x == '_' || x == '$')
3105 chartype[x] |= NEXTBIT;
3107 if (x == ' ' || x == '\t' || x == ',' || x == '"' || x == ';'
3108 || x == '"' || x == '<' || x == '>' || x == ')' || x == '(')
3109 chartype[x] |= SEPBIT;
3111 if (x == ' ' || x == '\t')
3112 chartype[x] |= WHITEBIT;
3117 /* What to do with all the keywords */
3118 #define PROCESS 0x1000 /* Run substitution over the line */
3119 #define LAB 0x2000 /* Spit out the label */
3121 #define K_EQU PROCESS|1
3122 #define K_ASSIGN PROCESS|2
3123 #define K_REG PROCESS|3
3124 #define K_ORG PROCESS|4
3125 #define K_RADIX PROCESS|5
3126 #define K_DATA LAB|PROCESS|6
3127 #define K_DATAB LAB|PROCESS|7
3128 #define K_SDATA LAB|PROCESS|8
3129 #define K_SDATAB LAB|PROCESS|9
3130 #define K_SDATAC LAB|PROCESS|10
3131 #define K_SDATAZ LAB|PROCESS|11
3132 #define K_RES LAB|PROCESS|12
3133 #define K_SRES LAB|PROCESS|13
3134 #define K_SRESC LAB|PROCESS|14
3135 #define K_SRESZ LAB|PROCESS|15
3136 #define K_EXPORT LAB|PROCESS|16
3137 #define K_GLOBAL LAB|PROCESS|17
3138 #define K_PRINT LAB|PROCESS|19
3139 #define K_FORM LAB|PROCESS|20
3140 #define K_HEADING LAB|PROCESS|21
3141 #define K_PAGE LAB|PROCESS|22
3142 #define K_IMPORT LAB|PROCESS|23
3143 #define K_PROGRAM LAB|PROCESS|24
3144 #define K_END PROCESS|25
3145 #define K_INCLUDE PROCESS|26
3146 #define K_IGNORED PROCESS|27
3147 #define K_ASSIGNA 28
3148 #define K_ASSIGNC 29
3149 #define K_AIF PROCESS|30
3150 #define K_AELSE PROCESS|31
3151 #define K_AENDI PROCESS|32
3152 #define K_AREPEAT PROCESS|33
3153 #define K_AENDR PROCESS|34
3155 #define K_AENDW PROCESS|36
3157 #define K_MACRO PROCESS|38
3159 #define K_ALIGN PROCESS|LAB|40
3170 { "EQU", K_EQU, 0 },
3171 { "ASSIGN", K_ASSIGN, 0 },
3172 { "REG", K_REG, 0 },
3173 { "ORG", K_ORG, 0 },
3174 { "RADIX", K_RADIX, 0 },
3175 { "DATA", K_DATA, 0 },
3176 { "DATAB", K_DATAB, 0 },
3177 { "SDATA", K_SDATA, 0 },
3178 { "SDATAB", K_SDATAB, 0 },
3179 { "SDATAZ", K_SDATAZ, 0 },
3180 { "SDATAC", K_SDATAC, 0 },
3181 { "RES", K_RES, 0 },
3182 { "SRES", K_SRES, 0 },
3183 { "SRESC", K_SRESC, 0 },
3184 { "SRESZ", K_SRESZ, 0 },
3185 { "EXPORT", K_EXPORT, 0 },
3186 { "GLOBAL", K_GLOBAL, 0 },
3187 { "PRINT", K_PRINT, 0 },
3188 { "FORM", K_FORM, 0 },
3189 { "HEADING", K_HEADING, 0 },
3190 { "PAGE", K_PAGE, 0 },
3191 { "PROGRAM", K_IGNORED, 0 },
3192 { "END", K_END, 0 },
3193 { "INCLUDE", K_INCLUDE, 0 },
3194 { "ASSIGNA", K_ASSIGNA, 0 },
3195 { "ASSIGNC", K_ASSIGNC, 0 },
3196 { "AIF", K_AIF, 0 },
3197 { "AELSE", K_AELSE, 0 },
3198 { "AENDI", K_AENDI, 0 },
3199 { "AREPEAT", K_AREPEAT, 0 },
3200 { "AENDR", K_AENDR, 0 },
3201 { "EXITM", K_EXITM, 0 },
3202 { "MACRO", K_MACRO, 0 },
3203 { "ENDM", K_ENDM, 0 },
3204 { "AWHILE", K_AWHILE, 0 },
3205 { "ALIGN", K_ALIGN, 0 },
3206 { "AENDW", K_AENDW, 0 },
3210 /* Look for a pseudo op on the line. If one's there then call
3214 process_pseudo_op (idx, line, acc)
3219 char *in = line->ptr + idx;
3223 /* Scan forward and find pseudo name */
3230 while (idx < line->len && *e && ISFIRSTCHAR (*e))
3232 sb_add_char (acc, *e);
3237 ptr = hash_lookup (&keyword_hash_table, acc);
3241 WARNING ((stderr, "Unrecognised pseudo op `%s'.\n", sb_name (acc)));
3244 if (ptr->value.i & LAB)
3245 { /* output the label */
3248 fprintf (outfile, "%s:\t", sb_name (&label));
3251 fprintf (outfile, "\t");
3254 if (ptr->value.i & PROCESS)
3256 /* Polish the rest of the line before handling the pseudo op */
3257 /* strip_comments(line);*/
3259 process_assigns (idx, line, acc);
3261 change_base (0, acc, line);
3266 switch (ptr->value.i)
3279 switch (ptr->value.i)
3288 ERROR ((stderr, "ORG command not allowed.\n"));
3294 do_data (idx, line);
3297 do_datab (idx, line);
3300 do_sdata (idx, line, 0);
3303 do_sdatab (idx, line);
3306 do_sdata (idx, line, 'c');
3309 do_sdata (idx, line, 'z');
3312 do_assign (1, 0, line);
3318 do_arepeat (idx, line);
3324 do_awhile (idx, line);
3330 do_assign (0, idx, line);
3333 do_align (idx, line);
3336 do_res (idx, line, 0);
3339 do_res (idx, line, 's');
3342 do_include (idx, line);
3345 do_macro (idx, line);
3351 do_res (idx, line, 'c');
3354 do_print (idx, line);
3357 do_form (idx, line);
3360 do_heading (idx, line);
3372 do_res (idx, line, 'z');
3380 do_assigna (idx, line);
3383 do_assignc (idx, line);
3399 /* Build the keyword hash table - put each keyword in the table twice,
3400 once upper and once lower case.*/
3407 for (i = 0; kinfo[i].name; i++)
3412 sb_add_string (&label, kinfo[i].name);
3414 hash_add_to_int_table (&keyword_hash_table, &label, kinfo[i].code);
3417 for (j = 0; kinfo[i].name[j]; j++)
3418 sb_add_char (&label, kinfo[i].name[j] - 'A' + 'a');
3419 hash_add_to_int_table (&keyword_hash_table, &label, kinfo[i].code);
3439 hash_new_table (101, ¯o_table);
3440 hash_new_table (101, &keyword_hash_table);
3441 hash_new_table (101, &assign_hash_table);
3442 hash_new_table (101, &vars);
3447 /* Find the output file */
3448 for (i = 1; i < ac; i++)
3450 if (av[i][0] == '-')
3452 if (av[i][1] == 'c' && av[i][2] == 0)
3456 else if (av[i][1] == 'p' && av[i][2] == 0)
3458 print_line_number = 1;
3460 else if (av[i][1] == 'u' && av[i][2] == 0)
3464 else if (av[i][1] == 's' && av[i][2] == 0)
3468 else if (av[i][1] == 'o' && av[i][2] == 0 & i + 1 < ac)
3470 /* Got output file name */
3472 outfile = fopen (av[i], "w");
3475 fprintf (stderr, "%s: Can't open output file `%s'.\n",
3482 fprintf (stderr, "Usage: %s [-o filename] infile1 infile2...\n",
3492 /* Process all the input files */
3494 for (i = 1; i < ac; i++)
3496 if (av[i][0] == '-')
3498 if (av[i][1] == 'o')
3503 if (new_file (av[i]))
3509 fprintf (stderr, "%s: Can't open input file `%s'.\n",