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 extern char *malloc ();
41 #define MAX_INCLUDES 30 /* Maximum include depth */
42 #define MAX_REASONABLE 1000 /* Maximum number of expansions */
44 int unreasonable
; /* -u on command line */
45 int stats
; /* -s on command line */
46 int print_line_number
; /* -p flag on command line */
47 int copysource
; /* -c flag on command line */
48 int warnings
; /* Number of WARNINGs generated so far. */
49 int errors
; /* Number of ERRORs generated so far. */
50 int fatals
; /* Number of fatal ERRORs generated so far (either 0 or 1). */
54 int radix
= 10; /* Default radix */
56 int had_end
; /* Seen .END */
58 /* The output stream */
62 /* Forward declarations. */
63 static int condass_lookup_name();
64 static int condass_on();
66 static int get_and_process();
67 static int get_token();
68 static int getstring();
69 static int include_next_index();
70 static int macro_op();
71 static int linecount();
72 static int process_pseudo_op();
73 static void include_pop();
74 static void include_print_where_line();
77 I had a couple of choices when deciding upon this data structure.
78 gas uses null terminated strings for all its internal work. This
79 often means that parts of the program that want to examine
80 substrings have to manipulate the data in the string to do the
81 right thing (a common operation is to single out a bit of text by
82 saving away the character after it, nulling it out, operating on
83 the substring and then replacing the character which was under the
84 null). This is a pain and I remember a load of problems that I had with
85 code in gas which almost got this right. Also, it's harder to grow and
86 allocate null terminated strings efficiently.
88 Obstacks provide all the functionality needed, but are too
89 complicated, hence the sb.
91 An sb is allocated by the caller, and is initialzed to point to an
92 sb_element. sb_elements are kept on a free lists, and used when
93 needed, replaced onto the free list when unused.
96 #define max_power_two 30 /* don't allow strings more than
97 2^max_power_two long */
98 /* structure of an sb */
101 char *ptr
; /* points to the current block. */
102 int len
; /* how much is used. */
103 int pot
; /* the maximum length is 1<<pot */
108 /* Structure of the free list object of an sb */
120 sb_element
*size
[max_power_two
];
123 sb_list_vector free_list
;
125 int string_count
[max_power_two
];
127 /* the attributes of each character are stored as a bit pattern
128 chartype, which gives us quick tests. */
135 #define ISFIRSTCHAR(x) (chartype[(unsigned)(x)] & FIRSTBIT)
136 #define ISNEXTCHAR(x) (chartype[(unsigned)(x)] & NEXTBIT)
137 #define ISSEP(x) (chartype[(unsigned)(x)] & SEPBIT)
138 #define ISWHITE(x) (chartype[(unsigned)(x)] & WHITEBIT)
140 static char chartype
[256];
143 /* Conditional assembly uses the `ifstack'. Each aif pushes another
144 entry onto the stack, and sets the on flag if it should. The aelse
145 sets hadelse, and toggles on. An aend pops a level. We limit to
146 100 levels of nesting, not because we're facists pigs with read
147 only minds, but because more than 100 levels of nesting is probably
148 a bug in the user's macro structure. */
150 #define IFNESTING 100
153 int on
; /* is the level being output */
154 int hadelse
; /* has an aelse been seen */
159 /* The final and intermediate results of expression evaluation are kept in
160 exp_t's. Note that a symbol is not an sb, but a pointer into the input
161 line. It must be coped somewhere safe before the next line is read in. */
172 int value
; /* constant part */
173 symbol add_symbol
; /* name part */
174 symbol sub_symbol
; /* name part */
179 /* Hashing is done in a pretty standard way. A hash_table has a
180 pointer to a vector of pointers to hash_entrys, and the size of the
181 vector. A hash_entry contains a union of all the info we like to
182 store in hash table. If there is a hash collision, hash_entries
183 with the same hash are kept in a chain. */
185 /* What the data in a hash_entry means */
188 hash_integer
, /* name->integer mapping */
189 hash_string
, /* name->string mapping */
190 hash_macro
, /* name is a macro */
191 hash_formal
/* name is a formal argument */
196 sb key
; /* symbol name */
197 hash_type type
; /* symbol meaning */
202 struct macro_struct
*m
;
203 struct formal_struct
*f
;
205 struct hs
*next
; /* next hash_entry with same hash key */
215 /* Structures used to store macros.
217 Each macro knows its name and included text. It gets built with a
218 list of formal arguments, and also keeps a hash table which points
219 into the list to speed up formal search. Each formal knows its
220 name and its default value. Each time the macro is expanded, the
221 formals get the actual values attatched to them. */
223 /* describe the formal arguments to a macro */
225 typedef struct formal_struct
227 struct formal_struct
*next
; /* next formal in list */
228 sb name
; /* name of the formal */
229 sb def
; /* the default value */
230 sb actual
; /* the actual argument (changed on each expansion) */
231 int index
; /* the index of the formal 0..formal_count-1 */
235 /* describe the macro. */
237 typedef struct macro_struct
239 sb sub
; /* substitution text. */
240 int formal_count
; /* number of formal args. */
241 formal_entry
*formals
; /* pointer to list of formal_structs */
242 hash_table formal_hash
; /* hash table of formals. */
246 /* how we nest files and expand macros etc.
248 we keep a stack of of include_stack structs. each include file
249 pushes a new level onto the stack. we keep an sb with a pushback
250 too. unget chars are pushed onto the pushback sb, getchars first
251 checks the pushback sb before reading from the input stream.
253 small things are expanded by adding the text of the item onto the
254 pushback sb. larger items are grown by pushing a new level and
255 allocating the entire pushback buf for the item. each time
256 something like a macro is expanded, the stack index is changed. we
257 can then perform an exitm by popping all entries off the stack with
258 the same stack index. if we're being reasonable, we can detect
259 recusive expansion by checking the index is reasonably small.
264 include_file
, include_repeat
, include_while
, include_macro
269 sb pushback
; /* current pushback stream */
270 int pushback_index
; /* next char to read from stream */
271 FILE *handle
; /* open file */
272 sb name
; /* name of file */
273 int linecount
; /* number of lines read so far */
275 int index
; /* index of this layer */
277 include_stack
[MAX_INCLUDES
];
279 struct include_stack
*sp
;
280 #define isp (sp - include_stack)
285 void include_print_where_line ();
289 do { include_print_where_line (stderr); fprintf x ; fatals++; quit(); } while(0)
291 do { include_print_where_line (stderr); fprintf x; errors++; } while(0)
293 do { include_print_where_line (stderr); fprintf x; warnings++;} while(0)
297 /* exit the program and return the right ERROR code. */
310 for (i
= 0; i
< max_power_two
; i
++)
312 fprintf (stderr
, "strings size %8d : %d\n", 1<<i
, string_count
[i
]);
323 char *p
= malloc (x
);
325 FATAL ((stderr
, "out of memory\n"));
330 /* this program is about manipulating strings.
331 they are managed in things called `sb's which is an abbreviation
332 for string buffers. an sb has to be created, things can be glued
333 on to it, and at the end of it's life it should be freed. the
334 contents should never be pointed at whilst it is still growing,
335 since it could be moved at any time
339 sb_grow... (&foo,...);
345 /* initializes an sb. */
352 /* see if we can find one to allocate */
355 if (size
> max_power_two
)
357 FATAL ((stderr
, "string longer than %d bytes requested.\n",
358 1 << max_power_two
));
360 e
= free_list
.size
[size
];
363 /* nothing there, allocate one and stick into the free list */
364 e
= (sb_element
*) xmalloc (sizeof (sb_element
) + (1 << size
));
365 e
->next
= free_list
.size
[size
];
367 free_list
.size
[size
] = e
;
368 string_count
[size
]++;
371 /* remove from free list */
373 free_list
.size
[size
] = e
->next
;
375 /* copy into callers world */
387 sb_build (ptr
, dsize
);
390 /* deallocate the sb at ptr */
397 /* return item to free list */
398 ptr
->item
->next
= free_list
.size
[ptr
->pot
];
399 free_list
.size
[ptr
->pot
] = ptr
->item
;
402 /* add the sb at s to the end of the sb at ptr */
404 static void sb_check ();
412 sb_check (ptr
, s
->len
);
413 memcpy (ptr
->ptr
+ ptr
->len
, s
->ptr
, s
->len
);
417 /* make sure that the sb at ptr has room for another len characters,
418 and grow it if it doesn't. */
425 if (ptr
->len
+ len
>= 1 << ptr
->pot
)
429 while (ptr
->len
+ len
>= 1 << pot
)
431 sb_build (&tmp
, pot
);
432 sb_add_sb (&tmp
, ptr
);
438 /* make the sb at ptr point back to the beginning. */
447 /* add character c to the end of the sb at ptr. */
455 ptr
->ptr
[ptr
->len
++] = c
;
458 /* add null terminated string s to the end of sb at ptr. */
461 sb_add_string (ptr
, s
)
465 int len
= strlen (s
);
467 memcpy (ptr
->ptr
+ ptr
->len
, s
, len
);
471 /* add string at s of length len to sb at ptr */
474 sb_add_buffer (ptr
, s
, len
)
480 memcpy (ptr
->ptr
+ ptr
->len
, s
, len
);
485 /* print the sb at ptr to the output file */
495 for (i
= 0; i
< ptr
->len
; i
++)
499 fprintf (outfile
, ",");
501 fprintf (outfile
, "%d", ptr
->ptr
[i
]);
506 /* put a null at the end of the sb at in and return the start of the
507 string, so that it can be used as an arg to printf %s. */
514 /* stick a null on the end of the string */
519 /* start at the index idx into the string in sb at ptr and skip
520 whitespace. return the index of the first non whitespace character */
523 sb_skip_white (idx
, ptr
)
527 while (idx
< ptr
->len
&& ISWHITE (ptr
->ptr
[idx
]))
532 /* start at the index idx into the sb at ptr. skips whitespace,
533 a comma and any following whitespace. returnes the index of the
537 sb_skip_comma (idx
, ptr
)
541 while (idx
< ptr
->len
&& ISWHITE (ptr
->ptr
[idx
]))
545 && ptr
->ptr
[idx
] == ',')
548 while (idx
< ptr
->len
&& ISWHITE (ptr
->ptr
[idx
]))
555 /* hash table maintenance. */
557 /* build a new hash table with size buckets, and fill in the info at ptr. */
560 hash_new_table (size
, ptr
)
565 ptr
->table
= (hash_entry
**) xmalloc (size
* (sizeof (hash_entry
*)));
568 /* calculate and return the hash value of the sb at key. */
577 for (i
= 0; i
< key
->len
; i
++)
585 /* lookup key in hash_table tab, if present, then return it, otherwise
586 build a new one and fill it with hash_integer. */
590 hash_create (tab
, key
)
594 int k
= hash (key
) % tab
->size
;
596 hash_entry
**table
= tab
->table
;
604 hash_entry
*n
= (hash_entry
*) xmalloc (sizeof (hash_entry
));
607 sb_add_sb (&n
->key
, key
);
609 n
->type
= hash_integer
;
612 if (strncmp (table
[k
]->key
.ptr
, key
->ptr
, key
->len
) == 0)
620 /* add sb name with key into hash_table tab. if replacing old value
621 and again, then ERROR. */
625 hash_add_to_string_table (tab
, key
, name
, again
)
631 hash_entry
*ptr
= hash_create (tab
, key
);
632 if (ptr
->type
== hash_integer
)
634 sb_new (&ptr
->value
.s
);
636 if (ptr
->value
.s
.len
)
639 ERROR ((stderr
, "redefintion not allowed"));
641 sb_reset (&ptr
->value
.s
);
642 sb_add_sb (&ptr
->value
.s
, name
);
645 /* add integer name to hash_table tab with sb key. */
649 hash_add_to_int_table (tab
, key
, name
)
654 hash_entry
*ptr
= hash_create (tab
, key
);
658 /* lookup sb key in hash_table tab. if found return hash_entry result,
663 hash_lookup (tab
, key
)
667 int k
= hash (key
) % tab
->size
;
668 hash_entry
**table
= tab
->table
;
669 hash_entry
*p
= table
[k
];
672 if (p
->key
.len
== key
->len
673 && strncmp (p
->key
.ptr
, key
->ptr
, key
->len
) == 0)
683 are handled in a really simple recursive decent way. each bit of
684 the machine takes an index into an sb and a pointer to an exp_t,
685 modifies the *exp_t and returns the index of the first character
686 past the part of the expression parsed.
688 expression precedence:
699 /* make sure that the exp_t at term is constant, if not the give the op ERROR. */
703 checkconst (op
, term
)
707 if (term
->add_symbol
.len
708 || term
->sub_symbol
.len
)
710 ERROR ((stderr
, "the %c operator cannot take non-absolute arguments.\n", op
));
714 /* turn the number in string at idx into a number of base,
715 fill in ptr and return the index of the first character not in the
720 sb_strtol (idx
, string
, base
, ptr
)
727 idx
= sb_skip_white (idx
, string
);
729 while (idx
< string
->len
)
731 int ch
= string
->ptr
[idx
];
735 else if (ch
>= 'a' && ch
<= 'f')
737 else if (ch
>= 'a' && ch
<= 'f')
745 value
= value
* base
+ dig
;
752 static int level_5 ();
755 level_0 (idx
, string
, lhs
)
760 lhs
->add_symbol
.len
= 0;
761 lhs
->add_symbol
.name
= 0;
763 lhs
->sub_symbol
.len
= 0;
764 lhs
->sub_symbol
.name
= 0;
766 idx
= sb_skip_white (idx
, string
);
770 if (isdigit (string
->ptr
[idx
]))
772 idx
= sb_strtol (idx
, string
, 10, &lhs
->value
);
774 else if (ISFIRSTCHAR (string
->ptr
[idx
]))
777 lhs
->add_symbol
.name
= string
->ptr
+ idx
;
778 while (idx
< string
->len
&& ISNEXTCHAR (string
->ptr
[idx
]))
783 lhs
->add_symbol
.len
= len
;
785 else if (string
->ptr
[idx
] == '"')
789 ERROR ((stderr
, "string where expression expected.\n"));
790 idx
= getstring (idx
, string
, &acc
);
795 ERROR ((stderr
, "can't find primary in expression.\n"));
798 return sb_skip_white (idx
, string
);
804 level_1 (idx
, string
, lhs
)
809 idx
= sb_skip_white (idx
, string
);
811 switch (string
->ptr
[idx
])
814 idx
= level_1 (idx
+ 1, string
, lhs
);
817 idx
= level_1 (idx
+ 1, string
, lhs
);
818 checkconst ('~', lhs
);
819 lhs
->value
= ~lhs
->value
;
824 idx
= level_1 (idx
+ 1, string
, lhs
);
825 lhs
->value
= -lhs
->value
;
827 lhs
->add_symbol
= lhs
->sub_symbol
;
833 idx
= level_5 (sb_skip_white (idx
, string
), string
, lhs
);
834 if (string
->ptr
[idx
] != ')')
835 ERROR ((stderr
, "misplaced closing parens.\n"));
840 idx
= level_0 (idx
, string
, lhs
);
843 return sb_skip_white (idx
, string
);
847 level_2 (idx
, string
, lhs
)
854 idx
= level_1 (idx
, string
, lhs
);
856 while (idx
< string
->len
&& (string
->ptr
[idx
] == '*'
857 || string
->ptr
[idx
] == '/'))
859 char op
= string
->ptr
[idx
++];
860 idx
= level_1 (idx
, string
, &rhs
);
864 checkconst ('*', lhs
);
865 checkconst ('*', &rhs
);
866 lhs
->value
*= rhs
.value
;
869 checkconst ('/', lhs
);
870 checkconst ('/', &rhs
);
872 ERROR ((stderr
, "attempt to divide by zero.\n"));
874 lhs
->value
/= rhs
.value
;
878 return sb_skip_white (idx
, string
);
883 level_3 (idx
, string
, lhs
)
890 idx
= level_2 (idx
, string
, lhs
);
892 while (idx
< string
->len
893 && (string
->ptr
[idx
] == '+'
894 || string
->ptr
[idx
] == '-'))
896 char op
= string
->ptr
[idx
++];
897 idx
= level_2 (idx
, string
, &rhs
);
901 lhs
->value
+= rhs
.value
;
902 if (lhs
->add_symbol
.name
&& rhs
.add_symbol
.name
)
904 ERROR ((stderr
, "can't add two relocatable expressions\n"));
906 /* change nn+symbol to symbol + nn */
907 if (rhs
.add_symbol
.name
)
909 lhs
->add_symbol
= rhs
.add_symbol
;
913 lhs
->value
-= rhs
.value
;
914 lhs
->sub_symbol
= rhs
.add_symbol
;
918 return sb_skip_white (idx
, string
);
922 level_4 (idx
, string
, lhs
)
929 idx
= level_3 (idx
, string
, lhs
);
931 while (idx
< string
->len
&&
932 string
->ptr
[idx
] == '&')
934 char op
= string
->ptr
[idx
++];
935 idx
= level_3 (idx
, string
, &rhs
);
939 checkconst ('&', lhs
);
940 checkconst ('&', &rhs
);
941 lhs
->value
&= rhs
.value
;
945 return sb_skip_white (idx
, string
);
949 level_5 (idx
, string
, lhs
)
956 idx
= level_4 (idx
, string
, lhs
);
958 while (idx
< string
->len
959 && (string
->ptr
[idx
] == '|' || string
->ptr
[idx
] == '~'))
961 char op
= string
->ptr
[idx
++];
962 idx
= level_4 (idx
, string
, &rhs
);
966 checkconst ('|', lhs
);
967 checkconst ('|', &rhs
);
968 lhs
->value
|= rhs
.value
;
971 checkconst ('~', lhs
);
972 checkconst ('~', &rhs
);
973 lhs
->value
^= rhs
.value
;
977 return sb_skip_white (idx
, string
);
981 /* parse the expression at offset idx into string, fill up res with
982 the result. return the index of the first char past the expression.
986 exp_parse (idx
, string
, res
)
991 return level_5 (sb_skip_white (idx
, string
), string
, res
);
995 /* turn the expression at exp into text and glue it onto the end of
999 exp_string (exp
, string
)
1007 if (exp
->add_symbol
.len
)
1009 sb_add_buffer (string
, exp
->add_symbol
.name
, exp
->add_symbol
.len
);
1017 sb_add_char (string
, '+');
1018 sprintf (buf
, "%d", exp
->value
);
1019 sb_add_string (string
, buf
);
1023 if (exp
->sub_symbol
.len
)
1025 sb_add_char (string
, '-');
1026 sb_add_buffer (string
, exp
->add_symbol
.name
, exp
->add_symbol
.len
);
1032 sb_add_char (string
, '0');
1036 /* parse the expression at offset idx into sb in, return the value in val.
1037 if the expression is not constant, give ERROR emsg. returns the index
1038 of the first character past the end of the expression. */
1041 exp_get_abs (emsg
, idx
, in
, val
)
1048 idx
= exp_parse (idx
, in
, &res
);
1049 if (res
.add_symbol
.len
|| res
.sub_symbol
.len
)
1050 ERROR ((stderr
, emsg
));
1056 sb label
; /* current label parsed from line */
1057 hash_table assign_hash_table
; /* hash table for all assigned variables */
1058 hash_table keyword_hash_table
; /* hash table for keyword */
1059 hash_table vars
; /* hash table for eq variables */
1061 #define in_comment ';'
1065 strip_comments (out
)
1070 for (i
= 0; i
< out
->len
; i
++)
1072 if (s
[i
] == in_comment
)
1081 /* push back character ch so that it can be read again. */
1091 if (sp
->pushback_index
)
1092 sp
->pushback_index
--;
1094 sb_add_char (&sp
->pushback
, ch
);
1097 /* push the sb ptr onto the include stack, with the given name, type and index. */
1101 include_buf (name
, ptr
, type
, index
)
1108 if (sp
- include_stack
>= MAX_INCLUDES
)
1109 FATAL ((stderr
, "unreasonable nesting.\n"));
1111 sb_add_sb (&sp
->name
, name
);
1114 sp
->pushback_index
= 0;
1117 sb_new (&sp
->pushback
);
1118 sb_add_sb (&sp
->pushback
, ptr
);
1122 /* used in ERROR messages, print info on where the include stack is onto file. */
1125 include_print_where_line (file
)
1128 struct include_stack
*p
= include_stack
+ 1;
1132 fprintf (file
, "%s:%d ", sb_name (&p
->name
), p
->linecount
- ((p
== sp
) ? 1 : 0));
1137 /* used in listings, print the line number onto file. */
1139 include_print_line (file
)
1143 struct include_stack
*p
= include_stack
+ 1;
1145 n
= fprintf (file
, "%4d", p
->linecount
);
1149 n
+= fprintf (file
, ".%d", p
->linecount
);
1154 fprintf (file
, " ");
1160 /* read a line from the top of the include stack into sb in. */
1171 putc ('!', outfile
);
1172 if (print_line_number
)
1173 include_print_line (outfile
);
1187 WARNING ((stderr
, "end of file not at start of line.\n"));
1189 putc ('\n', outfile
);
1206 /* continued line */
1209 putc ('!', outfile
);
1210 putc ('+', outfile
);
1223 sb_add_char (in
, ch
);
1231 /* find a label from sb in and put it in out. */
1234 grab_label (in
, out
)
1240 if (ISFIRSTCHAR (in
->ptr
[i
]))
1242 sb_add_char (out
, in
->ptr
[i
]);
1244 while (ISNEXTCHAR (in
->ptr
[i
]) && i
< in
->len
)
1246 sb_add_char (out
, in
->ptr
[i
]);
1253 /* find all strange base stuff and turn into decimal. also
1254 find all the other numbers and convert them from the default radix */
1257 change_base (idx
, in
, out
)
1264 while (idx
< in
->len
)
1266 if (idx
< in
->len
- 1 && in
->ptr
[idx
+ 1] == '\'')
1270 switch (in
->ptr
[idx
])
1289 ERROR ((stderr
, "Illegal base character %c.\n", in
->ptr
[idx
]));
1294 idx
= sb_strtol (idx
+ 2, in
, base
, &value
);
1295 sprintf (buffer
, "%d", value
);
1296 sb_add_string (out
, buffer
);
1298 else if (ISFIRSTCHAR (in
->ptr
[idx
]))
1300 /* copy entire names through quickly */
1301 sb_add_char (out
, in
->ptr
[idx
]);
1303 while (idx
< in
->len
&& ISNEXTCHAR (in
->ptr
[idx
]))
1305 sb_add_char (out
, in
->ptr
[idx
]);
1309 else if (isdigit (in
->ptr
[idx
]))
1312 /* all numbers must start with a digit, let's chew it and
1314 idx
= sb_strtol (idx
, in
, radix
, &value
);
1315 sprintf (buffer
, "%d", value
);
1316 sb_add_string (out
, buffer
);
1318 /* skip all undigsested letters */
1319 while (idx
< in
->len
&& ISNEXTCHAR (in
->ptr
[idx
]))
1321 sb_add_char (out
, in
->ptr
[idx
]);
1327 /* nothing special, just pass it through */
1328 sb_add_char (out
, in
->ptr
[idx
]);
1345 do_assign (again
, idx
, in
)
1350 /* stick label in symbol table with following value */
1355 idx
= exp_parse (idx
, in
, &e
);
1356 exp_string (&e
, &acc
);
1357 hash_add_to_string_table (&assign_hash_table
, &label
, &acc
, again
);
1362 /* .radix [b|q|d|h] */
1369 int idx
= sb_skip_white (0, ptr
);
1370 switch (ptr
->ptr
[idx
])
1389 ERROR ((stderr
, "radix is %c must be one of b, q, d or h", radix
));
1394 /* Parse off a .b, .w or .l */
1397 get_opsize (idx
, in
, size
)
1403 if (in
->ptr
[idx
] == '.')
1406 switch (in
->ptr
[idx
])
1421 ERROR ((stderr
, "size must be one of b, w or l, is %c.\n", in
->ptr
[idx
]));
1429 /* .data [.b|.w|.l] <data>* */
1441 idx
= get_opsize (idx
, in
, &opsize
);
1456 fprintf (outfile
, "%s\t", opname
);
1457 while (idx
< in
->len
)
1460 idx
= exp_parse (idx
, in
, &e
);
1461 exp_string (&e
, &acc
);
1462 sb_add_char (&acc
, 0);
1463 fprintf (outfile
, acc
.ptr
);
1464 if (idx
< in
->len
&& in
->ptr
[idx
] == ',')
1466 fprintf (outfile
, ",");
1471 fprintf (outfile
, "\n");
1474 /* .datab [.b|.w|.l] <repeat>,<fill> */
1485 idx
= get_opsize (idx
, in
, &opsize
);
1487 idx
= exp_get_abs ("datab repeat must be constant.\n", idx
, in
, &repeat
);
1488 idx
= sb_skip_comma (idx
, in
);
1489 idx
= exp_get_abs ("datab data must be absolute.\n", idx
, in
, &fill
);
1491 fprintf (outfile
, ".fill\t%d,%d,%d\n", repeat
, opsize
, fill
);
1502 idx
= exp_get_abs ("align needs absolute expression.\n", idx
, in
, &al
);
1507 WARNING ((stderr
, "alignment must be one of 1, 2 or 4.\n"));
1509 fprintf (outfile
, ".align %d\n", al
);
1512 /* .res[.b|.w|.l] <size> */
1515 do_res (idx
, in
, type
)
1523 idx
= get_opsize (idx
, in
, &size
);
1524 while (idx
< in
->len
)
1526 idx
= sb_skip_white (idx
, in
);
1527 if (in
->ptr
[idx
] == ',')
1529 idx
= exp_get_abs ("res needs absolute expression for fill count.\n", idx
, in
, &count
);
1531 if (type
== 'c' || type
== 'z')
1534 fprintf (outfile
, ".space %d\n", count
* size
);
1545 fprintf (outfile
, ".global %s\n", sb_name (in
));
1548 /* .print [list] [nolist] */
1555 idx
= sb_skip_white (idx
, in
);
1556 while (idx
< in
->len
)
1558 if (strncmp (in
->ptr
+ idx
, "LIST", 4) == 0)
1560 fprintf (outfile
, ".list\n");
1563 else if (strncmp (in
->ptr
+ idx
, "NOLIST", 6) == 0)
1565 fprintf (outfile
, ".nolist\n");
1574 do_heading (idx
, in
)
1580 idx
= getstring (idx
, in
, &head
);
1581 fprintf (outfile
, ".title \"%s\"\n", sb_name (&head
));
1590 fprintf (outfile
, ".eject\n");
1593 /* .form [lin=<value>] [col=<value>] */
1601 idx
= sb_skip_white (idx
, in
);
1603 while (idx
< in
->len
)
1606 if (strncmp (in
->ptr
+ idx
, "LIN=", 4) == 0)
1609 idx
= exp_get_abs ("form LIN= needs absolute expresssion.\n", idx
, in
, &lines
);
1612 if (strncmp (in
->ptr
+ idx
, "COL=", 4) == 0)
1615 idx
= exp_get_abs ("form COL= needs absolute expresssion.\n", idx
, in
, &columns
);
1620 fprintf (outfile
, ".psize %d,%d\n", lines
, columns
);
1625 get_any_string (idx
, in
, out
)
1630 idx
= sb_skip_white (idx
, in
);
1631 if (idx
< in
->len
&& (in
->ptr
[idx
] == '"'
1632 || in
->ptr
[idx
] == '<'))
1633 return getstring (idx
, in
, out
);
1637 while (idx
< in
->len
&& !ISSEP (in
->ptr
[idx
]))
1639 sb_add_char (out
, in
->ptr
[idx
++]);
1645 /* skip along sb in starting at idx, suck off whitespace a ( and more
1646 whitespace. return the idx of the next char */
1649 skip_openp (idx
, in
)
1653 idx
= sb_skip_white (idx
, in
);
1654 if (in
->ptr
[idx
] != '(')
1655 ERROR ((stderr
, "misplaced ( .\n"));
1656 idx
= sb_skip_white (idx
+ 1, in
);
1660 /* skip along sb in starting at idx, suck off whitespace a ) and more
1661 whitespace. return the idx of the next char */
1664 skip_closep (idx
, in
)
1668 idx
= sb_skip_white (idx
, in
);
1669 if (in
->ptr
[idx
] != ')')
1670 ERROR ((stderr
, "misplaced ).\n"));
1671 idx
= sb_skip_white (idx
+ 1, in
);
1678 dolen (idx
, in
, out
)
1687 sb_new (&stringout
);
1688 idx
= skip_openp (idx
, in
);
1689 idx
= get_and_process (idx
, in
, &stringout
);
1690 idx
= skip_closep (idx
, in
);
1691 sprintf (buffer
, "%d", stringout
.len
);
1692 sb_add_string (out
, buffer
);
1694 sb_kill (&stringout
);
1703 doinstr (idx
, in
, out
)
1717 idx
= skip_openp (idx
, in
);
1718 idx
= get_and_process (idx
, in
, &string
);
1719 idx
= sb_skip_comma (idx
, in
);
1720 idx
= get_and_process (idx
, in
, &search
);
1721 idx
= sb_skip_comma (idx
, in
);
1722 if (isdigit (in
->ptr
[idx
]))
1724 idx
= exp_get_abs (".instr needs absolute expresson.\n", idx
, in
, &start
);
1730 idx
= skip_closep (idx
, in
);
1732 for (i
= start
; i
< string
.len
; i
++)
1734 if (strncmp (string
.ptr
+ i
, search
.ptr
, search
.len
) == 0)
1740 sprintf (buffer
, "%d", res
);
1741 sb_add_string (out
, buffer
);
1749 dosubstr (idx
, in
, out
)
1759 idx
= skip_openp (idx
, in
);
1760 idx
= get_and_process (idx
, in
, &string
);
1761 idx
= sb_skip_comma (idx
, in
);
1762 idx
= exp_get_abs ("need absolute position.\n", idx
, in
, &pos
);
1763 idx
= sb_skip_comma (idx
, in
);
1764 idx
= exp_get_abs ("need absolute length.\n", idx
, in
, &len
);
1765 idx
= skip_closep (idx
, in
);
1768 if (len
< 0 || pos
< 0 ||
1770 || pos
+ len
> string
.len
)
1772 sb_add_string (out
, " ");
1776 sb_add_char (out
, '"');
1779 sb_add_char (out
, string
.ptr
[pos
++]);
1782 sb_add_char (out
, '"');
1788 /* scan line, change tokens in the hash table to their replacements */
1790 process_assigns (idx
, in
, buf
)
1795 while (idx
< in
->len
)
1798 if (in
->ptr
[idx
] == '\\'
1799 && in
->ptr
[idx
+ 1] == '&')
1801 idx
= condass_lookup_name (in
, idx
+ 2, buf
);
1803 else if (idx
+ 3 < in
->len
1804 && in
->ptr
[idx
] == '.'
1805 && in
->ptr
[idx
+ 1] == 'L'
1806 && in
->ptr
[idx
+ 2] == 'E'
1807 && in
->ptr
[idx
+ 3] == 'N')
1808 idx
= dolen (idx
+ 4, in
, buf
);
1809 else if (idx
+ 6 < in
->len
1810 && in
->ptr
[idx
] == '.'
1811 && in
->ptr
[idx
+ 1] == 'I'
1812 && in
->ptr
[idx
+ 2] == 'N'
1813 && in
->ptr
[idx
+ 3] == 'S'
1814 && in
->ptr
[idx
+ 4] == 'T'
1815 && in
->ptr
[idx
+ 5] == 'R')
1816 idx
= doinstr (idx
+ 6, in
, buf
);
1817 else if (idx
+ 7 < in
->len
1818 && in
->ptr
[idx
] == '.'
1819 && in
->ptr
[idx
+ 1] == 'S'
1820 && in
->ptr
[idx
+ 2] == 'U'
1821 && in
->ptr
[idx
+ 3] == 'B'
1822 && in
->ptr
[idx
+ 4] == 'S'
1823 && in
->ptr
[idx
+ 5] == 'T'
1824 && in
->ptr
[idx
+ 6] == 'R')
1825 idx
= dosubstr (idx
+ 7, in
, buf
);
1826 else if (ISFIRSTCHAR (in
->ptr
[idx
]))
1828 /* may be a simple name subsitution, see if we have a word */
1831 while (cur
< in
->len
1832 && (ISNEXTCHAR (in
->ptr
[cur
])))
1836 sb_add_buffer (&acc
, in
->ptr
+ idx
, cur
- idx
);
1837 ptr
= hash_lookup (&assign_hash_table
, &acc
);
1840 /* Found a definition for it */
1841 sb_add_sb (buf
, &ptr
->value
.s
);
1845 /* No definition, just copy the word */
1846 sb_add_sb (buf
, &acc
);
1853 sb_add_char (buf
, in
->ptr
[idx
++]);
1859 get_and_process (idx
, in
, out
)
1866 idx
= get_any_string (idx
, in
, &t
);
1867 process_assigns (0, &t
, out
);
1887 more
= get_line (&line
);
1890 /* Find any label and pseudo op that we're intested in */
1895 fprintf (outfile
, "\n");
1900 l
= grab_label (&line
, &label
);
1901 if (line
.ptr
[l
] == ':')
1903 while (ISWHITE (line
.ptr
[l
]) && l
< line
.len
)
1908 if (process_pseudo_op (l
, &line
, &acc
))
1914 else if (condass_on ())
1916 if (macro_op (l
, &line
))
1926 fprintf (outfile
, "%s:\t", sb_name (&label
));
1929 fprintf (outfile
, "\t");
1931 process_assigns (l
, &line
, &t1
);
1933 change_base (0, &t1
, &t2
);
1934 fprintf (outfile
, "%s\n", sb_name (&t2
));
1944 more
= get_line (&line
);
1948 WARNING ((stderr
, ".END missing from end of file.\n"));
1956 free_old_entry (ptr
)
1961 if (ptr
->type
== hash_string
)
1962 sb_kill(&ptr
->value
.s
);
1966 /* name: .ASSIGNA <value> */
1969 do_assigna (idx
, in
)
1977 process_assigns (idx
, in
, &tmp
);
1978 idx
= exp_get_abs (".ASSIGNA needs constant expression argument.\n", 0, &tmp
, &val
);
1982 ERROR ((stderr
, ".ASSIGNA without label.\n"));
1986 hash_entry
*ptr
= hash_create (&vars
, &label
);
1987 free_old_entry (ptr
);
1988 ptr
->type
= hash_integer
;
1994 /* name: .ASSIGNC <string> */
1997 do_assignc (idx
, in
)
2003 idx
= getstring (idx
, in
, &acc
);
2007 ERROR ((stderr
, ".ASSIGNS without label.\n"));
2011 hash_entry
*ptr
= hash_create (&vars
, &label
);
2012 free_old_entry (ptr
);
2013 ptr
->type
= hash_string
;
2014 sb_new (&ptr
->value
.s
);
2015 sb_add_sb (&ptr
->value
.s
, &acc
);
2021 /* name: .REG (reg) */
2028 /* remove reg stuff from inside parens */
2030 idx
= skip_openp (idx
, in
);
2032 while (idx
< in
->len
&& in
->ptr
[idx
] != ')')
2034 sb_add_char (&what
, in
->ptr
[idx
]);
2037 hash_add_to_string_table (&assign_hash_table
, &label
, &what
, 1);
2043 condass_lookup_name (inbuf
, idx
, out
)
2050 sb_new (&condass_acc
);
2052 while (idx
< inbuf
->len
2053 && ISNEXTCHAR (inbuf
->ptr
[idx
]))
2055 sb_add_char (&condass_acc
, inbuf
->ptr
[idx
++]);
2058 if (inbuf
->ptr
[idx
] == '\'')
2060 ptr
= hash_lookup (&vars
, &condass_acc
);
2063 WARNING ((stderr
, "Can't find preprocessor variable %s.\n", sb_name (&condass_acc
)));
2067 if (ptr
->type
== hash_integer
)
2070 sprintf (buffer
, "%d", ptr
->value
.i
);
2071 sb_add_string (out
, buffer
);
2075 sb_add_sb (out
, &ptr
->value
.s
);
2078 sb_kill (&condass_acc
);
2091 whatcond (idx
, in
, val
)
2098 idx
= sb_skip_white (idx
, in
);
2100 if (p
[0] == 'E' && p
[1] == 'Q')
2102 else if (p
[0] == 'N' && p
[1] == 'E')
2104 else if (p
[0] == 'L' && p
[1] == 'T')
2106 else if (p
[0] == 'L' && p
[1] == 'E')
2108 else if (p
[0] == 'G' && p
[1] == 'T')
2110 else if (p
[0] == 'G' && p
[1] == 'E')
2114 ERROR ((stderr
, "Comparison operator must be one of EQ, NE, LT, LE, GT or GE"));
2117 idx
= sb_skip_white (idx
+ 2, in
);
2134 idx
= sb_skip_white (idx
, in
);
2136 if (in
->ptr
[idx
] == '"')
2140 /* This is a string comparision */
2141 idx
= getstring (idx
, in
, &acc_a
);
2142 idx
= whatcond (idx
, in
, &cond
);
2143 idx
= getstring (idx
, in
, &acc_b
);
2144 same
= acc_a
.len
== acc_b
.len
&& (strncmp (acc_a
.ptr
, acc_b
.ptr
, acc_a
.len
) == 0);
2146 if (cond
!= EQ
&& cond
!= NE
)
2148 ERROR ((stderr
, "Comparison operator for strings must be EQ or NE"));
2152 res
= cond
== EQ
&& same
;
2155 /* This is a numeric expression */
2160 idx
= exp_get_abs ("Conditional operator must have absolute operands.\n", idx
, in
, &vala
);
2161 idx
= whatcond (idx
, in
, &cond
);
2162 idx
= sb_skip_white (idx
, in
);
2163 if (in
->ptr
[idx
] == '"')
2165 WARNING ((stderr
, "String compared against expression.\n"));
2170 idx
= exp_get_abs ("Conditional operator must have absolute operands.\n", idx
, in
, &valb
);
2210 if (ifi
>= IFNESTING
)
2212 FATAL ((stderr
, "AIF nesting unreasonable.\n"));
2215 ifstack
[ifi
].on
= istrue (idx
, in
);
2216 ifstack
[ifi
].hadelse
= 0;
2224 ifstack
[ifi
].on
= !ifstack
[ifi
].on
;
2225 if (ifstack
[ifi
].hadelse
)
2227 ERROR ((stderr
, "Multiple AELSEs in AIF.\n"));
2229 ifstack
[ifi
].hadelse
= 1;
2243 ERROR ((stderr
, "AENDI without AIF.\n"));
2250 return ifstack
[ifi
].on
;
2254 /* Read input lines till we get to a TO string.
2255 Increase nesting depth if we geta FROM string.
2256 Put the results into sb at PTR. */
2259 buffer_and_nest (from
, to
, ptr
)
2264 int from_len
= strlen (from
);
2265 int to_len
= strlen (to
);
2267 int line_start
= ptr
->len
;
2268 int line
= linecount ();
2270 int more
= get_line (ptr
);
2274 /* Try and find the first pseudo op on the line */
2277 /* Skip leading whitespace */
2279 && ISWHITE (ptr
->ptr
[i
]))
2282 /* Skip over a label */
2284 && ISNEXTCHAR (ptr
->ptr
[i
]))
2289 && ptr
->ptr
[i
] == ':')
2292 /* Skip trailing whitespace */
2294 && ISWHITE (ptr
->ptr
[i
]))
2298 && ptr
->ptr
[i
] == '.')
2300 if (strncmp (ptr
->ptr
+ i
, from
, from_len
) == 0)
2302 if (strncmp (ptr
->ptr
+ i
, to
, to_len
) == 0)
2307 /* Reset the string to not include the ending rune */
2308 ptr
->len
= line_start
;
2314 /* Add a CR to the end and keep running */
2315 sb_add_char (ptr
, '\n');
2316 line_start
= ptr
->len
;
2317 more
= get_line (ptr
);
2322 FATAL ((stderr
, "End of file whilst inside %s, started on line %d.\n", from
, line
));
2330 ERROR ((stderr
, "AENDR without a AREPEAT.\n"));
2349 process_assigns (idx
, in
, &exp
);
2350 doit
= istrue (0, &exp
);
2352 buffer_and_nest (".AWHILE", ".AENDW", &sub
);
2367 int index
= include_next_index ();
2371 sb_add_sb (©
, &sub
);
2372 sb_add_sb (©
, in
);
2373 sb_add_string (©
, "\n");
2374 sb_add_sb (©
, &sub
);
2375 sb_add_string (©
, "\t.AENDW\n");
2376 /* Push another WHILE */
2377 include_buf (&exp
, ©
, include_while
, index
);
2390 ERROR ((stderr
, "AENDW without a AENDW.\n"));
2396 Pop things off the include stack until the type and index changes */
2401 include_type type
= sp
->type
;
2402 if (type
== include_repeat
2403 || type
== include_while
2404 || type
== include_macro
)
2406 int index
= sp
->index
;
2408 while (sp
->index
== index
2409 && sp
->type
== type
)
2419 do_arepeat (idx
, in
)
2423 sb exp
; /* buffer with expression in it */
2424 sb copy
; /* expanded repeat block */
2425 sb sub
; /* contents of AREPEAT */
2431 process_assigns (idx
, in
, &exp
);
2432 idx
= exp_get_abs ("AREPEAT must have absolute operand.\n", 0, &exp
, &rc
);
2433 buffer_and_nest (".AREPEAT", ".AENDR", &sub
);
2436 /* Push back the text following the repeat, and another repeat block
2447 int index
= include_next_index ();
2448 sb_add_sb (©
, &sub
);
2451 sprintf (buffer
, "\t.AREPEAT %d\n", rc
- 1);
2452 sb_add_string (©
, buffer
);
2453 sb_add_sb (©
, &sub
);
2454 sb_add_string (©
, " .AENDR\n");
2457 include_buf (&exp
, ©
, include_repeat
, index
);
2469 ERROR ((stderr
, ".ENDM without a matching .MACRO.\n"));
2473 /* MARRO PROCESSING */
2476 hash_table macro_table
;
2486 do_formals (macro
, idx
, in
)
2491 formal_entry
**p
= ¯o
->formals
;
2492 macro
->formal_count
= 0;
2493 hash_new_table (5, ¯o
->formal_hash
);
2494 while (idx
< in
->len
)
2496 formal_entry
*formal
;
2498 formal
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
2500 sb_new (&formal
->name
);
2501 sb_new (&formal
->def
);
2502 sb_new (&formal
->actual
);
2504 idx
= sb_skip_white (idx
, in
);
2505 idx
= get_token (idx
, in
, &formal
->name
);
2506 if (formal
->name
.len
== 0)
2508 idx
= sb_skip_white (idx
, in
);
2509 if (formal
->name
.len
)
2511 /* This is a formal */
2512 if (idx
< in
->len
&& in
->ptr
[idx
] == '=')
2515 idx
= get_any_string (idx
+ 1, in
, &formal
->def
);
2520 /* Add to macro's hash table */
2522 hash_entry
*p
= hash_create (¯o
->formal_hash
, &formal
->name
);
2523 p
->type
= hash_formal
;
2524 p
->value
.f
= formal
;
2527 formal
->index
= macro
->formal_count
;
2528 idx
= sb_skip_comma (idx
, in
);
2529 macro
->formal_count
++;
2545 macro
= (macro_entry
*) xmalloc (sizeof (macro_entry
));
2546 sb_new (¯o
->sub
);
2549 macro
->formal_count
= 0;
2552 idx
= sb_skip_white (idx
, in
);
2553 buffer_and_nest (".MACRO", ".ENDM", ¯o
->sub
);
2556 /* It's the label: MACRO (formals,...) sort */
2557 sb_add_sb (&name
, &label
);
2558 if (in
->ptr
[idx
] == '(')
2560 /* Got some formals */
2561 idx
= do_formals (macro
, idx
+ 1, in
);
2562 if (in
->ptr
[idx
] != ')')
2563 ERROR ((stderr
, "Missing ) after formals.\n"));
2568 idx
= get_token (idx
, in
, &name
);
2569 idx
= sb_skip_white (idx
, in
);
2570 idx
= do_formals (macro
, idx
, in
);
2573 /* and stick it in the macro hash table */
2574 hash_create (¯o_table
, &name
)->value
.m
= macro
;
2579 get_token (idx
, in
, name
)
2585 && ISFIRSTCHAR (in
->ptr
[idx
]))
2587 sb_add_char (name
, in
->ptr
[idx
++]);
2588 while (idx
< in
->len
2589 && ISNEXTCHAR (in
->ptr
[idx
]))
2591 sb_add_char (name
, in
->ptr
[idx
++]);
2597 /* Scan a token, but stop if a ' is seen */
2599 get_apost_token (idx
, in
, name
, kind
)
2605 idx
= get_token (idx
, in
, name
);
2606 if (idx
< in
->len
&& in
->ptr
[idx
] == kind
)
2612 sub_actual (src
, in
, t
, m
, kind
, out
)
2620 /* This is something to take care of */
2622 src
= get_apost_token (src
, in
, t
, kind
);
2623 /* See if it's in the macro's hash table */
2624 ptr
= hash_lookup (&m
->formal_hash
, t
);
2627 if (ptr
->value
.f
->actual
.len
)
2629 sb_add_sb (out
, &ptr
->value
.f
->actual
);
2633 sb_add_sb (out
, &ptr
->value
.f
->def
);
2638 sb_add_char (out
, '\\');
2646 macro_expand (name
, idx
, in
, m
)
2657 int is_positional
= 0;
2663 /* Reset any old value the actuals may have */
2664 for (f
= m
->formals
; f
; f
= f
->next
)
2665 sb_reset (&f
->actual
);
2667 /* Peel off the actuals and store them away in the hash tables' actuals */
2668 while (idx
< in
->len
)
2671 idx
= sb_skip_white (idx
, in
);
2672 /* Look and see if it's a positional or keyword arg */
2674 while (scan
< in
->len
2675 && !ISSEP (in
->ptr
[scan
])
2676 && in
->ptr
[scan
] != '=')
2678 if (scan
< in
->len
&& in
->ptr
[scan
] == '=')
2683 ERROR ((stderr
, "Can't mix positional and keyword arguments.\n"));
2686 /* This is a keyword arg, fetch the formal name and
2687 then the actual stuff */
2689 idx
= get_token (idx
, in
, &t
);
2690 if (in
->ptr
[idx
] != '=')
2691 ERROR ((stderr
, "confused about formal params.\n"));
2693 /* Lookup the formal in the macro's list */
2694 ptr
= hash_lookup (&m
->formal_hash
, &t
);
2697 ERROR ((stderr
, "MACRO formal argument %s does not exist.\n", sb_name (&t
)));
2702 /* Insert this value into the right place */
2703 sb_reset (&ptr
->value
.f
->actual
);
2704 idx
= get_any_string (idx
+ 1, in
, &ptr
->value
.f
->actual
);
2709 /* This is a positional arg */
2713 ERROR ((stderr
, "Can't mix positional and keyword arguments.\n"));
2718 ERROR ((stderr
, "Too many positional arguments.\n"));
2722 sb_reset (&f
->actual
);
2723 idx
= get_any_string (idx
, in
, &f
->actual
);
2726 idx
= sb_skip_comma (idx
, in
);
2729 /* Copy the stuff from the macro buffer into a safe place and substitute any args */
2736 while (src
< in
->len
)
2738 if (in
->ptr
[src
] == '&')
2741 src
= sub_actual (src
+ 1, in
, &t
, m
, '&', &out
);
2743 else if (in
->ptr
[src
] == '\\')
2746 if (in
->ptr
[src
] == ';')
2748 /* This is a comment, just drop the rest of the line */
2749 while (src
< in
->len
2750 && in
->ptr
[src
] != '\n')
2754 else if (in
->ptr
[src
] == '(')
2756 /* Sub in till the next ')' literally */
2758 while (src
< in
->len
&& in
->ptr
[src
] != ')')
2760 sb_add_char (&out
, in
->ptr
[src
++]);
2762 if (in
->ptr
[src
] == ')')
2765 ERROR ((stderr
, "Missplaced ).\n"));
2767 else if (in
->ptr
[src
] == '@')
2769 /* Sub in the macro invocation number */
2773 sprintf (buffer
, "%05d", number
);
2774 sb_add_string (&out
, buffer
);
2776 else if (in
->ptr
[src
] == '&')
2778 /* This is a preprocessor variable name, we don't do them
2780 sb_add_char (&out
, '\\');
2781 sb_add_char (&out
, '&');
2787 src
= sub_actual (src
, in
, &t
, m
, '\'', &out
);
2792 sb_add_char (&out
, in
->ptr
[src
++]);
2795 include_buf (name
, &out
, include_macro
, include_next_index ());
2808 /* The macro name must be the first thing on the line */
2814 idx
= get_token (idx
, in
, &name
);
2818 /* Got a name, look it up */
2820 ptr
= hash_lookup (¯o_table
, &name
);
2824 /* It's in the table, copy out the stuff and convert any macro args */
2825 macro_expand (&name
, idx
, in
, ptr
->value
.m
);
2837 /* STRING HANDLING */
2840 getstring (idx
, in
, acc
)
2845 idx
= sb_skip_white (idx
, in
);
2847 while (idx
< in
->len
2848 && (in
->ptr
[idx
] == '"' || in
->ptr
[idx
] == '<'))
2850 if (in
->ptr
[idx
] == '<')
2854 idx
= exp_get_abs ("Character code in string must be absolute expression.\n",
2856 sb_add_char (acc
, code
);
2858 if (in
->ptr
[idx
] != '>')
2859 ERROR ((stderr
, "Missing > for character code.\n"));
2862 else if (in
->ptr
[idx
] == '"')
2865 while (idx
< in
->len
)
2867 if (in
->ptr
[idx
] == '"')
2870 if (idx
>= in
->len
|| in
->ptr
[idx
] != '"')
2873 sb_add_char (acc
, in
->ptr
[idx
]);
2882 /* .SDATA[C|Z] <string> */
2886 do_sdata (idx
, in
, type
)
2894 fprintf (outfile
, ".byte\t");
2896 while (idx
< in
->len
)
2900 idx
= sb_skip_white (idx
, in
);
2901 while ((in
->ptr
[idx
] == '"'
2902 || in
->ptr
[idx
] == '<')
2905 idx
= getstring (idx
, in
, &acc
);
2910 ERROR ((stderr
, "string for SDATAC longer than 255 characters (%d).\n", acc
.len
));
2912 fprintf (outfile
, "%d", acc
.len
);
2916 for (i
= 0; i
< acc
.len
; i
++)
2920 fprintf (outfile
, ",");
2922 fprintf (outfile
, "%d", acc
.ptr
[i
]);
2929 fprintf (outfile
, ",");
2930 fprintf (outfile
, "0");
2932 idx
= sb_skip_white (idx
, in
);
2934 if (in
->ptr
[idx
] != ',' && idx
!= in
->len
)
2936 fprintf (outfile
, "\n");
2937 ERROR ((stderr
, "illegal character in SDATA line (0x%x).\n", in
->ptr
[idx
]));
2943 fprintf (outfile
, "\n");
2946 /* .SDATAB <count> <string> */
2958 idx
= exp_get_abs ("Must have absolute SDATAB repeat count.\n", idx
, in
, &repeat
);
2961 ERROR ((stderr
, "Must have positive SDATAB repeat count (%d).\n", repeat
));
2965 idx
= sb_skip_comma (idx
, in
);
2966 idx
= getstring (idx
, in
, &acc
);
2968 for (i
= 0; i
< repeat
; i
++)
2971 fprintf (outfile
, "\t");
2972 fprintf (outfile
, ".byte\t");
2974 fprintf (outfile
, "\n");
2984 FILE *newone
= fopen (name
, "r");
2988 if (isp
== MAX_INCLUDES
)
2989 FATAL ((stderr
, "Unreasonable include depth (%d).\n", isp
));
2992 sp
->handle
= newone
;
2995 sb_add_string (&sp
->name
, name
);
2998 sp
->pushback_index
= 0;
2999 sp
->type
= include_file
;
3001 sb_new (&sp
->pushback
);
3006 do_include (idx
, in
)
3013 idx
= getstring (idx
, in
, &t
);
3014 text
= sb_name (&t
);
3015 if (!new_file (text
))
3017 FATAL ((stderr
, "Can't open include file `%s'.\n", text
));
3025 if (sp
!= include_stack
)
3028 fclose (sp
->handle
);
3033 /* Get the next character from the include stack. If there's anything
3034 in the pushback buffer, take that first. If we're at eof, pop from
3035 the stack and try again. Keep the linecount up to date. */
3042 if (sp
->pushback
.len
!= sp
->pushback_index
)
3044 r
= (char) (sp
->pushback
.ptr
[sp
->pushback_index
++]);
3045 /* When they've all gone, reset the pointer */
3046 if (sp
->pushback_index
== sp
->pushback
.len
)
3048 sp
->pushback
.len
= 0;
3049 sp
->pushback_index
= 0;
3052 else if (sp
->handle
)
3054 r
= getc (sp
->handle
);
3059 if (r
== EOF
&& isp
)
3063 while (r
== EOF
&& isp
)
3081 return sp
->linecount
;
3085 include_next_index ()
3089 && index
> MAX_REASONABLE
)
3090 FATAL ((stderr
, "Unreasonable expansion (-u turns off check).\n"));
3095 /* Initialize the chartype vector. */
3101 for (x
= 0; x
< 256; x
++)
3103 if (isalpha (x
) || x
== '_' || x
== '$')
3104 chartype
[x
] |= FIRSTBIT
;
3106 if (isdigit (x
) || isalpha (x
) || x
== '_' || x
== '$')
3107 chartype
[x
] |= NEXTBIT
;
3109 if (x
== ' ' || x
== '\t' || x
== ',' || x
== '"' || x
== ';'
3110 || x
== '"' || x
== '<' || x
== '>' || x
== ')' || x
== '(')
3111 chartype
[x
] |= SEPBIT
;
3113 if (x
== ' ' || x
== '\t')
3114 chartype
[x
] |= WHITEBIT
;
3119 /* What to do with all the keywords */
3120 #define PROCESS 0x1000 /* Run substitution over the line */
3121 #define LAB 0x2000 /* Spit out the label */
3123 #define K_EQU PROCESS|1
3124 #define K_ASSIGN PROCESS|2
3125 #define K_REG PROCESS|3
3126 #define K_ORG PROCESS|4
3127 #define K_RADIX PROCESS|5
3128 #define K_DATA LAB|PROCESS|6
3129 #define K_DATAB LAB|PROCESS|7
3130 #define K_SDATA LAB|PROCESS|8
3131 #define K_SDATAB LAB|PROCESS|9
3132 #define K_SDATAC LAB|PROCESS|10
3133 #define K_SDATAZ LAB|PROCESS|11
3134 #define K_RES LAB|PROCESS|12
3135 #define K_SRES LAB|PROCESS|13
3136 #define K_SRESC LAB|PROCESS|14
3137 #define K_SRESZ LAB|PROCESS|15
3138 #define K_EXPORT LAB|PROCESS|16
3139 #define K_GLOBAL LAB|PROCESS|17
3140 #define K_PRINT LAB|PROCESS|19
3141 #define K_FORM LAB|PROCESS|20
3142 #define K_HEADING LAB|PROCESS|21
3143 #define K_PAGE LAB|PROCESS|22
3144 #define K_IMPORT LAB|PROCESS|23
3145 #define K_PROGRAM LAB|PROCESS|24
3146 #define K_END PROCESS|25
3147 #define K_INCLUDE PROCESS|26
3148 #define K_IGNORED PROCESS|27
3149 #define K_ASSIGNA 28
3150 #define K_ASSIGNC 29
3151 #define K_AIF PROCESS|30
3152 #define K_AELSE PROCESS|31
3153 #define K_AENDI PROCESS|32
3154 #define K_AREPEAT PROCESS|33
3155 #define K_AENDR PROCESS|34
3157 #define K_AENDW PROCESS|36
3159 #define K_MACRO PROCESS|38
3161 #define K_ALIGN PROCESS|LAB|40
3173 "ASSIGN", K_ASSIGN
, 0,
3176 "RADIX", K_RADIX
, 0,
3178 "DATAB", K_DATAB
, 0,
3179 "SDATA", K_SDATA
, 0,
3180 "SDATAB", K_SDATAB
, 0,
3181 "SDATAZ", K_SDATAZ
, 0,
3182 "SDATAC", K_SDATAC
, 0,
3185 "SRESC", K_SRESC
, 0,
3186 "SRESZ", K_SRESZ
, 0,
3187 "EXPORT", K_EXPORT
, 0,
3188 "GLOBAL", K_GLOBAL
, 0,
3189 "PRINT", K_PRINT
, 0,
3191 "HEADING", K_HEADING
, 0,
3193 "PROGRAM", K_IGNORED
, 0,
3195 "INCLUDE", K_INCLUDE
, 0,
3196 "ASSIGNA", K_ASSIGNA
, 0,
3197 "ASSIGNC", K_ASSIGNC
, 0,
3199 "AELSE", K_AELSE
, 0,
3200 "AENDI", K_AENDI
, 0,
3201 "AREPEAT", K_AREPEAT
, 0,
3202 "AENDR", K_AENDR
, 0,
3203 "EXITM", K_EXITM
, 0,
3204 "MACRO", K_MACRO
, 0,
3206 "AWHILE", K_AWHILE
, 0,
3207 "ALIGN", K_ALIGN
, 0,
3208 "AENDW", K_AENDW
, 0,
3212 /* Look for a pseudo op on the line. If one's there then call
3216 process_pseudo_op (idx
, line
, acc
)
3221 char *in
= line
->ptr
+ idx
;
3225 /* Scan forward and find pseudo name */
3232 while (idx
< line
->len
&& *e
&& ISFIRSTCHAR (*e
))
3234 sb_add_char (acc
, *e
);
3239 ptr
= hash_lookup (&keyword_hash_table
, acc
);
3243 WARNING ((stderr
, "Unrecognised pseudo op `%s'.\n", sb_name (acc
)));
3246 if (ptr
->value
.i
& LAB
)
3247 { /* output the label */
3250 fprintf (outfile
, "%s:\t", sb_name (&label
));
3253 fprintf (outfile
, "\t");
3256 if (ptr
->value
.i
& PROCESS
)
3258 /* Polish the rest of the line before handling the pseudo op */
3259 /* strip_comments(line);*/
3261 process_assigns (idx
, line
, acc
);
3263 change_base (0, acc
, line
);
3268 switch (ptr
->value
.i
)
3281 switch (ptr
->value
.i
)
3290 ERROR ((stderr
, "ORG command not allowed.\n"));
3296 do_data (idx
, line
);
3299 do_datab (idx
, line
);
3302 do_sdata (idx
, line
, 0);
3305 do_sdatab (idx
, line
);
3308 do_sdata (idx
, line
, 'c');
3311 do_sdata (idx
, line
, 'z');
3314 do_assign (1, 0, line
);
3320 do_arepeat (idx
, line
);
3326 do_awhile (idx
, line
);
3332 do_assign (0, idx
, line
);
3335 do_align (idx
, line
);
3338 do_res (idx
, line
, 0);
3341 do_res (idx
, line
, 's');
3344 do_include (idx
, line
);
3347 do_macro (idx
, line
);
3353 do_res (idx
, line
, 'c');
3356 do_print (idx
, line
);
3359 do_form (idx
, line
);
3362 do_heading (idx
, line
);
3374 do_res (idx
, line
, 'z');
3382 do_assigna (idx
, line
);
3385 do_assignc (idx
, line
);
3401 /* Build the keyword hash table - put each keyword in the table twice,
3402 once upper and once lower case.*/
3409 for (i
= 0; kinfo
[i
].name
; i
++)
3414 sb_add_string (&label
, kinfo
[i
].name
);
3416 hash_add_to_int_table (&keyword_hash_table
, &label
, kinfo
[i
].code
);
3419 for (j
= 0; kinfo
[i
].name
[j
]; j
++)
3420 sb_add_char (&label
, kinfo
[i
].name
[j
] - 'A' + 'a');
3421 hash_add_to_int_table (&keyword_hash_table
, &label
, kinfo
[i
].code
);
3441 hash_new_table (101, ¯o_table
);
3442 hash_new_table (101, &keyword_hash_table
);
3443 hash_new_table (101, &assign_hash_table
);
3444 hash_new_table (101, &vars
);
3449 /* Find the output file */
3450 for (i
= 1; i
< ac
; i
++)
3452 if (av
[i
][0] == '-')
3454 if (av
[i
][1] == 'c' && av
[i
][2] == 0)
3458 else if (av
[i
][1] == 'p' && av
[i
][2] == 0)
3460 print_line_number
= 1;
3462 else if (av
[i
][1] == 'u' && av
[i
][2] == 0)
3466 else if (av
[i
][1] == 's' && av
[i
][2] == 0)
3470 else if (av
[i
][1] == 'o' && av
[i
][2] == 0 & i
+ 1 < ac
)
3472 /* Got output file name */
3474 outfile
= fopen (av
[i
], "w");
3477 fprintf (stderr
, "%s: Can't open output file `%s'.\n",
3484 fprintf (stderr
, "Usage: %s [-o filename] infile1 infile2...\n",
3494 /* Process all the input files */
3496 for (i
= 1; i
< ac
; i
++)
3498 if (av
[i
][0] == '-')
3500 if (av
[i
][1] == 'o')
3505 if (new_file (av
[i
]))
3511 fprintf (stderr
, "%s: Can't open input file `%s'.\n",