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
40 #define MAX_INCLUDES 30 /* Maximum include depth */
41 #define MAX_REASONABLE 1000 /* Maximum number of expansions */
43 int unreasonable
; /* -u on command line */
44 int stats
; /* -s on command line */
45 int print_line_number
; /* -p flag on command line */
46 int copysource
; /* -c flag on command line */
47 int warnings
; /* Number of WARNINGs generated so far. */
48 int errors
; /* Number of ERRORs generated so far. */
49 int fatals
; /* Number of fatal ERRORs generated so far (either 0 or 1). */
53 int radix
= 10; /* Default radix */
55 int had_end
; /* Seen .END */
57 /* The output stream */
61 /* Forward declarations. */
62 static int condass_lookup_name();
63 static int condass_on();
65 static int get_and_process();
66 static int get_token();
67 static int getstring();
68 static int include_next_index();
69 static int macro_op();
70 static int linecount();
71 static int process_pseudo_op();
72 static void include_pop();
73 static void include_print_where_line();
76 I had a couple of choices when deciding upon this data structure.
77 gas uses null terminated strings for all its internal work. This
78 often means that parts of the program that want to examine
79 substrings have to manipulate the data in the string to do the
80 right thing (a common operation is to single out a bit of text by
81 saving away the character after it, nulling it out, operating on
82 the substring and then replacing the character which was under the
83 null). This is a pain and I remember a load of problems that I had with
84 code in gas which almost got this right. Also, it's harder to grow and
85 allocate null terminated strings efficiently.
87 Obstacks provide all the functionality needed, but are too
88 complicated, hence the sb.
90 An sb is allocated by the caller, and is initialzed to point to an
91 sb_element. sb_elements are kept on a free lists, and used when
92 needed, replaced onto the free list when unused.
95 #define max_power_two 30 /* don't allow strings more than
96 2^max_power_two long */
97 /* structure of an sb */
100 char *ptr
; /* points to the current block. */
101 int len
; /* how much is used. */
102 int pot
; /* the maximum length is 1<<pot */
107 /* Structure of the free list object of an sb */
119 sb_element
*size
[max_power_two
];
122 sb_list_vector free_list
;
124 int string_count
[max_power_two
];
126 /* the attributes of each character are stored as a bit pattern
127 chartype, which gives us quick tests. */
134 #define ISFIRSTCHAR(x) (chartype[(unsigned)(x)] & FIRSTBIT)
135 #define ISNEXTCHAR(x) (chartype[(unsigned)(x)] & NEXTBIT)
136 #define ISSEP(x) (chartype[(unsigned)(x)] & SEPBIT)
137 #define ISWHITE(x) (chartype[(unsigned)(x)] & WHITEBIT)
139 static char chartype
[256];
142 /* Conditional assembly uses the `ifstack'. Each aif pushes another
143 entry onto the stack, and sets the on flag if it should. The aelse
144 sets hadelse, and toggles on. An aend pops a level. We limit to
145 100 levels of nesting, not because we're facists pigs with read
146 only minds, but because more than 100 levels of nesting is probably
147 a bug in the user's macro structure. */
149 #define IFNESTING 100
152 int on
; /* is the level being output */
153 int hadelse
; /* has an aelse been seen */
158 /* The final and intermediate results of expression evaluation are kept in
159 exp_t's. Note that a symbol is not an sb, but a pointer into the input
160 line. It must be coped somewhere safe before the next line is read in. */
171 int value
; /* constant part */
172 symbol add_symbol
; /* name part */
173 symbol sub_symbol
; /* name part */
178 /* Hashing is done in a pretty standard way. A hash_table has a
179 pointer to a vector of pointers to hash_entrys, and the size of the
180 vector. A hash_entry contains a union of all the info we like to
181 store in hash table. If there is a hash collision, hash_entries
182 with the same hash are kept in a chain. */
184 /* What the data in a hash_entry means */
187 hash_integer
, /* name->integer mapping */
188 hash_string
, /* name->string mapping */
189 hash_macro
, /* name is a macro */
190 hash_formal
/* name is a formal argument */
195 sb key
; /* symbol name */
196 hash_type type
; /* symbol meaning */
201 struct macro_struct
*m
;
202 struct formal_struct
*f
;
204 struct hs
*next
; /* next hash_entry with same hash key */
214 /* Structures used to store macros.
216 Each macro knows its name and included text. It gets built with a
217 list of formal arguments, and also keeps a hash table which points
218 into the list to speed up formal search. Each formal knows its
219 name and its default value. Each time the macro is expanded, the
220 formals get the actual values attatched to them. */
222 /* describe the formal arguments to a macro */
224 typedef struct formal_struct
226 struct formal_struct
*next
; /* next formal in list */
227 sb name
; /* name of the formal */
228 sb def
; /* the default value */
229 sb actual
; /* the actual argument (changed on each expansion) */
230 int index
; /* the index of the formal 0..formal_count-1 */
234 /* describe the macro. */
236 typedef struct macro_struct
238 sb sub
; /* substitution text. */
239 int formal_count
; /* number of formal args. */
240 formal_entry
*formals
; /* pointer to list of formal_structs */
241 hash_table formal_hash
; /* hash table of formals. */
245 /* how we nest files and expand macros etc.
247 we keep a stack of of include_stack structs. each include file
248 pushes a new level onto the stack. we keep an sb with a pushback
249 too. unget chars are pushed onto the pushback sb, getchars first
250 checks the pushback sb before reading from the input stream.
252 small things are expanded by adding the text of the item onto the
253 pushback sb. larger items are grown by pushing a new level and
254 allocating the entire pushback buf for the item. each time
255 something like a macro is expanded, the stack index is changed. we
256 can then perform an exitm by popping all entries off the stack with
257 the same stack index. if we're being reasonable, we can detect
258 recusive expansion by checking the index is reasonably small.
263 include_file
, include_repeat
, include_while
, include_macro
268 sb pushback
; /* current pushback stream */
269 int pushback_index
; /* next char to read from stream */
270 FILE *handle
; /* open file */
271 sb name
; /* name of file */
272 int linecount
; /* number of lines read so far */
274 int index
; /* index of this layer */
276 include_stack
[MAX_INCLUDES
];
278 struct include_stack
*sp
;
279 #define isp (sp - include_stack)
284 void include_print_where_line ();
288 do { include_print_where_line (stderr); fprintf x ; fatals++; quit(); } while(0)
290 do { include_print_where_line (stderr); fprintf x; errors++; } while(0)
292 do { include_print_where_line (stderr); fprintf x; warnings++;} while(0)
296 /* exit the program and return the right ERROR code. */
309 for (i
= 0; i
< max_power_two
; i
++)
311 fprintf (stderr
, "strings size %8d : %d\n", 1<<i
, string_count
[i
]);
322 char *p
= malloc (x
);
324 FATAL ((stderr
, "out of memory\n"));
329 /* this program is about manipulating strings.
330 they are managed in things called `sb's which is an abbreviation
331 for string buffers. an sb has to be created, things can be glued
332 on to it, and at the end of it's life it should be freed. the
333 contents should never be pointed at whilst it is still growing,
334 since it could be moved at any time
338 sb_grow... (&foo,...);
344 /* initializes an sb. */
351 /* see if we can find one to allocate */
354 if (size
> max_power_two
)
356 FATAL ((stderr
, "string longer than %d bytes requested.\n",
357 1 << max_power_two
));
359 e
= free_list
.size
[size
];
362 /* nothing there, allocate one and stick into the free list */
363 e
= (sb_element
*) xmalloc (sizeof (sb_element
) + (1 << size
));
364 e
->next
= free_list
.size
[size
];
366 free_list
.size
[size
] = e
;
367 string_count
[size
]++;
370 /* remove from free list */
372 free_list
.size
[size
] = e
->next
;
374 /* copy into callers world */
386 sb_build (ptr
, dsize
);
389 /* deallocate the sb at ptr */
396 /* return item to free list */
397 ptr
->item
->next
= free_list
.size
[ptr
->pot
];
398 free_list
.size
[ptr
->pot
] = ptr
->item
;
401 /* add the sb at s to the end of the sb at ptr */
403 static void sb_check ();
411 sb_check (ptr
, s
->len
);
412 memcpy (ptr
->ptr
+ ptr
->len
, s
->ptr
, s
->len
);
416 /* make sure that the sb at ptr has room for another len characters,
417 and grow it if it doesn't. */
424 if (ptr
->len
+ len
>= 1 << ptr
->pot
)
428 while (ptr
->len
+ len
>= 1 << pot
)
430 sb_build (&tmp
, pot
);
431 sb_add_sb (&tmp
, ptr
);
437 /* make the sb at ptr point back to the beginning. */
446 /* add character c to the end of the sb at ptr. */
454 ptr
->ptr
[ptr
->len
++] = c
;
457 /* add null terminated string s to the end of sb at ptr. */
460 sb_add_string (ptr
, s
)
464 int len
= strlen (s
);
466 memcpy (ptr
->ptr
+ ptr
->len
, s
, len
);
470 /* add string at s of length len to sb at ptr */
473 sb_add_buffer (ptr
, s
, len
)
479 memcpy (ptr
->ptr
+ ptr
->len
, s
, len
);
484 /* print the sb at ptr to the output file */
494 for (i
= 0; i
< ptr
->len
; i
++)
498 fprintf (outfile
, ",");
500 fprintf (outfile
, "%d", ptr
->ptr
[i
]);
505 /* put a null at the end of the sb at in and return the start of the
506 string, so that it can be used as an arg to printf %s. */
513 /* stick a null on the end of the string */
518 /* start at the index idx into the string in sb at ptr and skip
519 whitespace. return the index of the first non whitespace character */
522 sb_skip_white (idx
, ptr
)
526 while (idx
< ptr
->len
&& ISWHITE (ptr
->ptr
[idx
]))
531 /* start at the index idx into the sb at ptr. skips whitespace,
532 a comma and any following whitespace. returnes the index of the
536 sb_skip_comma (idx
, ptr
)
540 while (idx
< ptr
->len
&& ISWHITE (ptr
->ptr
[idx
]))
544 && ptr
->ptr
[idx
] == ',')
547 while (idx
< ptr
->len
&& ISWHITE (ptr
->ptr
[idx
]))
554 /* hash table maintenance. */
556 /* build a new hash table with size buckets, and fill in the info at ptr. */
559 hash_new_table (size
, ptr
)
564 ptr
->table
= (hash_entry
**) xmalloc (size
* (sizeof (hash_entry
*)));
567 /* calculate and return the hash value of the sb at key. */
576 for (i
= 0; i
< key
->len
; i
++)
584 /* lookup key in hash_table tab, if present, then return it, otherwise
585 build a new one and fill it with hash_integer. */
589 hash_create (tab
, key
)
593 int k
= hash (key
) % tab
->size
;
595 hash_entry
**table
= tab
->table
;
603 hash_entry
*n
= (hash_entry
*) xmalloc (sizeof (hash_entry
));
606 sb_add_sb (&n
->key
, key
);
608 n
->type
= hash_integer
;
611 if (strncmp (table
[k
]->key
.ptr
, key
->ptr
, key
->len
) == 0)
619 /* add sb name with key into hash_table tab. if replacing old value
620 and again, then ERROR. */
624 hash_add_to_string_table (tab
, key
, name
, again
)
630 hash_entry
*ptr
= hash_create (tab
, key
);
631 if (ptr
->type
== hash_integer
)
633 sb_new (&ptr
->value
.s
);
635 if (ptr
->value
.s
.len
)
638 ERROR ((stderr
, "redefintion not allowed"));
640 sb_reset (&ptr
->value
.s
);
641 sb_add_sb (&ptr
->value
.s
, name
);
644 /* add integer name to hash_table tab with sb key. */
648 hash_add_to_int_table (tab
, key
, name
)
653 hash_entry
*ptr
= hash_create (tab
, key
);
657 /* lookup sb key in hash_table tab. if found return hash_entry result,
662 hash_lookup (tab
, key
)
666 int k
= hash (key
) % tab
->size
;
667 hash_entry
**table
= tab
->table
;
668 hash_entry
*p
= table
[k
];
671 if (p
->key
.len
== key
->len
672 && strncmp (p
->key
.ptr
, key
->ptr
, key
->len
) == 0)
682 are handled in a really simple recursive decent way. each bit of
683 the machine takes an index into an sb and a pointer to an exp_t,
684 modifies the *exp_t and returns the index of the first character
685 past the part of the expression parsed.
687 expression precedence:
698 /* make sure that the exp_t at term is constant, if not the give the op ERROR. */
702 checkconst (op
, term
)
706 if (term
->add_symbol
.len
707 || term
->sub_symbol
.len
)
709 ERROR ((stderr
, "the %c operator cannot take non-absolute arguments.\n", op
));
713 /* turn the number in string at idx into a number of base,
714 fill in ptr and return the index of the first character not in the
719 sb_strtol (idx
, string
, base
, ptr
)
726 idx
= sb_skip_white (idx
, string
);
728 while (idx
< string
->len
)
730 int ch
= string
->ptr
[idx
];
734 else if (ch
>= 'a' && ch
<= 'f')
736 else if (ch
>= 'a' && ch
<= 'f')
744 value
= value
* base
+ dig
;
751 static int level_5 ();
754 level_0 (idx
, string
, lhs
)
759 lhs
->add_symbol
.len
= 0;
760 lhs
->add_symbol
.name
= 0;
762 lhs
->sub_symbol
.len
= 0;
763 lhs
->sub_symbol
.name
= 0;
765 idx
= sb_skip_white (idx
, string
);
769 if (isdigit (string
->ptr
[idx
]))
771 idx
= sb_strtol (idx
, string
, 10, &lhs
->value
);
773 else if (ISFIRSTCHAR (string
->ptr
[idx
]))
776 lhs
->add_symbol
.name
= string
->ptr
+ idx
;
777 while (idx
< string
->len
&& ISNEXTCHAR (string
->ptr
[idx
]))
782 lhs
->add_symbol
.len
= len
;
784 else if (string
->ptr
[idx
] == '"')
788 ERROR ((stderr
, "string where expression expected.\n"));
789 idx
= getstring (idx
, string
, &acc
);
794 ERROR ((stderr
, "can't find primary in expression.\n"));
797 return sb_skip_white (idx
, string
);
803 level_1 (idx
, string
, lhs
)
808 idx
= sb_skip_white (idx
, string
);
810 switch (string
->ptr
[idx
])
813 idx
= level_1 (idx
+ 1, string
, lhs
);
816 idx
= level_1 (idx
+ 1, string
, lhs
);
817 checkconst ('~', lhs
);
818 lhs
->value
= ~lhs
->value
;
823 idx
= level_1 (idx
+ 1, string
, lhs
);
824 lhs
->value
= -lhs
->value
;
826 lhs
->add_symbol
= lhs
->sub_symbol
;
832 idx
= level_5 (sb_skip_white (idx
, string
), string
, lhs
);
833 if (string
->ptr
[idx
] != ')')
834 ERROR ((stderr
, "misplaced closing parens.\n"));
839 idx
= level_0 (idx
, string
, lhs
);
842 return sb_skip_white (idx
, string
);
846 level_2 (idx
, string
, lhs
)
853 idx
= level_1 (idx
, string
, lhs
);
855 while (idx
< string
->len
&& (string
->ptr
[idx
] == '*'
856 || string
->ptr
[idx
] == '/'))
858 char op
= string
->ptr
[idx
++];
859 idx
= level_1 (idx
, string
, &rhs
);
863 checkconst ('*', lhs
);
864 checkconst ('*', &rhs
);
865 lhs
->value
*= rhs
.value
;
868 checkconst ('/', lhs
);
869 checkconst ('/', &rhs
);
871 ERROR ((stderr
, "attempt to divide by zero.\n"));
873 lhs
->value
/= rhs
.value
;
877 return sb_skip_white (idx
, string
);
882 level_3 (idx
, string
, lhs
)
889 idx
= level_2 (idx
, string
, lhs
);
891 while (idx
< string
->len
892 && (string
->ptr
[idx
] == '+'
893 || string
->ptr
[idx
] == '-'))
895 char op
= string
->ptr
[idx
++];
896 idx
= level_2 (idx
, string
, &rhs
);
900 lhs
->value
+= rhs
.value
;
901 if (lhs
->add_symbol
.name
&& rhs
.add_symbol
.name
)
903 ERROR ((stderr
, "can't add two relocatable expressions\n"));
905 /* change nn+symbol to symbol + nn */
906 if (rhs
.add_symbol
.name
)
908 lhs
->add_symbol
= rhs
.add_symbol
;
912 lhs
->value
-= rhs
.value
;
913 lhs
->sub_symbol
= rhs
.add_symbol
;
917 return sb_skip_white (idx
, string
);
921 level_4 (idx
, string
, lhs
)
928 idx
= level_3 (idx
, string
, lhs
);
930 while (idx
< string
->len
&&
931 string
->ptr
[idx
] == '&')
933 char op
= string
->ptr
[idx
++];
934 idx
= level_3 (idx
, string
, &rhs
);
938 checkconst ('&', lhs
);
939 checkconst ('&', &rhs
);
940 lhs
->value
&= rhs
.value
;
944 return sb_skip_white (idx
, string
);
948 level_5 (idx
, string
, lhs
)
955 idx
= level_4 (idx
, string
, lhs
);
957 while (idx
< string
->len
958 && (string
->ptr
[idx
] == '|' || string
->ptr
[idx
] == '~'))
960 char op
= string
->ptr
[idx
++];
961 idx
= level_4 (idx
, string
, &rhs
);
965 checkconst ('|', lhs
);
966 checkconst ('|', &rhs
);
967 lhs
->value
|= rhs
.value
;
970 checkconst ('~', lhs
);
971 checkconst ('~', &rhs
);
972 lhs
->value
^= rhs
.value
;
976 return sb_skip_white (idx
, string
);
980 /* parse the expression at offset idx into string, fill up res with
981 the result. return the index of the first char past the expression.
985 exp_parse (idx
, string
, res
)
990 return level_5 (sb_skip_white (idx
, string
), string
, res
);
994 /* turn the expression at exp into text and glue it onto the end of
998 exp_string (exp
, string
)
1006 if (exp
->add_symbol
.len
)
1008 sb_add_buffer (string
, exp
->add_symbol
.name
, exp
->add_symbol
.len
);
1016 sb_add_char (string
, '+');
1017 sprintf (buf
, "%d", exp
->value
);
1018 sb_add_string (string
, buf
);
1022 if (exp
->sub_symbol
.len
)
1024 sb_add_char (string
, '-');
1025 sb_add_buffer (string
, exp
->add_symbol
.name
, exp
->add_symbol
.len
);
1031 sb_add_char (string
, '0');
1035 /* parse the expression at offset idx into sb in, return the value in val.
1036 if the expression is not constant, give ERROR emsg. returns the index
1037 of the first character past the end of the expression. */
1040 exp_get_abs (emsg
, idx
, in
, val
)
1047 idx
= exp_parse (idx
, in
, &res
);
1048 if (res
.add_symbol
.len
|| res
.sub_symbol
.len
)
1049 ERROR ((stderr
, emsg
));
1055 sb label
; /* current label parsed from line */
1056 hash_table assign_hash_table
; /* hash table for all assigned variables */
1057 hash_table keyword_hash_table
; /* hash table for keyword */
1058 hash_table vars
; /* hash table for eq variables */
1060 #define in_comment ';'
1064 strip_comments (out
)
1069 for (i
= 0; i
< out
->len
; i
++)
1071 if (s
[i
] == in_comment
)
1080 /* push back character ch so that it can be read again. */
1090 if (sp
->pushback_index
)
1091 sp
->pushback_index
--;
1093 sb_add_char (&sp
->pushback
, ch
);
1096 /* push the sb ptr onto the include stack, with the given name, type and index. */
1100 include_buf (name
, ptr
, type
, index
)
1107 if (sp
- include_stack
>= MAX_INCLUDES
)
1108 FATAL ((stderr
, "unreasonable nesting.\n"));
1110 sb_add_sb (&sp
->name
, name
);
1113 sp
->pushback_index
= 0;
1116 sb_new (&sp
->pushback
);
1117 sb_add_sb (&sp
->pushback
, ptr
);
1121 /* used in ERROR messages, print info on where the include stack is onto file. */
1124 include_print_where_line (file
)
1127 struct include_stack
*p
= include_stack
+ 1;
1131 fprintf (file
, "%s:%d ", sb_name (&p
->name
), p
->linecount
- ((p
== sp
) ? 1 : 0));
1136 /* used in listings, print the line number onto file. */
1138 include_print_line (file
)
1142 struct include_stack
*p
= include_stack
+ 1;
1144 n
= fprintf (file
, "%4d", p
->linecount
);
1148 n
+= fprintf (file
, ".%d", p
->linecount
);
1153 fprintf (file
, " ");
1159 /* read a line from the top of the include stack into sb in. */
1170 putc ('!', outfile
);
1171 if (print_line_number
)
1172 include_print_line (outfile
);
1186 WARNING ((stderr
, "end of file not at start of line.\n"));
1188 putc ('\n', outfile
);
1205 /* continued line */
1208 putc ('!', outfile
);
1209 putc ('+', outfile
);
1222 sb_add_char (in
, ch
);
1230 /* find a label from sb in and put it in out. */
1233 grab_label (in
, out
)
1239 if (ISFIRSTCHAR (in
->ptr
[i
]))
1241 sb_add_char (out
, in
->ptr
[i
]);
1243 while (ISNEXTCHAR (in
->ptr
[i
]) && i
< in
->len
)
1245 sb_add_char (out
, in
->ptr
[i
]);
1252 /* find all strange base stuff and turn into decimal. also
1253 find all the other numbers and convert them from the default radix */
1256 change_base (idx
, in
, out
)
1263 while (idx
< in
->len
)
1265 if (idx
< in
->len
- 1 && in
->ptr
[idx
+ 1] == '\'')
1269 switch (in
->ptr
[idx
])
1288 ERROR ((stderr
, "Illegal base character %c.\n", in
->ptr
[idx
]));
1293 idx
= sb_strtol (idx
+ 2, in
, base
, &value
);
1294 sprintf (buffer
, "%d", value
);
1295 sb_add_string (out
, buffer
);
1297 else if (ISFIRSTCHAR (in
->ptr
[idx
]))
1299 /* copy entire names through quickly */
1300 sb_add_char (out
, in
->ptr
[idx
]);
1302 while (idx
< in
->len
&& ISNEXTCHAR (in
->ptr
[idx
]))
1304 sb_add_char (out
, in
->ptr
[idx
]);
1308 else if (isdigit (in
->ptr
[idx
]))
1311 /* all numbers must start with a digit, let's chew it and
1313 idx
= sb_strtol (idx
, in
, radix
, &value
);
1314 sprintf (buffer
, "%d", value
);
1315 sb_add_string (out
, buffer
);
1317 /* skip all undigsested letters */
1318 while (idx
< in
->len
&& ISNEXTCHAR (in
->ptr
[idx
]))
1320 sb_add_char (out
, in
->ptr
[idx
]);
1326 /* nothing special, just pass it through */
1327 sb_add_char (out
, in
->ptr
[idx
]);
1344 do_assign (again
, idx
, in
)
1349 /* stick label in symbol table with following value */
1354 idx
= exp_parse (idx
, in
, &e
);
1355 exp_string (&e
, &acc
);
1356 hash_add_to_string_table (&assign_hash_table
, &label
, &acc
, again
);
1361 /* .radix [b|q|d|h] */
1368 int idx
= sb_skip_white (0, ptr
);
1369 switch (ptr
->ptr
[idx
])
1388 ERROR ((stderr
, "radix is %c must be one of b, q, d or h", radix
));
1393 /* Parse off a .b, .w or .l */
1396 get_opsize (idx
, in
, size
)
1402 if (in
->ptr
[idx
] == '.')
1405 switch (in
->ptr
[idx
])
1420 ERROR ((stderr
, "size must be one of b, w or l, is %c.\n", in
->ptr
[idx
]));
1428 /* .data [.b|.w|.l] <data>* */
1440 idx
= get_opsize (idx
, in
, &opsize
);
1455 fprintf (outfile
, "%s\t", opname
);
1456 while (idx
< in
->len
)
1459 idx
= exp_parse (idx
, in
, &e
);
1460 exp_string (&e
, &acc
);
1461 sb_add_char (&acc
, 0);
1462 fprintf (outfile
, acc
.ptr
);
1463 if (idx
< in
->len
&& in
->ptr
[idx
] == ',')
1465 fprintf (outfile
, ",");
1470 fprintf (outfile
, "\n");
1473 /* .datab [.b|.w|.l] <repeat>,<fill> */
1484 idx
= get_opsize (idx
, in
, &opsize
);
1486 idx
= exp_get_abs ("datab repeat must be constant.\n", idx
, in
, &repeat
);
1487 idx
= sb_skip_comma (idx
, in
);
1488 idx
= exp_get_abs ("datab data must be absolute.\n", idx
, in
, &fill
);
1490 fprintf (outfile
, ".fill\t%d,%d,%d\n", repeat
, opsize
, fill
);
1501 idx
= exp_get_abs ("align needs absolute expression.\n", idx
, in
, &al
);
1506 WARNING ((stderr
, "alignment must be one of 1, 2 or 4.\n"));
1508 fprintf (outfile
, ".align %d\n", al
);
1511 /* .res[.b|.w|.l] <size> */
1514 do_res (idx
, in
, type
)
1522 idx
= get_opsize (idx
, in
, &size
);
1523 while (idx
< in
->len
)
1525 idx
= sb_skip_white (idx
, in
);
1526 if (in
->ptr
[idx
] == ',')
1528 idx
= exp_get_abs ("res needs absolute expression for fill count.\n", idx
, in
, &count
);
1530 if (type
== 'c' || type
== 'z')
1533 fprintf (outfile
, ".space %d\n", count
* size
);
1544 fprintf (outfile
, ".global %s\n", sb_name (in
));
1547 /* .print [list] [nolist] */
1554 idx
= sb_skip_white (idx
, in
);
1555 while (idx
< in
->len
)
1557 if (strncmp (in
->ptr
+ idx
, "LIST", 4) == 0)
1559 fprintf (outfile
, ".list\n");
1562 else if (strncmp (in
->ptr
+ idx
, "NOLIST", 6) == 0)
1564 fprintf (outfile
, ".nolist\n");
1573 do_heading (idx
, in
)
1579 idx
= getstring (idx
, in
, &head
);
1580 fprintf (outfile
, ".title \"%s\"\n", sb_name (&head
));
1589 fprintf (outfile
, ".eject\n");
1592 /* .form [lin=<value>] [col=<value>] */
1600 idx
= sb_skip_white (idx
, in
);
1602 while (idx
< in
->len
)
1605 if (strncmp (in
->ptr
+ idx
, "LIN=", 4) == 0)
1608 idx
= exp_get_abs ("form LIN= needs absolute expresssion.\n", idx
, in
, &lines
);
1611 if (strncmp (in
->ptr
+ idx
, "COL=", 4) == 0)
1614 idx
= exp_get_abs ("form COL= needs absolute expresssion.\n", idx
, in
, &columns
);
1619 fprintf (outfile
, ".psize %d,%d\n", lines
, columns
);
1624 get_any_string (idx
, in
, out
)
1629 idx
= sb_skip_white (idx
, in
);
1630 if (idx
< in
->len
&& (in
->ptr
[idx
] == '"'
1631 || in
->ptr
[idx
] == '<'))
1632 return getstring (idx
, in
, out
);
1636 while (idx
< in
->len
&& !ISSEP (in
->ptr
[idx
]))
1638 sb_add_char (out
, in
->ptr
[idx
++]);
1644 /* skip along sb in starting at idx, suck off whitespace a ( and more
1645 whitespace. return the idx of the next char */
1648 skip_openp (idx
, in
)
1652 idx
= sb_skip_white (idx
, in
);
1653 if (in
->ptr
[idx
] != '(')
1654 ERROR ((stderr
, "misplaced ( .\n"));
1655 idx
= sb_skip_white (idx
+ 1, in
);
1659 /* skip along sb in starting at idx, suck off whitespace a ) and more
1660 whitespace. return the idx of the next char */
1663 skip_closep (idx
, in
)
1667 idx
= sb_skip_white (idx
, in
);
1668 if (in
->ptr
[idx
] != ')')
1669 ERROR ((stderr
, "misplaced ).\n"));
1670 idx
= sb_skip_white (idx
+ 1, in
);
1677 dolen (idx
, in
, out
)
1686 sb_new (&stringout
);
1687 idx
= skip_openp (idx
, in
);
1688 idx
= get_and_process (idx
, in
, &stringout
);
1689 idx
= skip_closep (idx
, in
);
1690 sprintf (buffer
, "%d", stringout
.len
);
1691 sb_add_string (out
, buffer
);
1693 sb_kill (&stringout
);
1702 doinstr (idx
, in
, out
)
1716 idx
= skip_openp (idx
, in
);
1717 idx
= get_and_process (idx
, in
, &string
);
1718 idx
= sb_skip_comma (idx
, in
);
1719 idx
= get_and_process (idx
, in
, &search
);
1720 idx
= sb_skip_comma (idx
, in
);
1721 if (isdigit (in
->ptr
[idx
]))
1723 idx
= exp_get_abs (".instr needs absolute expresson.\n", idx
, in
, &start
);
1729 idx
= skip_closep (idx
, in
);
1731 for (i
= start
; i
< string
.len
; i
++)
1733 if (strncmp (string
.ptr
+ i
, search
.ptr
, search
.len
) == 0)
1739 sprintf (buffer
, "%d", res
);
1740 sb_add_string (out
, buffer
);
1748 dosubstr (idx
, in
, out
)
1758 idx
= skip_openp (idx
, in
);
1759 idx
= get_and_process (idx
, in
, &string
);
1760 idx
= sb_skip_comma (idx
, in
);
1761 idx
= exp_get_abs ("need absolute position.\n", idx
, in
, &pos
);
1762 idx
= sb_skip_comma (idx
, in
);
1763 idx
= exp_get_abs ("need absolute length.\n", idx
, in
, &len
);
1764 idx
= skip_closep (idx
, in
);
1767 if (len
< 0 || pos
< 0 ||
1769 || pos
+ len
> string
.len
)
1771 sb_add_string (out
, " ");
1775 sb_add_char (out
, '"');
1778 sb_add_char (out
, string
.ptr
[pos
++]);
1781 sb_add_char (out
, '"');
1787 /* scan line, change tokens in the hash table to their replacements */
1789 process_assigns (idx
, in
, buf
)
1794 while (idx
< in
->len
)
1797 if (in
->ptr
[idx
] == '\\'
1798 && in
->ptr
[idx
+ 1] == '&')
1800 idx
= condass_lookup_name (in
, idx
+ 2, buf
);
1802 else if (idx
+ 3 < in
->len
1803 && in
->ptr
[idx
] == '.'
1804 && in
->ptr
[idx
+ 1] == 'L'
1805 && in
->ptr
[idx
+ 2] == 'E'
1806 && in
->ptr
[idx
+ 3] == 'N')
1807 idx
= dolen (idx
+ 4, in
, buf
);
1808 else if (idx
+ 6 < in
->len
1809 && in
->ptr
[idx
] == '.'
1810 && in
->ptr
[idx
+ 1] == 'I'
1811 && in
->ptr
[idx
+ 2] == 'N'
1812 && in
->ptr
[idx
+ 3] == 'S'
1813 && in
->ptr
[idx
+ 4] == 'T'
1814 && in
->ptr
[idx
+ 5] == 'R')
1815 idx
= doinstr (idx
+ 6, in
, buf
);
1816 else if (idx
+ 7 < in
->len
1817 && in
->ptr
[idx
] == '.'
1818 && in
->ptr
[idx
+ 1] == 'S'
1819 && in
->ptr
[idx
+ 2] == 'U'
1820 && in
->ptr
[idx
+ 3] == 'B'
1821 && in
->ptr
[idx
+ 4] == 'S'
1822 && in
->ptr
[idx
+ 5] == 'T'
1823 && in
->ptr
[idx
+ 6] == 'R')
1824 idx
= dosubstr (idx
+ 7, in
, buf
);
1825 else if (ISFIRSTCHAR (in
->ptr
[idx
]))
1827 /* may be a simple name subsitution, see if we have a word */
1830 while (cur
< in
->len
1831 && (ISNEXTCHAR (in
->ptr
[cur
])))
1835 sb_add_buffer (&acc
, in
->ptr
+ idx
, cur
- idx
);
1836 ptr
= hash_lookup (&assign_hash_table
, &acc
);
1839 /* Found a definition for it */
1840 sb_add_sb (buf
, &ptr
->value
.s
);
1844 /* No definition, just copy the word */
1845 sb_add_sb (buf
, &acc
);
1852 sb_add_char (buf
, in
->ptr
[idx
++]);
1858 get_and_process (idx
, in
, out
)
1865 idx
= get_any_string (idx
, in
, &t
);
1866 process_assigns (0, &t
, out
);
1886 more
= get_line (&line
);
1889 /* Find any label and pseudo op that we're intested in */
1894 fprintf (outfile
, "\n");
1899 l
= grab_label (&line
, &label
);
1900 if (line
.ptr
[l
] == ':')
1902 while (ISWHITE (line
.ptr
[l
]) && l
< line
.len
)
1907 if (process_pseudo_op (l
, &line
, &acc
))
1913 else if (condass_on ())
1915 if (macro_op (l
, &line
))
1925 fprintf (outfile
, "%s:\t", sb_name (&label
));
1928 fprintf (outfile
, "\t");
1930 process_assigns (l
, &line
, &t1
);
1932 change_base (0, &t1
, &t2
);
1933 fprintf (outfile
, "%s\n", sb_name (&t2
));
1943 more
= get_line (&line
);
1947 WARNING ((stderr
, ".END missing from end of file.\n"));
1955 free_old_entry (ptr
)
1960 if (ptr
->type
== hash_string
)
1961 sb_kill(&ptr
->value
.s
);
1965 /* name: .ASSIGNA <value> */
1968 do_assigna (idx
, in
)
1976 process_assigns (idx
, in
, &tmp
);
1977 idx
= exp_get_abs (".ASSIGNA needs constant expression argument.\n", 0, &tmp
, &val
);
1981 ERROR ((stderr
, ".ASSIGNA without label.\n"));
1985 hash_entry
*ptr
= hash_create (&vars
, &label
);
1986 free_old_entry (ptr
);
1987 ptr
->type
= hash_integer
;
1993 /* name: .ASSIGNC <string> */
1996 do_assignc (idx
, in
)
2002 idx
= getstring (idx
, in
, &acc
);
2006 ERROR ((stderr
, ".ASSIGNS without label.\n"));
2010 hash_entry
*ptr
= hash_create (&vars
, &label
);
2011 free_old_entry (ptr
);
2012 ptr
->type
= hash_string
;
2013 sb_new (&ptr
->value
.s
);
2014 sb_add_sb (&ptr
->value
.s
, &acc
);
2020 /* name: .REG (reg) */
2027 /* remove reg stuff from inside parens */
2029 idx
= skip_openp (idx
, in
);
2031 while (idx
< in
->len
&& in
->ptr
[idx
] != ')')
2033 sb_add_char (&what
, in
->ptr
[idx
]);
2036 hash_add_to_string_table (&assign_hash_table
, &label
, &what
, 1);
2042 condass_lookup_name (inbuf
, idx
, out
)
2049 sb_new (&condass_acc
);
2051 while (idx
< inbuf
->len
2052 && ISNEXTCHAR (inbuf
->ptr
[idx
]))
2054 sb_add_char (&condass_acc
, inbuf
->ptr
[idx
++]);
2057 if (inbuf
->ptr
[idx
] == '\'')
2059 ptr
= hash_lookup (&vars
, &condass_acc
);
2062 WARNING ((stderr
, "Can't find preprocessor variable %s.\n", sb_name (&condass_acc
)));
2066 if (ptr
->type
== hash_integer
)
2069 sprintf (buffer
, "%d", ptr
->value
.i
);
2070 sb_add_string (out
, buffer
);
2074 sb_add_sb (out
, &ptr
->value
.s
);
2077 sb_kill (&condass_acc
);
2090 whatcond (idx
, in
, val
)
2097 idx
= sb_skip_white (idx
, in
);
2099 if (p
[0] == 'E' && p
[1] == 'Q')
2101 else if (p
[0] == 'N' && p
[1] == 'E')
2103 else if (p
[0] == 'L' && p
[1] == 'T')
2105 else if (p
[0] == 'L' && p
[1] == 'E')
2107 else if (p
[0] == 'G' && p
[1] == 'T')
2109 else if (p
[0] == 'G' && p
[1] == 'E')
2113 ERROR ((stderr
, "Comparison operator must be one of EQ, NE, LT, LE, GT or GE"));
2116 idx
= sb_skip_white (idx
+ 2, in
);
2133 idx
= sb_skip_white (idx
, in
);
2135 if (in
->ptr
[idx
] == '"')
2139 /* This is a string comparision */
2140 idx
= getstring (idx
, in
, &acc_a
);
2141 idx
= whatcond (idx
, in
, &cond
);
2142 idx
= getstring (idx
, in
, &acc_b
);
2143 same
= acc_a
.len
== acc_b
.len
&& (strncmp (acc_a
.ptr
, acc_b
.ptr
, acc_a
.len
) == 0);
2145 if (cond
!= EQ
&& cond
!= NE
)
2147 ERROR ((stderr
, "Comparison operator for strings must be EQ or NE"));
2151 res
= cond
== EQ
&& same
;
2154 /* This is a numeric expression */
2159 idx
= exp_get_abs ("Conditional operator must have absolute operands.\n", idx
, in
, &vala
);
2160 idx
= whatcond (idx
, in
, &cond
);
2161 idx
= sb_skip_white (idx
, in
);
2162 if (in
->ptr
[idx
] == '"')
2164 WARNING ((stderr
, "String compared against expression.\n"));
2169 idx
= exp_get_abs ("Conditional operator must have absolute operands.\n", idx
, in
, &valb
);
2209 if (ifi
>= IFNESTING
)
2211 FATAL ((stderr
, "AIF nesting unreasonable.\n"));
2214 ifstack
[ifi
].on
= istrue (idx
, in
);
2215 ifstack
[ifi
].hadelse
= 0;
2223 ifstack
[ifi
].on
= !ifstack
[ifi
].on
;
2224 if (ifstack
[ifi
].hadelse
)
2226 ERROR ((stderr
, "Multiple AELSEs in AIF.\n"));
2228 ifstack
[ifi
].hadelse
= 1;
2242 ERROR ((stderr
, "AENDI without AIF.\n"));
2249 return ifstack
[ifi
].on
;
2253 /* Read input lines till we get to a TO string.
2254 Increase nesting depth if we geta FROM string.
2255 Put the results into sb at PTR. */
2258 buffer_and_nest (from
, to
, ptr
)
2263 int from_len
= strlen (from
);
2264 int to_len
= strlen (to
);
2266 int line_start
= ptr
->len
;
2267 int line
= linecount ();
2269 int more
= get_line (ptr
);
2273 /* Try and find the first pseudo op on the line */
2276 /* Skip leading whitespace */
2278 && ISWHITE (ptr
->ptr
[i
]))
2281 /* Skip over a label */
2283 && ISNEXTCHAR (ptr
->ptr
[i
]))
2288 && ptr
->ptr
[i
] == ':')
2291 /* Skip trailing whitespace */
2293 && ISWHITE (ptr
->ptr
[i
]))
2297 && ptr
->ptr
[i
] == '.')
2299 if (strncmp (ptr
->ptr
+ i
, from
, from_len
) == 0)
2301 if (strncmp (ptr
->ptr
+ i
, to
, to_len
) == 0)
2306 /* Reset the string to not include the ending rune */
2307 ptr
->len
= line_start
;
2313 /* Add a CR to the end and keep running */
2314 sb_add_char (ptr
, '\n');
2315 line_start
= ptr
->len
;
2316 more
= get_line (ptr
);
2321 FATAL ((stderr
, "End of file whilst inside %s, started on line %d.\n", from
, line
));
2329 ERROR ((stderr
, "AENDR without a AREPEAT.\n"));
2348 process_assigns (idx
, in
, &exp
);
2349 doit
= istrue (0, &exp
);
2351 buffer_and_nest (".AWHILE", ".AENDW", &sub
);
2366 int index
= include_next_index ();
2370 sb_add_sb (©
, &sub
);
2371 sb_add_sb (©
, in
);
2372 sb_add_string (©
, "\n");
2373 sb_add_sb (©
, &sub
);
2374 sb_add_string (©
, "\t.AENDW\n");
2375 /* Push another WHILE */
2376 include_buf (&exp
, ©
, include_while
, index
);
2389 ERROR ((stderr
, "AENDW without a AENDW.\n"));
2395 Pop things off the include stack until the type and index changes */
2400 include_type type
= sp
->type
;
2401 if (type
== include_repeat
2402 || type
== include_while
2403 || type
== include_macro
)
2405 int index
= sp
->index
;
2407 while (sp
->index
== index
2408 && sp
->type
== type
)
2418 do_arepeat (idx
, in
)
2422 sb exp
; /* buffer with expression in it */
2423 sb copy
; /* expanded repeat block */
2424 sb sub
; /* contents of AREPEAT */
2430 process_assigns (idx
, in
, &exp
);
2431 idx
= exp_get_abs ("AREPEAT must have absolute operand.\n", 0, &exp
, &rc
);
2432 buffer_and_nest (".AREPEAT", ".AENDR", &sub
);
2435 /* Push back the text following the repeat, and another repeat block
2446 int index
= include_next_index ();
2447 sb_add_sb (©
, &sub
);
2450 sprintf (buffer
, "\t.AREPEAT %d\n", rc
- 1);
2451 sb_add_string (©
, buffer
);
2452 sb_add_sb (©
, &sub
);
2453 sb_add_string (©
, " .AENDR\n");
2456 include_buf (&exp
, ©
, include_repeat
, index
);
2468 ERROR ((stderr
, ".ENDM without a matching .MACRO.\n"));
2472 /* MARRO PROCESSING */
2475 hash_table macro_table
;
2485 do_formals (macro
, idx
, in
)
2490 formal_entry
**p
= ¯o
->formals
;
2491 macro
->formal_count
= 0;
2492 hash_new_table (5, ¯o
->formal_hash
);
2493 while (idx
< in
->len
)
2495 formal_entry
*formal
;
2497 formal
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
2499 sb_new (&formal
->name
);
2500 sb_new (&formal
->def
);
2501 sb_new (&formal
->actual
);
2503 idx
= sb_skip_white (idx
, in
);
2504 idx
= get_token (idx
, in
, &formal
->name
);
2505 if (formal
->name
.len
== 0)
2507 idx
= sb_skip_white (idx
, in
);
2508 if (formal
->name
.len
)
2510 /* This is a formal */
2511 if (idx
< in
->len
&& in
->ptr
[idx
] == '=')
2514 idx
= get_any_string (idx
+ 1, in
, &formal
->def
);
2519 /* Add to macro's hash table */
2521 hash_entry
*p
= hash_create (¯o
->formal_hash
, &formal
->name
);
2522 p
->type
= hash_formal
;
2523 p
->value
.f
= formal
;
2526 formal
->index
= macro
->formal_count
;
2527 idx
= sb_skip_comma (idx
, in
);
2528 macro
->formal_count
++;
2544 macro
= (macro_entry
*) xmalloc (sizeof (macro_entry
));
2545 sb_new (¯o
->sub
);
2548 macro
->formal_count
= 0;
2551 idx
= sb_skip_white (idx
, in
);
2552 buffer_and_nest (".MACRO", ".ENDM", ¯o
->sub
);
2555 /* It's the label: MACRO (formals,...) sort */
2556 sb_add_sb (&name
, &label
);
2557 if (in
->ptr
[idx
] == '(')
2559 /* Got some formals */
2560 idx
= do_formals (macro
, idx
+ 1, in
);
2561 if (in
->ptr
[idx
] != ')')
2562 ERROR ((stderr
, "Missing ) after formals.\n"));
2567 idx
= get_token (idx
, in
, &name
);
2568 idx
= sb_skip_white (idx
, in
);
2569 idx
= do_formals (macro
, idx
, in
);
2572 /* and stick it in the macro hash table */
2573 hash_create (¯o_table
, &name
)->value
.m
= macro
;
2578 get_token (idx
, in
, name
)
2584 && ISFIRSTCHAR (in
->ptr
[idx
]))
2586 sb_add_char (name
, in
->ptr
[idx
++]);
2587 while (idx
< in
->len
2588 && ISNEXTCHAR (in
->ptr
[idx
]))
2590 sb_add_char (name
, in
->ptr
[idx
++]);
2596 /* Scan a token, but stop if a ' is seen */
2598 get_apost_token (idx
, in
, name
, kind
)
2604 idx
= get_token (idx
, in
, name
);
2605 if (idx
< in
->len
&& in
->ptr
[idx
] == kind
)
2611 sub_actual (src
, in
, t
, m
, kind
, out
)
2619 /* This is something to take care of */
2621 src
= get_apost_token (src
, in
, t
, kind
);
2622 /* See if it's in the macro's hash table */
2623 ptr
= hash_lookup (&m
->formal_hash
, t
);
2626 if (ptr
->value
.f
->actual
.len
)
2628 sb_add_sb (out
, &ptr
->value
.f
->actual
);
2632 sb_add_sb (out
, &ptr
->value
.f
->def
);
2637 sb_add_char (out
, '\\');
2645 macro_expand (name
, idx
, in
, m
)
2656 int is_positional
= 0;
2662 /* Reset any old value the actuals may have */
2663 for (f
= m
->formals
; f
; f
= f
->next
)
2664 sb_reset (&f
->actual
);
2666 /* Peel off the actuals and store them away in the hash tables' actuals */
2667 while (idx
< in
->len
)
2670 idx
= sb_skip_white (idx
, in
);
2671 /* Look and see if it's a positional or keyword arg */
2673 while (scan
< in
->len
2674 && !ISSEP (in
->ptr
[scan
])
2675 && in
->ptr
[scan
] != '=')
2677 if (scan
< in
->len
&& in
->ptr
[scan
] == '=')
2682 ERROR ((stderr
, "Can't mix positional and keyword arguments.\n"));
2685 /* This is a keyword arg, fetch the formal name and
2686 then the actual stuff */
2688 idx
= get_token (idx
, in
, &t
);
2689 if (in
->ptr
[idx
] != '=')
2690 ERROR ((stderr
, "confused about formal params.\n"));
2692 /* Lookup the formal in the macro's list */
2693 ptr
= hash_lookup (&m
->formal_hash
, &t
);
2696 ERROR ((stderr
, "MACRO formal argument %s does not exist.\n", sb_name (&t
)));
2701 /* Insert this value into the right place */
2702 sb_reset (&ptr
->value
.f
->actual
);
2703 idx
= get_any_string (idx
+ 1, in
, &ptr
->value
.f
->actual
);
2708 /* This is a positional arg */
2712 ERROR ((stderr
, "Can't mix positional and keyword arguments.\n"));
2717 ERROR ((stderr
, "Too many positional arguments.\n"));
2721 sb_reset (&f
->actual
);
2722 idx
= get_any_string (idx
, in
, &f
->actual
);
2725 idx
= sb_skip_comma (idx
, in
);
2728 /* Copy the stuff from the macro buffer into a safe place and substitute any args */
2735 while (src
< in
->len
)
2737 if (in
->ptr
[src
] == '&')
2740 src
= sub_actual (src
+ 1, in
, &t
, m
, '&', &out
);
2742 else if (in
->ptr
[src
] == '\\')
2745 if (in
->ptr
[src
] == ';')
2747 /* This is a comment, just drop the rest of the line */
2748 while (src
< in
->len
2749 && in
->ptr
[src
] != '\n')
2753 else if (in
->ptr
[src
] == '(')
2755 /* Sub in till the next ')' literally */
2757 while (src
< in
->len
&& in
->ptr
[src
] != ')')
2759 sb_add_char (&out
, in
->ptr
[src
++]);
2761 if (in
->ptr
[src
] == ')')
2764 ERROR ((stderr
, "Missplaced ).\n"));
2766 else if (in
->ptr
[src
] == '@')
2768 /* Sub in the macro invocation number */
2772 sprintf (buffer
, "%05d", number
);
2773 sb_add_string (&out
, buffer
);
2775 else if (in
->ptr
[src
] == '&')
2777 /* This is a preprocessor variable name, we don't do them
2779 sb_add_char (&out
, '\\');
2780 sb_add_char (&out
, '&');
2786 src
= sub_actual (src
, in
, &t
, m
, '\'', &out
);
2791 sb_add_char (&out
, in
->ptr
[src
++]);
2794 include_buf (name
, &out
, include_macro
, include_next_index ());
2807 /* The macro name must be the first thing on the line */
2813 idx
= get_token (idx
, in
, &name
);
2817 /* Got a name, look it up */
2819 ptr
= hash_lookup (¯o_table
, &name
);
2823 /* It's in the table, copy out the stuff and convert any macro args */
2824 macro_expand (&name
, idx
, in
, ptr
->value
.m
);
2836 /* STRING HANDLING */
2839 getstring (idx
, in
, acc
)
2844 idx
= sb_skip_white (idx
, in
);
2846 while (idx
< in
->len
2847 && (in
->ptr
[idx
] == '"' || in
->ptr
[idx
] == '<'))
2849 if (in
->ptr
[idx
] == '<')
2853 idx
= exp_get_abs ("Character code in string must be absolute expression.\n",
2855 sb_add_char (acc
, code
);
2857 if (in
->ptr
[idx
] != '>')
2858 ERROR ((stderr
, "Missing > for character code.\n"));
2861 else if (in
->ptr
[idx
] == '"')
2864 while (idx
< in
->len
)
2866 if (in
->ptr
[idx
] == '"')
2869 if (idx
>= in
->len
|| in
->ptr
[idx
] != '"')
2872 sb_add_char (acc
, in
->ptr
[idx
]);
2881 /* .SDATA[C|Z] <string> */
2885 do_sdata (idx
, in
, type
)
2893 fprintf (outfile
, ".byte\t");
2895 while (idx
< in
->len
)
2899 idx
= sb_skip_white (idx
, in
);
2900 while ((in
->ptr
[idx
] == '"'
2901 || in
->ptr
[idx
] == '<')
2904 idx
= getstring (idx
, in
, &acc
);
2909 ERROR ((stderr
, "string for SDATAC longer than 255 characters (%d).\n", acc
.len
));
2911 fprintf (outfile
, "%d", acc
.len
);
2915 for (i
= 0; i
< acc
.len
; i
++)
2919 fprintf (outfile
, ",");
2921 fprintf (outfile
, "%d", acc
.ptr
[i
]);
2928 fprintf (outfile
, ",");
2929 fprintf (outfile
, "0");
2931 idx
= sb_skip_white (idx
, in
);
2933 if (in
->ptr
[idx
] != ',' && idx
!= in
->len
)
2935 fprintf (outfile
, "\n");
2936 ERROR ((stderr
, "illegal character in SDATA line (0x%x).\n", in
->ptr
[idx
]));
2942 fprintf (outfile
, "\n");
2945 /* .SDATAB <count> <string> */
2957 idx
= exp_get_abs ("Must have absolute SDATAB repeat count.\n", idx
, in
, &repeat
);
2960 ERROR ((stderr
, "Must have positive SDATAB repeat count (%d).\n", repeat
));
2964 idx
= sb_skip_comma (idx
, in
);
2965 idx
= getstring (idx
, in
, &acc
);
2967 for (i
= 0; i
< repeat
; i
++)
2970 fprintf (outfile
, "\t");
2971 fprintf (outfile
, ".byte\t");
2973 fprintf (outfile
, "\n");
2983 FILE *newone
= fopen (name
, "r");
2987 if (isp
== MAX_INCLUDES
)
2988 FATAL ((stderr
, "Unreasonable include depth (%d).\n", isp
));
2991 sp
->handle
= newone
;
2994 sb_add_string (&sp
->name
, name
);
2997 sp
->pushback_index
= 0;
2998 sp
->type
= include_file
;
3000 sb_new (&sp
->pushback
);
3005 do_include (idx
, in
)
3012 idx
= getstring (idx
, in
, &t
);
3013 text
= sb_name (&t
);
3014 if (!new_file (text
))
3016 FATAL ((stderr
, "Can't open include file `%s'.\n", text
));
3024 if (sp
!= include_stack
)
3027 fclose (sp
->handle
);
3032 /* Get the next character from the include stack. If there's anything
3033 in the pushback buffer, take that first. If we're at eof, pop from
3034 the stack and try again. Keep the linecount up to date. */
3041 if (sp
->pushback
.len
!= sp
->pushback_index
)
3043 r
= (char) (sp
->pushback
.ptr
[sp
->pushback_index
++]);
3044 /* When they've all gone, reset the pointer */
3045 if (sp
->pushback_index
== sp
->pushback
.len
)
3047 sp
->pushback
.len
= 0;
3048 sp
->pushback_index
= 0;
3051 else if (sp
->handle
)
3053 r
= getc (sp
->handle
);
3058 if (r
== EOF
&& isp
)
3062 while (r
== EOF
&& isp
)
3080 return sp
->linecount
;
3084 include_next_index ()
3088 && index
> MAX_REASONABLE
)
3089 FATAL ((stderr
, "Unreasonable expansion (-u turns off check).\n"));
3094 /* Initialize the chartype vector. */
3100 for (x
= 0; x
< 256; x
++)
3102 if (isalpha (x
) || x
== '_' || x
== '$')
3103 chartype
[x
] |= FIRSTBIT
;
3105 if (isdigit (x
) || isalpha (x
) || x
== '_' || x
== '$')
3106 chartype
[x
] |= NEXTBIT
;
3108 if (x
== ' ' || x
== '\t' || x
== ',' || x
== '"' || x
== ';'
3109 || x
== '"' || x
== '<' || x
== '>' || x
== ')' || x
== '(')
3110 chartype
[x
] |= SEPBIT
;
3112 if (x
== ' ' || x
== '\t')
3113 chartype
[x
] |= WHITEBIT
;
3118 /* What to do with all the keywords */
3119 #define PROCESS 0x1000 /* Run substitution over the line */
3120 #define LAB 0x2000 /* Spit out the label */
3122 #define K_EQU PROCESS|1
3123 #define K_ASSIGN PROCESS|2
3124 #define K_REG PROCESS|3
3125 #define K_ORG PROCESS|4
3126 #define K_RADIX PROCESS|5
3127 #define K_DATA LAB|PROCESS|6
3128 #define K_DATAB LAB|PROCESS|7
3129 #define K_SDATA LAB|PROCESS|8
3130 #define K_SDATAB LAB|PROCESS|9
3131 #define K_SDATAC LAB|PROCESS|10
3132 #define K_SDATAZ LAB|PROCESS|11
3133 #define K_RES LAB|PROCESS|12
3134 #define K_SRES LAB|PROCESS|13
3135 #define K_SRESC LAB|PROCESS|14
3136 #define K_SRESZ LAB|PROCESS|15
3137 #define K_EXPORT LAB|PROCESS|16
3138 #define K_GLOBAL LAB|PROCESS|17
3139 #define K_PRINT LAB|PROCESS|19
3140 #define K_FORM LAB|PROCESS|20
3141 #define K_HEADING LAB|PROCESS|21
3142 #define K_PAGE LAB|PROCESS|22
3143 #define K_IMPORT LAB|PROCESS|23
3144 #define K_PROGRAM LAB|PROCESS|24
3145 #define K_END PROCESS|25
3146 #define K_INCLUDE PROCESS|26
3147 #define K_IGNORED PROCESS|27
3148 #define K_ASSIGNA 28
3149 #define K_ASSIGNC 29
3150 #define K_AIF PROCESS|30
3151 #define K_AELSE PROCESS|31
3152 #define K_AENDI PROCESS|32
3153 #define K_AREPEAT PROCESS|33
3154 #define K_AENDR PROCESS|34
3156 #define K_AENDW PROCESS|36
3158 #define K_MACRO PROCESS|38
3160 #define K_ALIGN PROCESS|LAB|40
3171 { "EQU", K_EQU
, 0 },
3172 { "ASSIGN", K_ASSIGN
, 0 },
3173 { "REG", K_REG
, 0 },
3174 { "ORG", K_ORG
, 0 },
3175 { "RADIX", K_RADIX
, 0 },
3176 { "DATA", K_DATA
, 0 },
3177 { "DATAB", K_DATAB
, 0 },
3178 { "SDATA", K_SDATA
, 0 },
3179 { "SDATAB", K_SDATAB
, 0 },
3180 { "SDATAZ", K_SDATAZ
, 0 },
3181 { "SDATAC", K_SDATAC
, 0 },
3182 { "RES", K_RES
, 0 },
3183 { "SRES", K_SRES
, 0 },
3184 { "SRESC", K_SRESC
, 0 },
3185 { "SRESZ", K_SRESZ
, 0 },
3186 { "EXPORT", K_EXPORT
, 0 },
3187 { "GLOBAL", K_GLOBAL
, 0 },
3188 { "PRINT", K_PRINT
, 0 },
3189 { "FORM", K_FORM
, 0 },
3190 { "HEADING", K_HEADING
, 0 },
3191 { "PAGE", K_PAGE
, 0 },
3192 { "PROGRAM", K_IGNORED
, 0 },
3193 { "END", K_END
, 0 },
3194 { "INCLUDE", K_INCLUDE
, 0 },
3195 { "ASSIGNA", K_ASSIGNA
, 0 },
3196 { "ASSIGNC", K_ASSIGNC
, 0 },
3197 { "AIF", K_AIF
, 0 },
3198 { "AELSE", K_AELSE
, 0 },
3199 { "AENDI", K_AENDI
, 0 },
3200 { "AREPEAT", K_AREPEAT
, 0 },
3201 { "AENDR", K_AENDR
, 0 },
3202 { "EXITM", K_EXITM
, 0 },
3203 { "MACRO", K_MACRO
, 0 },
3204 { "ENDM", K_ENDM
, 0 },
3205 { "AWHILE", K_AWHILE
, 0 },
3206 { "ALIGN", K_ALIGN
, 0 },
3207 { "AENDW", K_AENDW
, 0 },
3211 /* Look for a pseudo op on the line. If one's there then call
3215 process_pseudo_op (idx
, line
, acc
)
3220 char *in
= line
->ptr
+ idx
;
3224 /* Scan forward and find pseudo name */
3231 while (idx
< line
->len
&& *e
&& ISFIRSTCHAR (*e
))
3233 sb_add_char (acc
, *e
);
3238 ptr
= hash_lookup (&keyword_hash_table
, acc
);
3242 WARNING ((stderr
, "Unrecognised pseudo op `%s'.\n", sb_name (acc
)));
3245 if (ptr
->value
.i
& LAB
)
3246 { /* output the label */
3249 fprintf (outfile
, "%s:\t", sb_name (&label
));
3252 fprintf (outfile
, "\t");
3255 if (ptr
->value
.i
& PROCESS
)
3257 /* Polish the rest of the line before handling the pseudo op */
3258 /* strip_comments(line);*/
3260 process_assigns (idx
, line
, acc
);
3262 change_base (0, acc
, line
);
3267 switch (ptr
->value
.i
)
3280 switch (ptr
->value
.i
)
3289 ERROR ((stderr
, "ORG command not allowed.\n"));
3295 do_data (idx
, line
);
3298 do_datab (idx
, line
);
3301 do_sdata (idx
, line
, 0);
3304 do_sdatab (idx
, line
);
3307 do_sdata (idx
, line
, 'c');
3310 do_sdata (idx
, line
, 'z');
3313 do_assign (1, 0, line
);
3319 do_arepeat (idx
, line
);
3325 do_awhile (idx
, line
);
3331 do_assign (0, idx
, line
);
3334 do_align (idx
, line
);
3337 do_res (idx
, line
, 0);
3340 do_res (idx
, line
, 's');
3343 do_include (idx
, line
);
3346 do_macro (idx
, line
);
3352 do_res (idx
, line
, 'c');
3355 do_print (idx
, line
);
3358 do_form (idx
, line
);
3361 do_heading (idx
, line
);
3373 do_res (idx
, line
, 'z');
3381 do_assigna (idx
, line
);
3384 do_assignc (idx
, line
);
3400 /* Build the keyword hash table - put each keyword in the table twice,
3401 once upper and once lower case.*/
3408 for (i
= 0; kinfo
[i
].name
; i
++)
3413 sb_add_string (&label
, kinfo
[i
].name
);
3415 hash_add_to_int_table (&keyword_hash_table
, &label
, kinfo
[i
].code
);
3418 for (j
= 0; kinfo
[i
].name
[j
]; j
++)
3419 sb_add_char (&label
, kinfo
[i
].name
[j
] - 'A' + 'a');
3420 hash_add_to_int_table (&keyword_hash_table
, &label
, kinfo
[i
].code
);
3440 hash_new_table (101, ¯o_table
);
3441 hash_new_table (101, &keyword_hash_table
);
3442 hash_new_table (101, &assign_hash_table
);
3443 hash_new_table (101, &vars
);
3448 /* Find the output file */
3449 for (i
= 1; i
< ac
; i
++)
3451 if (av
[i
][0] == '-')
3453 if (av
[i
][1] == 'c' && av
[i
][2] == 0)
3457 else if (av
[i
][1] == 'p' && av
[i
][2] == 0)
3459 print_line_number
= 1;
3461 else if (av
[i
][1] == 'u' && av
[i
][2] == 0)
3465 else if (av
[i
][1] == 's' && av
[i
][2] == 0)
3469 else if (av
[i
][1] == 'o' && av
[i
][2] == 0 & i
+ 1 < ac
)
3471 /* Got output file name */
3473 outfile
= fopen (av
[i
], "w");
3476 fprintf (stderr
, "%s: Can't open output file `%s'.\n",
3483 fprintf (stderr
, "Usage: %s [-o filename] infile1 infile2...\n",
3493 /* Process all the input files */
3495 for (i
= 1; i
< ac
; i
++)
3497 if (av
[i
][0] == '-')
3499 if (av
[i
][1] == 'o')
3504 if (new_file (av
[i
]))
3510 fprintf (stderr
, "%s: Can't open input file `%s'.\n",