1 /* gasp.c - Gnu assembler preprocessor main program.
2 Copyright (C) 1994 Free Software Foundation, Inc.
4 Written by Steve and Judy Chamberlain of Cygnus Support,
7 This file is part of GASP, the GNU Assembler Preprocessor.
9 GASP is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
14 GASP is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GASP; see the file COPYING. If not, write to
21 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
25 This program translates the input macros and stuff into a form
26 suitable for gas to consume.
29 gasp [-sdhau] [-c char] [-o <outfile>] <infile>*
31 -s copy source to output
32 -c <char> comments are started with <char> instead of !
33 -u allow unreasonable stuff
35 -d print debugging stats
36 -s semi colons start comments
37 -a use alternate syntax
38 Pseudo ops can start with or without a .
39 Labels have to be in first column.
40 Macro arg parameters subsituted by name, don't need the &.
41 String can start with ' too.
42 Strings can be surrounded by <..>
43 A %<exp> in a string evaluates the expression
44 Literal char in a string with !
59 #ifdef NEED_MALLOC_DECLARATION
60 extern char *malloc ();
63 #include "libiberty.h"
65 char *program_version
= "1.2";
67 #define MAX_INCLUDES 30 /* Maximum include depth */
68 #define MAX_REASONABLE 1000 /* Maximum number of expansions */
70 int unreasonable
; /* -u on command line */
71 int stats
; /* -d on command line */
72 int print_line_number
; /* -p flag on command line */
73 int copysource
; /* -c flag on command line */
74 int warnings
; /* Number of WARNINGs generated so far. */
75 int errors
; /* Number of ERRORs generated so far. */
76 int fatals
; /* Number of fatal ERRORs generated so far (either 0 or 1). */
77 int alternate
= 0; /* -a on command line */
78 char comment_char
= '!';
79 int radix
= 10; /* Default radix */
81 int had_end
; /* Seen .END */
83 /* The output stream */
87 /* Forward declarations. */
88 static int condass_lookup_name();
89 static int condass_on();
91 static int get_and_process();
92 static int get_token();
93 static int getstring();
94 static int include_next_index();
95 static int macro_op();
96 static int linecount();
97 static int process_pseudo_op();
98 static void include_pop();
99 static void include_print_where_line();
102 I had a couple of choices when deciding upon this data structure.
103 gas uses null terminated strings for all its internal work. This
104 often means that parts of the program that want to examine
105 substrings have to manipulate the data in the string to do the
106 right thing (a common operation is to single out a bit of text by
107 saving away the character after it, nulling it out, operating on
108 the substring and then replacing the character which was under the
109 null). This is a pain and I remember a load of problems that I had with
110 code in gas which almost got this right. Also, it's harder to grow and
111 allocate null terminated strings efficiently.
113 Obstacks provide all the functionality needed, but are too
114 complicated, hence the sb.
116 An sb is allocated by the caller, and is initialzed to point to an
117 sb_element. sb_elements are kept on a free lists, and used when
118 needed, replaced onto the free list when unused.
121 #define max_power_two 30 /* don't allow strings more than
122 2^max_power_two long */
123 /* structure of an sb */
126 char *ptr
; /* points to the current block. */
127 int len
; /* how much is used. */
128 int pot
; /* the maximum length is 1<<pot */
133 /* Structure of the free list object of an sb */
145 sb_element
*size
[max_power_two
];
148 sb_list_vector free_list
;
150 int string_count
[max_power_two
];
152 /* the attributes of each character are stored as a bit pattern
153 chartype, which gives us quick tests. */
160 #define COMMENTBIT 16
162 #define ISCOMMENTCHAR(x) (chartype[(unsigned)(x)] & COMMENTBIT)
163 #define ISFIRSTCHAR(x) (chartype[(unsigned)(x)] & FIRSTBIT)
164 #define ISNEXTCHAR(x) (chartype[(unsigned)(x)] & NEXTBIT)
165 #define ISSEP(x) (chartype[(unsigned)(x)] & SEPBIT)
166 #define ISWHITE(x) (chartype[(unsigned)(x)] & WHITEBIT)
167 #define ISBASE(x) (chartype[(unsigned)(x)] & BASEBIT)
168 static char chartype
[256];
171 /* Conditional assembly uses the `ifstack'. Each aif pushes another
172 entry onto the stack, and sets the on flag if it should. The aelse
173 sets hadelse, and toggles on. An aend pops a level. We limit to
174 100 levels of nesting, not because we're facists pigs with read
175 only minds, but because more than 100 levels of nesting is probably
176 a bug in the user's macro structure. */
178 #define IFNESTING 100
181 int on
; /* is the level being output */
182 int hadelse
; /* has an aelse been seen */
187 /* The final and intermediate results of expression evaluation are kept in
188 exp_t's. Note that a symbol is not an sb, but a pointer into the input
189 line. It must be coped somewhere safe before the next line is read in. */
200 int value
; /* constant part */
201 symbol add_symbol
; /* name part */
202 symbol sub_symbol
; /* name part */
207 /* Hashing is done in a pretty standard way. A hash_table has a
208 pointer to a vector of pointers to hash_entrys, and the size of the
209 vector. A hash_entry contains a union of all the info we like to
210 store in hash table. If there is a hash collision, hash_entries
211 with the same hash are kept in a chain. */
213 /* What the data in a hash_entry means */
216 hash_integer
, /* name->integer mapping */
217 hash_string
, /* name->string mapping */
218 hash_macro
, /* name is a macro */
219 hash_formal
/* name is a formal argument */
224 sb key
; /* symbol name */
225 hash_type type
; /* symbol meaning */
230 struct macro_struct
*m
;
231 struct formal_struct
*f
;
233 struct hs
*next
; /* next hash_entry with same hash key */
243 /* Structures used to store macros.
245 Each macro knows its name and included text. It gets built with a
246 list of formal arguments, and also keeps a hash table which points
247 into the list to speed up formal search. Each formal knows its
248 name and its default value. Each time the macro is expanded, the
249 formals get the actual values attatched to them. */
251 /* describe the formal arguments to a macro */
253 typedef struct formal_struct
255 struct formal_struct
*next
; /* next formal in list */
256 sb name
; /* name of the formal */
257 sb def
; /* the default value */
258 sb actual
; /* the actual argument (changed on each expansion) */
259 int index
; /* the index of the formal 0..formal_count-1 */
263 /* describe the macro. */
265 typedef struct macro_struct
267 sb sub
; /* substitution text. */
268 int formal_count
; /* number of formal args. */
269 formal_entry
*formals
; /* pointer to list of formal_structs */
270 hash_table formal_hash
; /* hash table of formals. */
274 /* how we nest files and expand macros etc.
276 we keep a stack of of include_stack structs. each include file
277 pushes a new level onto the stack. we keep an sb with a pushback
278 too. unget chars are pushed onto the pushback sb, getchars first
279 checks the pushback sb before reading from the input stream.
281 small things are expanded by adding the text of the item onto the
282 pushback sb. larger items are grown by pushing a new level and
283 allocating the entire pushback buf for the item. each time
284 something like a macro is expanded, the stack index is changed. we
285 can then perform an exitm by popping all entries off the stack with
286 the same stack index. if we're being reasonable, we can detect
287 recusive expansion by checking the index is reasonably small.
292 include_file
, include_repeat
, include_while
, include_macro
297 sb pushback
; /* current pushback stream */
298 int pushback_index
; /* next char to read from stream */
299 FILE *handle
; /* open file */
300 sb name
; /* name of file */
301 int linecount
; /* number of lines read so far */
303 int index
; /* index of this layer */
305 include_stack
[MAX_INCLUDES
];
307 struct include_stack
*sp
;
308 #define isp (sp - include_stack)
313 void include_print_where_line ();
317 do { include_print_where_line (stderr); fprintf x ; fatals++; quit(); } while(0)
319 do { include_print_where_line (stderr); fprintf x; errors++; } while(0)
321 do { include_print_where_line (stderr); fprintf x; warnings++;} while(0)
325 /* exit the program and return the right ERROR code. */
338 for (i
= 0; i
< max_power_two
; i
++)
340 fprintf (stderr
, "strings size %8d : %d\n", 1<<i
, string_count
[i
]);
347 /* this program is about manipulating strings.
348 they are managed in things called `sb's which is an abbreviation
349 for string buffers. an sb has to be created, things can be glued
350 on to it, and at the end of it's life it should be freed. the
351 contents should never be pointed at whilst it is still growing,
352 since it could be moved at any time
356 sb_grow... (&foo,...);
362 /* initializes an sb. */
369 /* see if we can find one to allocate */
372 if (size
> max_power_two
)
374 FATAL ((stderr
, "string longer than %d bytes requested.\n",
375 1 << max_power_two
));
377 e
= free_list
.size
[size
];
380 /* nothing there, allocate one and stick into the free list */
381 e
= (sb_element
*) xmalloc (sizeof (sb_element
) + (1 << size
));
382 e
->next
= free_list
.size
[size
];
384 free_list
.size
[size
] = e
;
385 string_count
[size
]++;
388 /* remove from free list */
390 free_list
.size
[size
] = e
->next
;
392 /* copy into callers world */
404 sb_build (ptr
, dsize
);
407 /* deallocate the sb at ptr */
414 /* return item to free list */
415 ptr
->item
->next
= free_list
.size
[ptr
->pot
];
416 free_list
.size
[ptr
->pot
] = ptr
->item
;
419 /* add the sb at s to the end of the sb at ptr */
421 static void sb_check ();
429 sb_check (ptr
, s
->len
);
430 memcpy (ptr
->ptr
+ ptr
->len
, s
->ptr
, s
->len
);
434 /* make sure that the sb at ptr has room for another len characters,
435 and grow it if it doesn't. */
442 if (ptr
->len
+ len
>= 1 << ptr
->pot
)
446 while (ptr
->len
+ len
>= 1 << pot
)
448 sb_build (&tmp
, pot
);
449 sb_add_sb (&tmp
, ptr
);
455 /* make the sb at ptr point back to the beginning. */
464 /* add character c to the end of the sb at ptr. */
472 ptr
->ptr
[ptr
->len
++] = c
;
475 /* add null terminated string s to the end of sb at ptr. */
478 sb_add_string (ptr
, s
)
482 int len
= strlen (s
);
484 memcpy (ptr
->ptr
+ ptr
->len
, s
, len
);
488 /* add string at s of length len to sb at ptr */
491 sb_add_buffer (ptr
, s
, len
)
497 memcpy (ptr
->ptr
+ ptr
->len
, s
, len
);
502 /* print the sb at ptr to the output file */
512 for (i
= 0; i
< ptr
->len
; i
++)
516 fprintf (outfile
, ",");
518 fprintf (outfile
, "%d", ptr
->ptr
[i
]);
525 sb_print_at (idx
, ptr
)
530 for (i
= idx
; i
< ptr
->len
; i
++)
531 putc (ptr
->ptr
[i
], outfile
);
533 /* put a null at the end of the sb at in and return the start of the
534 string, so that it can be used as an arg to printf %s. */
541 /* stick a null on the end of the string */
546 /* start at the index idx into the string in sb at ptr and skip
547 whitespace. return the index of the first non whitespace character */
550 sb_skip_white (idx
, ptr
)
554 while (idx
< ptr
->len
&& ISWHITE (ptr
->ptr
[idx
]))
559 /* start at the index idx into the sb at ptr. skips whitespace,
560 a comma and any following whitespace. returnes the index of the
564 sb_skip_comma (idx
, ptr
)
568 while (idx
< ptr
->len
&& ISWHITE (ptr
->ptr
[idx
]))
572 && ptr
->ptr
[idx
] == ',')
575 while (idx
< ptr
->len
&& ISWHITE (ptr
->ptr
[idx
]))
582 /* hash table maintenance. */
584 /* build a new hash table with size buckets, and fill in the info at ptr. */
587 hash_new_table (size
, ptr
)
593 ptr
->table
= (hash_entry
**) xmalloc (size
* (sizeof (hash_entry
*)));
594 /* Fill with null-pointer, not zero-bit-pattern. */
595 for (i
= 0; i
< size
; i
++)
599 /* calculate and return the hash value of the sb at key. */
608 for (i
= 0; i
< key
->len
; i
++)
616 /* lookup key in hash_table tab, if present, then return it, otherwise
617 build a new one and fill it with hash_integer. */
621 hash_create (tab
, key
)
625 int k
= hash (key
) % tab
->size
;
627 hash_entry
**table
= tab
->table
;
635 hash_entry
*n
= (hash_entry
*) xmalloc (sizeof (hash_entry
));
638 sb_add_sb (&n
->key
, key
);
640 n
->type
= hash_integer
;
643 if (strncmp (table
[k
]->key
.ptr
, key
->ptr
, key
->len
) == 0)
651 /* add sb name with key into hash_table tab. if replacing old value
652 and again, then ERROR. */
656 hash_add_to_string_table (tab
, key
, name
, again
)
662 hash_entry
*ptr
= hash_create (tab
, key
);
663 if (ptr
->type
== hash_integer
)
665 sb_new (&ptr
->value
.s
);
667 if (ptr
->value
.s
.len
)
670 ERROR ((stderr
, "redefintion not allowed"));
673 ptr
->type
= hash_string
;
674 sb_reset (&ptr
->value
.s
);
676 sb_add_sb (&ptr
->value
.s
, name
);
679 /* add integer name to hash_table tab with sb key. */
683 hash_add_to_int_table (tab
, key
, name
)
688 hash_entry
*ptr
= hash_create (tab
, key
);
692 /* lookup sb key in hash_table tab. if found return hash_entry result,
697 hash_lookup (tab
, key
)
701 int k
= hash (key
) % tab
->size
;
702 hash_entry
**table
= tab
->table
;
703 hash_entry
*p
= table
[k
];
706 if (p
->key
.len
== key
->len
707 && strncmp (p
->key
.ptr
, key
->ptr
, key
->len
) == 0)
717 are handled in a really simple recursive decent way. each bit of
718 the machine takes an index into an sb and a pointer to an exp_t,
719 modifies the *exp_t and returns the index of the first character
720 past the part of the expression parsed.
722 expression precedence:
733 /* make sure that the exp_t at term is constant, if not the give the op ERROR. */
737 checkconst (op
, term
)
741 if (term
->add_symbol
.len
742 || term
->sub_symbol
.len
)
744 ERROR ((stderr
, "the %c operator cannot take non-absolute arguments.\n", op
));
748 /* turn the number in string at idx into a number of base,
749 fill in ptr and return the index of the first character not in the
754 sb_strtol (idx
, string
, base
, ptr
)
761 idx
= sb_skip_white (idx
, string
);
763 while (idx
< string
->len
)
765 int ch
= string
->ptr
[idx
];
769 else if (ch
>= 'a' && ch
<= 'f')
771 else if (ch
>= 'A' && ch
<= 'F')
779 value
= value
* base
+ dig
;
786 static int level_5 ();
789 level_0 (idx
, string
, lhs
)
794 lhs
->add_symbol
.len
= 0;
795 lhs
->add_symbol
.name
= 0;
797 lhs
->sub_symbol
.len
= 0;
798 lhs
->sub_symbol
.name
= 0;
800 idx
= sb_skip_white (idx
, string
);
804 if (isdigit (string
->ptr
[idx
]))
806 idx
= sb_strtol (idx
, string
, 10, &lhs
->value
);
808 else if (ISFIRSTCHAR (string
->ptr
[idx
]))
811 lhs
->add_symbol
.name
= string
->ptr
+ idx
;
812 while (idx
< string
->len
&& ISNEXTCHAR (string
->ptr
[idx
]))
817 lhs
->add_symbol
.len
= len
;
819 else if (string
->ptr
[idx
] == '"')
823 ERROR ((stderr
, "string where expression expected.\n"));
824 idx
= getstring (idx
, string
, &acc
);
829 ERROR ((stderr
, "can't find primary in expression.\n"));
832 return sb_skip_white (idx
, string
);
838 level_1 (idx
, string
, lhs
)
843 idx
= sb_skip_white (idx
, string
);
845 switch (string
->ptr
[idx
])
848 idx
= level_1 (idx
+ 1, string
, lhs
);
851 idx
= level_1 (idx
+ 1, string
, lhs
);
852 checkconst ('~', lhs
);
853 lhs
->value
= ~lhs
->value
;
858 idx
= level_1 (idx
+ 1, string
, lhs
);
859 lhs
->value
= -lhs
->value
;
861 lhs
->add_symbol
= lhs
->sub_symbol
;
867 idx
= level_5 (sb_skip_white (idx
, string
), string
, lhs
);
868 if (string
->ptr
[idx
] != ')')
869 ERROR ((stderr
, "misplaced closing parens.\n"));
874 idx
= level_0 (idx
, string
, lhs
);
877 return sb_skip_white (idx
, string
);
881 level_2 (idx
, string
, lhs
)
888 idx
= level_1 (idx
, string
, lhs
);
890 while (idx
< string
->len
&& (string
->ptr
[idx
] == '*'
891 || string
->ptr
[idx
] == '/'))
893 char op
= string
->ptr
[idx
++];
894 idx
= level_1 (idx
, string
, &rhs
);
898 checkconst ('*', lhs
);
899 checkconst ('*', &rhs
);
900 lhs
->value
*= rhs
.value
;
903 checkconst ('/', lhs
);
904 checkconst ('/', &rhs
);
906 ERROR ((stderr
, "attempt to divide by zero.\n"));
908 lhs
->value
/= rhs
.value
;
912 return sb_skip_white (idx
, string
);
917 level_3 (idx
, string
, lhs
)
924 idx
= level_2 (idx
, string
, lhs
);
926 while (idx
< string
->len
927 && (string
->ptr
[idx
] == '+'
928 || string
->ptr
[idx
] == '-'))
930 char op
= string
->ptr
[idx
++];
931 idx
= level_2 (idx
, string
, &rhs
);
935 lhs
->value
+= rhs
.value
;
936 if (lhs
->add_symbol
.name
&& rhs
.add_symbol
.name
)
938 ERROR ((stderr
, "can't add two relocatable expressions\n"));
940 /* change nn+symbol to symbol + nn */
941 if (rhs
.add_symbol
.name
)
943 lhs
->add_symbol
= rhs
.add_symbol
;
947 lhs
->value
-= rhs
.value
;
948 lhs
->sub_symbol
= rhs
.add_symbol
;
952 return sb_skip_white (idx
, string
);
956 level_4 (idx
, string
, lhs
)
963 idx
= level_3 (idx
, string
, lhs
);
965 while (idx
< string
->len
&&
966 string
->ptr
[idx
] == '&')
968 char op
= string
->ptr
[idx
++];
969 idx
= level_3 (idx
, string
, &rhs
);
973 checkconst ('&', lhs
);
974 checkconst ('&', &rhs
);
975 lhs
->value
&= rhs
.value
;
979 return sb_skip_white (idx
, string
);
983 level_5 (idx
, string
, lhs
)
990 idx
= level_4 (idx
, string
, lhs
);
992 while (idx
< string
->len
993 && (string
->ptr
[idx
] == '|' || string
->ptr
[idx
] == '~'))
995 char op
= string
->ptr
[idx
++];
996 idx
= level_4 (idx
, string
, &rhs
);
1000 checkconst ('|', lhs
);
1001 checkconst ('|', &rhs
);
1002 lhs
->value
|= rhs
.value
;
1005 checkconst ('~', lhs
);
1006 checkconst ('~', &rhs
);
1007 lhs
->value
^= rhs
.value
;
1011 return sb_skip_white (idx
, string
);
1015 /* parse the expression at offset idx into string, fill up res with
1016 the result. return the index of the first char past the expression.
1020 exp_parse (idx
, string
, res
)
1025 return level_5 (sb_skip_white (idx
, string
), string
, res
);
1029 /* turn the expression at exp into text and glue it onto the end of
1033 exp_string (exp
, string
)
1041 if (exp
->add_symbol
.len
)
1043 sb_add_buffer (string
, exp
->add_symbol
.name
, exp
->add_symbol
.len
);
1051 sb_add_char (string
, '+');
1052 sprintf (buf
, "%d", exp
->value
);
1053 sb_add_string (string
, buf
);
1057 if (exp
->sub_symbol
.len
)
1059 sb_add_char (string
, '-');
1060 sb_add_buffer (string
, exp
->add_symbol
.name
, exp
->add_symbol
.len
);
1066 sb_add_char (string
, '0');
1070 /* parse the expression at offset idx into sb in, return the value in val.
1071 if the expression is not constant, give ERROR emsg. returns the index
1072 of the first character past the end of the expression. */
1075 exp_get_abs (emsg
, idx
, in
, val
)
1082 idx
= exp_parse (idx
, in
, &res
);
1083 if (res
.add_symbol
.len
|| res
.sub_symbol
.len
)
1084 ERROR ((stderr
, emsg
));
1090 sb label
; /* current label parsed from line */
1091 hash_table assign_hash_table
; /* hash table for all assigned variables */
1092 hash_table keyword_hash_table
; /* hash table for keyword */
1093 hash_table vars
; /* hash table for eq variables */
1095 #define in_comment ';'
1099 strip_comments (out
)
1104 for (i
= 0; i
< out
->len
; i
++)
1106 if (ISCOMMENTCHAR(s
[i
]))
1115 /* push back character ch so that it can be read again. */
1125 if (sp
->pushback_index
)
1126 sp
->pushback_index
--;
1128 sb_add_char (&sp
->pushback
, ch
);
1131 /* push the sb ptr onto the include stack, with the given name, type and index. */
1135 include_buf (name
, ptr
, type
, index
)
1142 if (sp
- include_stack
>= MAX_INCLUDES
)
1143 FATAL ((stderr
, "unreasonable nesting.\n"));
1145 sb_add_sb (&sp
->name
, name
);
1148 sp
->pushback_index
= 0;
1151 sb_new (&sp
->pushback
);
1152 sb_add_sb (&sp
->pushback
, ptr
);
1156 /* used in ERROR messages, print info on where the include stack is onto file. */
1159 include_print_where_line (file
)
1162 struct include_stack
*p
= include_stack
+ 1;
1166 fprintf (file
, "%s:%d ", sb_name (&p
->name
), p
->linecount
- ((p
== sp
) ? 1 : 0));
1171 /* used in listings, print the line number onto file. */
1173 include_print_line (file
)
1177 struct include_stack
*p
= include_stack
+ 1;
1179 n
= fprintf (file
, "%4d", p
->linecount
);
1183 n
+= fprintf (file
, ".%d", p
->linecount
);
1188 fprintf (file
, " ");
1194 /* read a line from the top of the include stack into sb in. */
1205 putc (comment_char
, outfile
);
1206 if (print_line_number
)
1207 include_print_line (outfile
);
1221 WARNING ((stderr
, "End of file not at start of line.\n"));
1223 putc ('\n', outfile
);
1242 /* continued line */
1245 putc (comment_char
, outfile
);
1246 putc ('+', outfile
);
1259 sb_add_char (in
, ch
);
1267 /* find a label from sb in and put it in out. */
1270 grab_label (in
, out
)
1276 if (ISFIRSTCHAR (in
->ptr
[i
]))
1278 sb_add_char (out
, in
->ptr
[i
]);
1280 while ((ISNEXTCHAR (in
->ptr
[i
])
1281 || in
->ptr
[i
] == '\\'
1282 || in
->ptr
[i
] == '&')
1285 sb_add_char (out
, in
->ptr
[i
]);
1292 /* find all strange base stuff and turn into decimal. also
1293 find all the other numbers and convert them from the default radix */
1296 change_base (idx
, in
, out
)
1303 while (idx
< in
->len
)
1305 if (idx
< in
->len
- 1 && in
->ptr
[idx
+ 1] == '\'')
1309 switch (in
->ptr
[idx
])
1328 ERROR ((stderr
, "Illegal base character %c.\n", in
->ptr
[idx
]));
1333 idx
= sb_strtol (idx
+ 2, in
, base
, &value
);
1334 sprintf (buffer
, "%d", value
);
1335 sb_add_string (out
, buffer
);
1337 else if (ISFIRSTCHAR (in
->ptr
[idx
]))
1339 /* copy entire names through quickly */
1340 sb_add_char (out
, in
->ptr
[idx
]);
1342 while (idx
< in
->len
&& ISNEXTCHAR (in
->ptr
[idx
]))
1344 sb_add_char (out
, in
->ptr
[idx
]);
1348 else if (isdigit (in
->ptr
[idx
]))
1351 /* all numbers must start with a digit, let's chew it and
1353 idx
= sb_strtol (idx
, in
, radix
, &value
);
1354 sprintf (buffer
, "%d", value
);
1355 sb_add_string (out
, buffer
);
1357 /* skip all undigsested letters */
1358 while (idx
< in
->len
&& ISNEXTCHAR (in
->ptr
[idx
]))
1360 sb_add_char (out
, in
->ptr
[idx
]);
1366 /* nothing special, just pass it through */
1367 sb_add_char (out
, in
->ptr
[idx
]);
1384 do_assign (again
, idx
, in
)
1389 /* stick label in symbol table with following value */
1394 idx
= exp_parse (idx
, in
, &e
);
1395 exp_string (&e
, &acc
);
1396 hash_add_to_string_table (&assign_hash_table
, &label
, &acc
, again
);
1401 /* .radix [b|q|d|h] */
1408 int idx
= sb_skip_white (0, ptr
);
1409 switch (ptr
->ptr
[idx
])
1428 ERROR ((stderr
, "radix is %c must be one of b, q, d or h", radix
));
1433 /* Parse off a .b, .w or .l */
1436 get_opsize (idx
, in
, size
)
1442 if (in
->ptr
[idx
] == '.')
1446 switch (in
->ptr
[idx
])
1464 ERROR ((stderr
, "size must be one of b, w or l, is %c.\n", in
->ptr
[idx
]));
1477 idx
= sb_skip_white (idx
, line
);
1479 && ISCOMMENTCHAR(line
->ptr
[idx
]))
1481 if (idx
>= line
->len
)
1486 /* .data [.b|.w|.l] <data>*
1487 or d[bwl] <data>* */
1490 do_data (idx
, in
, size
)
1502 idx
= get_opsize (idx
, in
, &opsize
);
1521 fprintf (outfile
, "%s\t", opname
);
1523 idx
= sb_skip_white (idx
, in
);
1527 && in
->ptr
[idx
] == '"')
1530 idx
= getstring (idx
, in
, &acc
);
1531 for (i
= 0; i
< acc
.len
; i
++)
1534 fprintf(outfile
,",");
1535 fprintf (outfile
, "%d", acc
.ptr
[i
]);
1540 while (!eol (idx
, in
))
1543 idx
= exp_parse (idx
, in
, &e
);
1544 exp_string (&e
, &acc
);
1545 sb_add_char (&acc
, 0);
1546 fprintf (outfile
, acc
.ptr
);
1547 if (idx
< in
->len
&& in
->ptr
[idx
] == ',')
1549 fprintf (outfile
, ",");
1555 sb_print_at (idx
, in
);
1556 fprintf (outfile
, "\n");
1559 /* .datab [.b|.w|.l] <repeat>,<fill> */
1570 idx
= get_opsize (idx
, in
, &opsize
);
1572 idx
= exp_get_abs ("datab repeat must be constant.\n", idx
, in
, &repeat
);
1573 idx
= sb_skip_comma (idx
, in
);
1574 idx
= exp_get_abs ("datab data must be absolute.\n", idx
, in
, &fill
);
1576 fprintf (outfile
, ".fill\t%d,%d,%d\n", repeat
, opsize
, fill
);
1587 idx
= exp_get_abs ("align needs absolute expression.\n", idx
, in
, &al
);
1592 WARNING ((stderr
, "alignment must be one of 1, 2 or 4.\n"));
1594 fprintf (outfile
, ".align %d\n", al
);
1597 /* .res[.b|.w|.l] <size> */
1600 do_res (idx
, in
, type
)
1608 idx
= get_opsize (idx
, in
, &size
);
1609 while (!eol(idx
, in
))
1611 idx
= sb_skip_white (idx
, in
);
1612 if (in
->ptr
[idx
] == ',')
1614 idx
= exp_get_abs ("res needs absolute expression for fill count.\n", idx
, in
, &count
);
1616 if (type
== 'c' || type
== 'z')
1619 fprintf (outfile
, ".space %d\n", count
* size
);
1630 fprintf (outfile
, ".global %s\n", sb_name (in
));
1633 /* .print [list] [nolist] */
1640 idx
= sb_skip_white (idx
, in
);
1641 while (idx
< in
->len
)
1643 if (strncmp (in
->ptr
+ idx
, "LIST", 4) == 0)
1645 fprintf (outfile
, ".list\n");
1648 else if (strncmp (in
->ptr
+ idx
, "NOLIST", 6) == 0)
1650 fprintf (outfile
, ".nolist\n");
1659 do_heading (idx
, in
)
1665 idx
= getstring (idx
, in
, &head
);
1666 fprintf (outfile
, ".title \"%s\"\n", sb_name (&head
));
1675 fprintf (outfile
, ".eject\n");
1678 /* .form [lin=<value>] [col=<value>] */
1686 idx
= sb_skip_white (idx
, in
);
1688 while (idx
< in
->len
)
1691 if (strncmp (in
->ptr
+ idx
, "LIN=", 4) == 0)
1694 idx
= exp_get_abs ("form LIN= needs absolute expresssion.\n", idx
, in
, &lines
);
1697 if (strncmp (in
->ptr
+ idx
, "COL=", 4) == 0)
1700 idx
= exp_get_abs ("form COL= needs absolute expresssion.\n", idx
, in
, &columns
);
1705 fprintf (outfile
, ".psize %d,%d\n", lines
, columns
);
1710 /* Fetch string from the input stream,
1712 'Bxyx<whitespace> -> return 'Bxyza
1713 %<char> -> return string of decimal value of x
1714 "<string>" -> return string
1715 xyx<whitespace> -> return xyz
1718 get_any_string (idx
, in
, out
, expand
, pretend_quoted
)
1726 idx
= sb_skip_white (idx
, in
);
1730 if (in
->len
> 2 && in
->ptr
[idx
+1] == '\'' && ISBASE (in
->ptr
[idx
]))
1732 while (!ISSEP (in
->ptr
[idx
]))
1733 sb_add_char (out
, in
->ptr
[idx
++]);
1735 else if (in
->ptr
[idx
] == '%'
1741 /* Turns the next expression into a string */
1742 idx
= exp_get_abs ("% operator needs absolute expression",
1746 sprintf(buf
, "%d", val
);
1747 sb_add_string (out
, buf
);
1749 else if (in
->ptr
[idx
] == '"'
1750 || in
->ptr
[idx
] == '<'
1751 || (alternate
&& in
->ptr
[idx
] == '\''))
1753 if (alternate
&& expand
)
1755 /* Keep the quotes */
1756 sb_add_char (out
, '\"');
1758 idx
= getstring (idx
, in
, out
);
1759 sb_add_char (out
, '\"');
1763 idx
= getstring (idx
, in
, out
);
1768 while (idx
< in
->len
1769 && (in
->ptr
[idx
] == '"'
1770 || in
->ptr
[idx
] == '\''
1772 || !ISSEP (in
->ptr
[idx
])))
1774 if (in
->ptr
[idx
] == '"'
1775 || in
->ptr
[idx
] == '\'')
1777 char tchar
= in
->ptr
[idx
];
1778 sb_add_char (out
, in
->ptr
[idx
++]);
1779 while (idx
< in
->len
1780 && in
->ptr
[idx
] != tchar
)
1781 sb_add_char (out
, in
->ptr
[idx
++]);
1785 sb_add_char (out
, in
->ptr
[idx
++]);
1794 /* skip along sb in starting at idx, suck off whitespace a ( and more
1795 whitespace. return the idx of the next char */
1798 skip_openp (idx
, in
)
1802 idx
= sb_skip_white (idx
, in
);
1803 if (in
->ptr
[idx
] != '(')
1804 ERROR ((stderr
, "misplaced ( .\n"));
1805 idx
= sb_skip_white (idx
+ 1, in
);
1809 /* skip along sb in starting at idx, suck off whitespace a ) and more
1810 whitespace. return the idx of the next char */
1813 skip_closep (idx
, in
)
1817 idx
= sb_skip_white (idx
, in
);
1818 if (in
->ptr
[idx
] != ')')
1819 ERROR ((stderr
, "misplaced ).\n"));
1820 idx
= sb_skip_white (idx
+ 1, in
);
1827 dolen (idx
, in
, out
)
1836 sb_new (&stringout
);
1837 idx
= skip_openp (idx
, in
);
1838 idx
= get_and_process (idx
, in
, &stringout
);
1839 idx
= skip_closep (idx
, in
);
1840 sprintf (buffer
, "%d", stringout
.len
);
1841 sb_add_string (out
, buffer
);
1843 sb_kill (&stringout
);
1852 doinstr (idx
, in
, out
)
1866 idx
= skip_openp (idx
, in
);
1867 idx
= get_and_process (idx
, in
, &string
);
1868 idx
= sb_skip_comma (idx
, in
);
1869 idx
= get_and_process (idx
, in
, &search
);
1870 idx
= sb_skip_comma (idx
, in
);
1871 if (isdigit (in
->ptr
[idx
]))
1873 idx
= exp_get_abs (".instr needs absolute expresson.\n", idx
, in
, &start
);
1879 idx
= skip_closep (idx
, in
);
1881 for (i
= start
; i
< string
.len
; i
++)
1883 if (strncmp (string
.ptr
+ i
, search
.ptr
, search
.len
) == 0)
1889 sprintf (buffer
, "%d", res
);
1890 sb_add_string (out
, buffer
);
1898 dosubstr (idx
, in
, out
)
1908 idx
= skip_openp (idx
, in
);
1909 idx
= get_and_process (idx
, in
, &string
);
1910 idx
= sb_skip_comma (idx
, in
);
1911 idx
= exp_get_abs ("need absolute position.\n", idx
, in
, &pos
);
1912 idx
= sb_skip_comma (idx
, in
);
1913 idx
= exp_get_abs ("need absolute length.\n", idx
, in
, &len
);
1914 idx
= skip_closep (idx
, in
);
1917 if (len
< 0 || pos
< 0 ||
1919 || pos
+ len
> string
.len
)
1921 sb_add_string (out
, " ");
1925 sb_add_char (out
, '"');
1928 sb_add_char (out
, string
.ptr
[pos
++]);
1931 sb_add_char (out
, '"');
1937 /* scan line, change tokens in the hash table to their replacements */
1939 process_assigns (idx
, in
, buf
)
1944 while (idx
< in
->len
)
1947 if (in
->ptr
[idx
] == '\\'
1948 && in
->ptr
[idx
+ 1] == '&')
1950 idx
= condass_lookup_name (in
, idx
+ 2, buf
, 1);
1952 else if (in
->ptr
[idx
] == '\\'
1953 && in
->ptr
[idx
+ 1] == '$')
1955 idx
= condass_lookup_name (in
, idx
+ 2, buf
, 0);
1957 else if (idx
+ 3 < in
->len
1958 && in
->ptr
[idx
] == '.'
1959 && in
->ptr
[idx
+ 1] == 'L'
1960 && in
->ptr
[idx
+ 2] == 'E'
1961 && in
->ptr
[idx
+ 3] == 'N')
1962 idx
= dolen (idx
+ 4, in
, buf
);
1963 else if (idx
+ 6 < in
->len
1964 && in
->ptr
[idx
] == '.'
1965 && in
->ptr
[idx
+ 1] == 'I'
1966 && in
->ptr
[idx
+ 2] == 'N'
1967 && in
->ptr
[idx
+ 3] == 'S'
1968 && in
->ptr
[idx
+ 4] == 'T'
1969 && in
->ptr
[idx
+ 5] == 'R')
1970 idx
= doinstr (idx
+ 6, in
, buf
);
1971 else if (idx
+ 7 < in
->len
1972 && in
->ptr
[idx
] == '.'
1973 && in
->ptr
[idx
+ 1] == 'S'
1974 && in
->ptr
[idx
+ 2] == 'U'
1975 && in
->ptr
[idx
+ 3] == 'B'
1976 && in
->ptr
[idx
+ 4] == 'S'
1977 && in
->ptr
[idx
+ 5] == 'T'
1978 && in
->ptr
[idx
+ 6] == 'R')
1979 idx
= dosubstr (idx
+ 7, in
, buf
);
1980 else if (ISFIRSTCHAR (in
->ptr
[idx
]))
1982 /* may be a simple name subsitution, see if we have a word */
1985 while (cur
< in
->len
1986 && (ISNEXTCHAR (in
->ptr
[cur
])))
1990 sb_add_buffer (&acc
, in
->ptr
+ idx
, cur
- idx
);
1991 ptr
= hash_lookup (&assign_hash_table
, &acc
);
1994 /* Found a definition for it */
1995 sb_add_sb (buf
, &ptr
->value
.s
);
1999 /* No definition, just copy the word */
2000 sb_add_sb (buf
, &acc
);
2007 sb_add_char (buf
, in
->ptr
[idx
++]);
2013 get_and_process (idx
, in
, out
)
2020 idx
= get_any_string (idx
, in
, &t
, 1, 0);
2021 process_assigns (0, &t
, out
);
2042 more
= get_line (&line
);
2045 /* Find any label and pseudo op that we're intested in */
2050 fprintf (outfile
, "\n");
2054 l
= grab_label (&line
, &label_in
);
2058 /* Munge any label */
2061 process_assigns (0, &label_in
, &label
);
2064 if (line
.ptr
[l
] == ':')
2066 while (ISWHITE (line
.ptr
[l
]) && l
< line
.len
)
2071 if (process_pseudo_op (l
, &line
, &acc
))
2077 else if (condass_on ())
2079 if (macro_op (l
, &line
))
2089 fprintf (outfile
, "%s:\t", sb_name (&label
));
2092 fprintf (outfile
, "\t");
2094 process_assigns (l
, &line
, &t1
);
2096 change_base (0, &t1
, &t2
);
2097 fprintf (outfile
, "%s\n", sb_name (&t2
));
2103 /* Only a label on this line */
2104 if (label
.len
&& condass_on())
2106 fprintf (outfile
, "%s:\n", sb_name (&label
));
2114 more
= get_line (&line
);
2118 WARNING ((stderr
, "END missing from end of file.\n"));
2126 free_old_entry (ptr
)
2131 if (ptr
->type
== hash_string
)
2132 sb_kill(&ptr
->value
.s
);
2136 /* name: .ASSIGNA <value> */
2139 do_assigna (idx
, in
)
2147 process_assigns (idx
, in
, &tmp
);
2148 idx
= exp_get_abs (".ASSIGNA needs constant expression argument.\n", 0, &tmp
, &val
);
2152 ERROR ((stderr
, ".ASSIGNA without label.\n"));
2156 hash_entry
*ptr
= hash_create (&vars
, &label
);
2157 free_old_entry (ptr
);
2158 ptr
->type
= hash_integer
;
2164 /* name: .ASSIGNC <string> */
2167 do_assignc (idx
, in
)
2173 idx
= getstring (idx
, in
, &acc
);
2177 ERROR ((stderr
, ".ASSIGNS without label.\n"));
2181 hash_entry
*ptr
= hash_create (&vars
, &label
);
2182 free_old_entry (ptr
);
2183 ptr
->type
= hash_string
;
2184 sb_new (&ptr
->value
.s
);
2185 sb_add_sb (&ptr
->value
.s
, &acc
);
2191 /* name: .REG (reg) */
2198 /* remove reg stuff from inside parens */
2200 idx
= skip_openp (idx
, in
);
2202 while (idx
< in
->len
&& in
->ptr
[idx
] != ')')
2204 sb_add_char (&what
, in
->ptr
[idx
]);
2207 hash_add_to_string_table (&assign_hash_table
, &label
, &what
, 1);
2213 condass_lookup_name (inbuf
, idx
, out
, warn
)
2221 sb_new (&condass_acc
);
2223 while (idx
< inbuf
->len
2224 && ISNEXTCHAR (inbuf
->ptr
[idx
]))
2226 sb_add_char (&condass_acc
, inbuf
->ptr
[idx
++]);
2229 if (inbuf
->ptr
[idx
] == '\'')
2231 ptr
= hash_lookup (&vars
, &condass_acc
);
2238 WARNING ((stderr
, "Can't find preprocessor variable %s.\n", sb_name (&condass_acc
)));
2242 sb_add_string (out
, "0");
2247 if (ptr
->type
== hash_integer
)
2250 sprintf (buffer
, "%d", ptr
->value
.i
);
2251 sb_add_string (out
, buffer
);
2255 sb_add_sb (out
, &ptr
->value
.s
);
2258 sb_kill (&condass_acc
);
2271 whatcond (idx
, in
, val
)
2278 idx
= sb_skip_white (idx
, in
);
2280 if (p
[0] == 'E' && p
[1] == 'Q')
2282 else if (p
[0] == 'N' && p
[1] == 'E')
2284 else if (p
[0] == 'L' && p
[1] == 'T')
2286 else if (p
[0] == 'L' && p
[1] == 'E')
2288 else if (p
[0] == 'G' && p
[1] == 'T')
2290 else if (p
[0] == 'G' && p
[1] == 'E')
2294 ERROR ((stderr
, "Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n"));
2297 idx
= sb_skip_white (idx
+ 2, in
);
2314 idx
= sb_skip_white (idx
, in
);
2316 if (in
->ptr
[idx
] == '"')
2320 /* This is a string comparision */
2321 idx
= getstring (idx
, in
, &acc_a
);
2322 idx
= whatcond (idx
, in
, &cond
);
2323 idx
= getstring (idx
, in
, &acc_b
);
2324 same
= acc_a
.len
== acc_b
.len
&& (strncmp (acc_a
.ptr
, acc_b
.ptr
, acc_a
.len
) == 0);
2326 if (cond
!= EQ
&& cond
!= NE
)
2328 ERROR ((stderr
, "Comparison operator for strings must be EQ or NE\n"));
2332 res
= cond
== EQ
&& same
;
2335 /* This is a numeric expression */
2340 idx
= exp_get_abs ("Conditional operator must have absolute operands.\n", idx
, in
, &vala
);
2341 idx
= whatcond (idx
, in
, &cond
);
2342 idx
= sb_skip_white (idx
, in
);
2343 if (in
->ptr
[idx
] == '"')
2345 WARNING ((stderr
, "String compared against expression.\n"));
2350 idx
= exp_get_abs ("Conditional operator must have absolute operands.\n", idx
, in
, &valb
);
2390 if (ifi
>= IFNESTING
)
2392 FATAL ((stderr
, "AIF nesting unreasonable.\n"));
2395 ifstack
[ifi
].on
= ifstack
[ifi
-1].on
? istrue (idx
, in
) : 0;
2396 ifstack
[ifi
].hadelse
= 0;
2404 ifstack
[ifi
].on
= ifstack
[ifi
-1].on
? !ifstack
[ifi
].on
: 0;
2405 if (ifstack
[ifi
].hadelse
)
2407 ERROR ((stderr
, "Multiple AELSEs in AIF.\n"));
2409 ifstack
[ifi
].hadelse
= 1;
2423 ERROR ((stderr
, "AENDI without AIF.\n"));
2430 return ifstack
[ifi
].on
;
2434 /* Read input lines till we get to a TO string.
2435 Increase nesting depth if we geta FROM string.
2436 Put the results into sb at PTR. */
2439 buffer_and_nest (from
, to
, ptr
)
2444 int from_len
= strlen (from
);
2445 int to_len
= strlen (to
);
2447 int line_start
= ptr
->len
;
2448 int line
= linecount ();
2450 int more
= get_line (ptr
);
2454 /* Try and find the first pseudo op on the line */
2459 /* With normal syntax we can suck what we want till we get to the dot.
2460 With the alternate, labels have to start in the first column, since
2461 we cant tell what's a label and whats a pseudoop */
2463 /* Skip leading whitespace */
2465 && ISWHITE (ptr
->ptr
[i
]))
2468 /* Skip over a label */
2470 && ISNEXTCHAR (ptr
->ptr
[i
]))
2475 && ptr
->ptr
[i
] == ':')
2479 /* Skip trailing whitespace */
2481 && ISWHITE (ptr
->ptr
[i
]))
2484 if (i
< ptr
->len
&& (ptr
->ptr
[i
] == '.'
2487 if (ptr
->ptr
[i
] == '.')
2489 if (strncmp (ptr
->ptr
+ i
, from
, from_len
) == 0)
2491 if (strncmp (ptr
->ptr
+ i
, to
, to_len
) == 0)
2496 /* Reset the string to not include the ending rune */
2497 ptr
->len
= line_start
;
2503 /* Add a CR to the end and keep running */
2504 sb_add_char (ptr
, '\n');
2505 line_start
= ptr
->len
;
2506 more
= get_line (ptr
);
2511 FATAL ((stderr
, "End of file whilst inside %s, started on line %d.\n", from
, line
));
2519 ERROR ((stderr
, "AENDR without a AREPEAT.\n"));
2538 process_assigns (idx
, in
, &exp
);
2539 doit
= istrue (0, &exp
);
2541 buffer_and_nest ("AWHILE", "AENDW", &sub
);
2556 int index
= include_next_index ();
2560 sb_add_sb (©
, &sub
);
2561 sb_add_sb (©
, in
);
2562 sb_add_string (©
, "\n");
2563 sb_add_sb (©
, &sub
);
2564 sb_add_string (©
, "\t.AENDW\n");
2565 /* Push another WHILE */
2566 include_buf (&exp
, ©
, include_while
, index
);
2579 ERROR ((stderr
, "AENDW without a AENDW.\n"));
2585 Pop things off the include stack until the type and index changes */
2590 include_type type
= sp
->type
;
2591 if (type
== include_repeat
2592 || type
== include_while
2593 || type
== include_macro
)
2595 int index
= sp
->index
;
2597 while (sp
->index
== index
2598 && sp
->type
== type
)
2608 do_arepeat (idx
, in
)
2612 sb exp
; /* buffer with expression in it */
2613 sb copy
; /* expanded repeat block */
2614 sb sub
; /* contents of AREPEAT */
2620 process_assigns (idx
, in
, &exp
);
2621 idx
= exp_get_abs ("AREPEAT must have absolute operand.\n", 0, &exp
, &rc
);
2622 buffer_and_nest ("AREPEAT", "AENDR", &sub
);
2625 /* Push back the text following the repeat, and another repeat block
2636 int index
= include_next_index ();
2637 sb_add_sb (©
, &sub
);
2640 sprintf (buffer
, "\t.AREPEAT %d\n", rc
- 1);
2641 sb_add_string (©
, buffer
);
2642 sb_add_sb (©
, &sub
);
2643 sb_add_string (©
, " .AENDR\n");
2646 include_buf (&exp
, ©
, include_repeat
, index
);
2658 ERROR ((stderr
, ".ENDM without a matching .MACRO.\n"));
2662 /* MARRO PROCESSING */
2665 hash_table macro_table
;
2675 do_formals (macro
, idx
, in
)
2680 formal_entry
**p
= ¯o
->formals
;
2681 macro
->formal_count
= 0;
2682 hash_new_table (5, ¯o
->formal_hash
);
2683 while (idx
< in
->len
)
2685 formal_entry
*formal
;
2687 formal
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
2689 sb_new (&formal
->name
);
2690 sb_new (&formal
->def
);
2691 sb_new (&formal
->actual
);
2693 idx
= sb_skip_white (idx
, in
);
2694 idx
= get_token (idx
, in
, &formal
->name
);
2695 if (formal
->name
.len
== 0)
2697 idx
= sb_skip_white (idx
, in
);
2698 if (formal
->name
.len
)
2700 /* This is a formal */
2701 if (idx
< in
->len
&& in
->ptr
[idx
] == '=')
2704 idx
= get_any_string (idx
+ 1, in
, &formal
->def
, 1, 0);
2709 /* Add to macro's hash table */
2711 hash_entry
*p
= hash_create (¯o
->formal_hash
, &formal
->name
);
2712 p
->type
= hash_formal
;
2713 p
->value
.f
= formal
;
2716 formal
->index
= macro
->formal_count
;
2717 idx
= sb_skip_comma (idx
, in
);
2718 macro
->formal_count
++;
2725 /* Parse off LOCAL n1, n2,... Invent a label name for it */
2728 do_local (idx
, line
)
2738 idx
= sb_skip_white (idx
, line
);
2739 while (!eol(idx
, line
))
2744 sprintf(subs
, "LL%04x", ln
);
2745 idx
= get_token(idx
, line
, &acc
);
2746 sb_add_string (&sub
, subs
);
2747 hash_add_to_string_table (&assign_hash_table
, &acc
, &sub
, 1);
2748 idx
= sb_skip_comma (idx
, line
);
2763 macro
= (macro_entry
*) xmalloc (sizeof (macro_entry
));
2764 sb_new (¯o
->sub
);
2767 macro
->formal_count
= 0;
2770 idx
= sb_skip_white (idx
, in
);
2771 buffer_and_nest ("MACRO", "ENDM", ¯o
->sub
);
2775 sb_add_sb (&name
, &label
);
2776 if (in
->ptr
[idx
] == '(')
2778 /* It's the label: MACRO (formals,...) sort */
2779 idx
= do_formals (macro
, idx
+ 1, in
);
2780 if (in
->ptr
[idx
] != ')')
2781 ERROR ((stderr
, "Missing ) after formals.\n"));
2784 /* It's the label: MACRO formals,... sort */
2785 idx
= do_formals (macro
, idx
, in
);
2790 idx
= get_token (idx
, in
, &name
);
2791 idx
= sb_skip_white (idx
, in
);
2792 idx
= do_formals (macro
, idx
, in
);
2795 /* and stick it in the macro hash table */
2796 hash_create (¯o_table
, &name
)->value
.m
= macro
;
2801 get_token (idx
, in
, name
)
2807 && ISFIRSTCHAR (in
->ptr
[idx
]))
2809 sb_add_char (name
, in
->ptr
[idx
++]);
2810 while (idx
< in
->len
2811 && ISNEXTCHAR (in
->ptr
[idx
]))
2813 sb_add_char (name
, in
->ptr
[idx
++]);
2816 /* Ignore trailing & */
2817 if (alternate
&& idx
< in
->len
&& in
->ptr
[idx
] == '&')
2822 /* Scan a token, but stop if a ' is seen */
2824 get_apost_token (idx
, in
, name
, kind
)
2830 idx
= get_token (idx
, in
, name
);
2831 if (idx
< in
->len
&& in
->ptr
[idx
] == kind
)
2837 sub_actual (src
, in
, t
, m
, kind
, out
, copyifnotthere
)
2846 /* This is something to take care of */
2848 src
= get_apost_token (src
, in
, t
, kind
);
2849 /* See if it's in the macro's hash table */
2850 ptr
= hash_lookup (&m
->formal_hash
, t
);
2853 if (ptr
->value
.f
->actual
.len
)
2855 sb_add_sb (out
, &ptr
->value
.f
->actual
);
2859 sb_add_sb (out
, &ptr
->value
.f
->def
);
2862 else if (copyifnotthere
)
2868 sb_add_char (out
, '\\');
2876 macro_expand (name
, idx
, in
, m
)
2886 int is_positional
= 0;
2892 /* Reset any old value the actuals may have */
2893 for (f
= m
->formals
; f
; f
= f
->next
)
2894 sb_reset (&f
->actual
);
2896 /* Peel off the actuals and store them away in the hash tables' actuals */
2897 while (!eol(idx
, in
))
2900 idx
= sb_skip_white (idx
, in
);
2901 /* Look and see if it's a positional or keyword arg */
2903 while (scan
< in
->len
2904 && !ISSEP (in
->ptr
[scan
])
2905 && (!alternate
&& in
->ptr
[scan
] != '='))
2907 if (scan
< in
->len
&& (!alternate
) && in
->ptr
[scan
] == '=')
2912 ERROR ((stderr
, "Can't mix positional and keyword arguments.\n"));
2915 /* This is a keyword arg, fetch the formal name and
2916 then the actual stuff */
2918 idx
= get_token (idx
, in
, &t
);
2919 if (in
->ptr
[idx
] != '=')
2920 ERROR ((stderr
, "confused about formal params.\n"));
2922 /* Lookup the formal in the macro's list */
2923 ptr
= hash_lookup (&m
->formal_hash
, &t
);
2926 ERROR ((stderr
, "MACRO formal argument %s does not exist.\n", sb_name (&t
)));
2931 /* Insert this value into the right place */
2932 sb_reset (&ptr
->value
.f
->actual
);
2933 idx
= get_any_string (idx
+ 1, in
, &ptr
->value
.f
->actual
, 0, 0);
2938 /* This is a positional arg */
2942 ERROR ((stderr
, "Can't mix positional and keyword arguments.\n"));
2947 ERROR ((stderr
, "Too many positional arguments.\n"));
2951 sb_reset (&f
->actual
);
2952 idx
= get_any_string (idx
, in
, &f
->actual
, 1, 0);
2955 idx
= sb_skip_comma (idx
, in
);
2958 /* Copy the stuff from the macro buffer into a safe place and substitute any args */
2966 while (src
< in
->len
)
2968 if (in
->ptr
[src
] == '&')
2971 src
= sub_actual (src
+ 1, in
, &t
, m
, '&', &out
, 0);
2973 else if (in
->ptr
[src
] == '\\')
2976 if (in
->ptr
[src
] == comment_char
)
2978 /* This is a comment, just drop the rest of the line */
2979 while (src
< in
->len
2980 && in
->ptr
[src
] != '\n')
2984 else if (in
->ptr
[src
] == '(')
2986 /* Sub in till the next ')' literally */
2988 while (src
< in
->len
&& in
->ptr
[src
] != ')')
2990 sb_add_char (&out
, in
->ptr
[src
++]);
2992 if (in
->ptr
[src
] == ')')
2995 ERROR ((stderr
, "Missplaced ).\n"));
2997 else if (in
->ptr
[src
] == '@')
2999 /* Sub in the macro invocation number */
3003 sprintf (buffer
, "%05d", number
);
3004 sb_add_string (&out
, buffer
);
3006 else if (in
->ptr
[src
] == '&')
3008 /* This is a preprocessor variable name, we don't do them
3010 sb_add_char (&out
, '\\');
3011 sb_add_char (&out
, '&');
3017 src
= sub_actual (src
, in
, &t
, m
, '\'', &out
, 0);
3020 else if (ISFIRSTCHAR (in
->ptr
[src
]) && alternate
)
3023 src
= sub_actual (src
, in
, &t
, m
, '\'', &out
, 1);
3025 else if (ISCOMMENTCHAR (in
->ptr
[src
])
3026 && src
+ 1 < in
->len
3027 && ISCOMMENTCHAR (in
->ptr
[src
+1])
3030 /* Two comment chars in a row cause the rest of the line to be dropped */
3031 while (src
< in
->len
&& in
->ptr
[src
] != '\n')
3034 else if (in
->ptr
[src
] == '"')
3037 sb_add_char (&out
, in
->ptr
[src
++]);
3041 sb_add_char (&out
, in
->ptr
[src
++]);
3044 include_buf (name
, &out
, include_macro
, include_next_index ());
3057 /* The macro name must be the first thing on the line */
3063 idx
= get_token (idx
, in
, &name
);
3067 /* Got a name, look it up */
3069 ptr
= hash_lookup (¯o_table
, &name
);
3073 /* It's in the table, copy out the stuff and convert any macro args */
3074 macro_expand (&name
, idx
, in
, ptr
->value
.m
);
3086 /* STRING HANDLING */
3089 getstring (idx
, in
, acc
)
3094 idx
= sb_skip_white (idx
, in
);
3096 while (idx
< in
->len
3097 && (in
->ptr
[idx
] == '"'
3098 || in
->ptr
[idx
] == '<'
3099 || (in
->ptr
[idx
] == '\'' && alternate
)))
3101 if (in
->ptr
[idx
] == '<')
3107 while ((in
->ptr
[idx
] != '>' || nest
)
3110 if (in
->ptr
[idx
] == '!')
3113 sb_add_char (acc
, in
->ptr
[idx
++]);
3116 if (in
->ptr
[idx
] == '>')
3118 if (in
->ptr
[idx
] == '<')
3120 sb_add_char (acc
, in
->ptr
[idx
++]);
3128 idx
= exp_get_abs ("Character code in string must be absolute expression.\n",
3130 sb_add_char (acc
, code
);
3132 if (in
->ptr
[idx
] != '>')
3133 ERROR ((stderr
, "Missing > for character code.\n"));
3137 else if (in
->ptr
[idx
] == '"' || in
->ptr
[idx
] == '\'')
3139 char tchar
= in
->ptr
[idx
];
3141 while (idx
< in
->len
)
3143 if (alternate
&& in
->ptr
[idx
] == '!')
3146 sb_add_char (acc
, in
->ptr
[idx
++]);
3149 if (in
->ptr
[idx
] == tchar
)
3152 if (idx
>= in
->len
|| in
->ptr
[idx
] != tchar
)
3155 sb_add_char (acc
, in
->ptr
[idx
]);
3165 /* .SDATA[C|Z] <string> */
3169 do_sdata (idx
, in
, type
)
3178 fprintf (outfile
, ".byte\t");
3180 while (!eol (idx
, in
))
3184 idx
= sb_skip_white (idx
, in
);
3185 while (!eol (idx
, in
))
3187 pidx
= idx
= get_any_string (idx
, in
, &acc
, 0, 1);
3192 ERROR ((stderr
, "string for SDATAC longer than 255 characters (%d).\n", acc
.len
));
3194 fprintf (outfile
, "%d", acc
.len
);
3198 for (i
= 0; i
< acc
.len
; i
++)
3202 fprintf (outfile
, ",");
3204 fprintf (outfile
, "%d", acc
.ptr
[i
]);
3211 fprintf (outfile
, ",");
3212 fprintf (outfile
, "0");
3214 idx
= sb_skip_comma (idx
, in
);
3215 if (idx
== pidx
) break;
3217 if (!alternate
&& in
->ptr
[idx
] != ',' && idx
!= in
->len
)
3219 fprintf (outfile
, "\n");
3220 ERROR ((stderr
, "illegal character in SDATA line (0x%x).\n", in
->ptr
[idx
]));
3226 fprintf (outfile
, "\n");
3229 /* .SDATAB <count> <string> */
3241 idx
= exp_get_abs ("Must have absolute SDATAB repeat count.\n", idx
, in
, &repeat
);
3244 ERROR ((stderr
, "Must have positive SDATAB repeat count (%d).\n", repeat
));
3248 idx
= sb_skip_comma (idx
, in
);
3249 idx
= getstring (idx
, in
, &acc
);
3251 for (i
= 0; i
< repeat
; i
++)
3254 fprintf (outfile
, "\t");
3255 fprintf (outfile
, ".byte\t");
3257 fprintf (outfile
, "\n");
3267 FILE *newone
= fopen (name
, "r");
3271 if (isp
== MAX_INCLUDES
)
3272 FATAL ((stderr
, "Unreasonable include depth (%ld).\n", (long) isp
));
3275 sp
->handle
= newone
;
3278 sb_add_string (&sp
->name
, name
);
3281 sp
->pushback_index
= 0;
3282 sp
->type
= include_file
;
3284 sb_new (&sp
->pushback
);
3289 do_include (idx
, in
)
3296 idx
= getstring (idx
, in
, &t
);
3297 text
= sb_name (&t
);
3298 if (!new_file (text
))
3300 FATAL ((stderr
, "Can't open include file `%s'.\n", text
));
3308 if (sp
!= include_stack
)
3311 fclose (sp
->handle
);
3316 /* Get the next character from the include stack. If there's anything
3317 in the pushback buffer, take that first. If we're at eof, pop from
3318 the stack and try again. Keep the linecount up to date. */
3325 if (sp
->pushback
.len
!= sp
->pushback_index
)
3327 r
= (char) (sp
->pushback
.ptr
[sp
->pushback_index
++]);
3328 /* When they've all gone, reset the pointer */
3329 if (sp
->pushback_index
== sp
->pushback
.len
)
3331 sp
->pushback
.len
= 0;
3332 sp
->pushback_index
= 0;
3335 else if (sp
->handle
)
3337 r
= getc (sp
->handle
);
3342 if (r
== EOF
&& isp
)
3346 while (r
== EOF
&& isp
)
3364 return sp
->linecount
;
3368 include_next_index ()
3372 && index
> MAX_REASONABLE
)
3373 FATAL ((stderr
, "Unreasonable expansion (-u turns off check).\n"));
3378 /* Initialize the chartype vector. */
3384 for (x
= 0; x
< 256; x
++)
3386 if (isalpha (x
) || x
== '_' || x
== '$')
3387 chartype
[x
] |= FIRSTBIT
;
3389 if (isdigit (x
) || isalpha (x
) || x
== '_' || x
== '$')
3390 chartype
[x
] |= NEXTBIT
;
3392 if (x
== ' ' || x
== '\t' || x
== ',' || x
== '"' || x
== ';'
3393 || x
== '"' || x
== '<' || x
== '>' || x
== ')' || x
== '(')
3394 chartype
[x
] |= SEPBIT
;
3396 if (x
== 'b' || x
== 'B'
3397 || x
== 'q' || x
== 'Q'
3398 || x
== 'h' || x
== 'H'
3399 || x
== 'd' || x
== 'D')
3400 chartype
[x
] |= BASEBIT
;
3402 if (x
== ' ' || x
== '\t')
3403 chartype
[x
] |= WHITEBIT
;
3405 if (x
== comment_char
)
3406 chartype
[x
] |= COMMENTBIT
;
3412 /* What to do with all the keywords */
3413 #define PROCESS 0x1000 /* Run substitution over the line */
3414 #define LAB 0x2000 /* Spit out the label */
3416 #define K_EQU PROCESS|1
3417 #define K_ASSIGN PROCESS|2
3418 #define K_REG PROCESS|3
3419 #define K_ORG PROCESS|4
3420 #define K_RADIX PROCESS|5
3421 #define K_DATA LAB|PROCESS|6
3422 #define K_DATAB LAB|PROCESS|7
3423 #define K_SDATA LAB|PROCESS|8
3424 #define K_SDATAB LAB|PROCESS|9
3425 #define K_SDATAC LAB|PROCESS|10
3426 #define K_SDATAZ LAB|PROCESS|11
3427 #define K_RES LAB|PROCESS|12
3428 #define K_SRES LAB|PROCESS|13
3429 #define K_SRESC LAB|PROCESS|14
3430 #define K_SRESZ LAB|PROCESS|15
3431 #define K_EXPORT LAB|PROCESS|16
3432 #define K_GLOBAL LAB|PROCESS|17
3433 #define K_PRINT LAB|PROCESS|19
3434 #define K_FORM LAB|PROCESS|20
3435 #define K_HEADING LAB|PROCESS|21
3436 #define K_PAGE LAB|PROCESS|22
3437 #define K_IMPORT LAB|PROCESS|23
3438 #define K_PROGRAM LAB|PROCESS|24
3439 #define K_END PROCESS|25
3440 #define K_INCLUDE PROCESS|26
3441 #define K_IGNORED PROCESS|27
3442 #define K_ASSIGNA PROCESS|28
3443 #define K_ASSIGNC 29
3444 #define K_AIF PROCESS|30
3445 #define K_AELSE PROCESS|31
3446 #define K_AENDI PROCESS|32
3447 #define K_AREPEAT PROCESS|33
3448 #define K_AENDR PROCESS|34
3450 #define K_AENDW PROCESS|36
3452 #define K_MACRO PROCESS|38
3454 #define K_ALIGN PROCESS|LAB|40
3455 #define K_ALTERNATE 41
3456 #define K_DB LAB|PROCESS|42
3457 #define K_DW LAB|PROCESS|43
3458 #define K_DL LAB|PROCESS|44
3470 { "EQU", K_EQU
, 0 },
3471 { "ALTERNATE", K_ALTERNATE
, 0 },
3472 { "ASSIGN", K_ASSIGN
, 0 },
3473 { "REG", K_REG
, 0 },
3474 { "ORG", K_ORG
, 0 },
3475 { "RADIX", K_RADIX
, 0 },
3476 { "DATA", K_DATA
, 0 },
3480 { "DATAB", K_DATAB
, 0 },
3481 { "SDATA", K_SDATA
, 0 },
3482 { "SDATAB", K_SDATAB
, 0 },
3483 { "SDATAZ", K_SDATAZ
, 0 },
3484 { "SDATAC", K_SDATAC
, 0 },
3485 { "RES", K_RES
, 0 },
3486 { "SRES", K_SRES
, 0 },
3487 { "SRESC", K_SRESC
, 0 },
3488 { "SRESZ", K_SRESZ
, 0 },
3489 { "EXPORT", K_EXPORT
, 0 },
3490 { "GLOBAL", K_GLOBAL
, 0 },
3491 { "PRINT", K_PRINT
, 0 },
3492 { "FORM", K_FORM
, 0 },
3493 { "HEADING", K_HEADING
, 0 },
3494 { "PAGE", K_PAGE
, 0 },
3495 { "PROGRAM", K_IGNORED
, 0 },
3496 { "END", K_END
, 0 },
3497 { "INCLUDE", K_INCLUDE
, 0 },
3498 { "ASSIGNA", K_ASSIGNA
, 0 },
3499 { "ASSIGNC", K_ASSIGNC
, 0 },
3500 { "AIF", K_AIF
, 0 },
3501 { "AELSE", K_AELSE
, 0 },
3502 { "AENDI", K_AENDI
, 0 },
3503 { "AREPEAT", K_AREPEAT
, 0 },
3504 { "AENDR", K_AENDR
, 0 },
3505 { "EXITM", K_EXITM
, 0 },
3506 { "MACRO", K_MACRO
, 0 },
3507 { "ENDM", K_ENDM
, 0 },
3508 { "AWHILE", K_AWHILE
, 0 },
3509 { "ALIGN", K_ALIGN
, 0 },
3510 { "AENDW", K_AENDW
, 0 },
3511 { "ALTERNATE", K_ALTERNATE
, 0 },
3512 { "LOCAL", K_LOCAL
, 0 },
3516 /* Look for a pseudo op on the line. If one's there then call
3520 process_pseudo_op (idx
, line
, acc
)
3527 if (line
->ptr
[idx
] == '.' || alternate
)
3529 /* Scan forward and find pseudo name */
3535 if (line
->ptr
[idx
] == '.')
3537 in
= line
->ptr
+ idx
;
3542 while (idx
< line
->len
&& *e
&& ISFIRSTCHAR (*e
))
3544 sb_add_char (acc
, *e
);
3549 ptr
= hash_lookup (&keyword_hash_table
, acc
);
3554 /* This one causes lots of pain when trying to preprocess
3556 WARNING ((stderr
, "Unrecognised pseudo op `%s'.\n", sb_name (acc
)));
3560 if (ptr
->value
.i
& LAB
)
3561 { /* output the label */
3564 fprintf (outfile
, "%s:\t", sb_name (&label
));
3567 fprintf (outfile
, "\t");
3570 if (ptr
->value
.i
& PROCESS
)
3572 /* Polish the rest of the line before handling the pseudo op */
3574 strip_comments(line
);
3577 process_assigns (idx
, line
, acc
);
3579 change_base (0, acc
, line
);
3584 switch (ptr
->value
.i
)
3600 switch (ptr
->value
.i
)
3612 ERROR ((stderr
, "ORG command not allowed.\n"));
3618 do_data (idx
, line
, 1);
3621 do_data (idx
, line
, 2);
3624 do_data (idx
, line
, 4);
3627 do_data (idx
, line
, 0);
3630 do_datab (idx
, line
);
3633 do_sdata (idx
, line
, 0);
3636 do_sdatab (idx
, line
);
3639 do_sdata (idx
, line
, 'c');
3642 do_sdata (idx
, line
, 'z');
3645 do_assign (1, 0, line
);
3651 do_arepeat (idx
, line
);
3657 do_awhile (idx
, line
);
3663 do_assign (0, idx
, line
);
3666 do_align (idx
, line
);
3669 do_res (idx
, line
, 0);
3672 do_res (idx
, line
, 's');
3675 do_include (idx
, line
);
3678 do_local (idx
, line
);
3681 do_macro (idx
, line
);
3687 do_res (idx
, line
, 'c');
3690 do_print (idx
, line
);
3693 do_form (idx
, line
);
3696 do_heading (idx
, line
);
3708 do_res (idx
, line
, 'z');
3716 do_assigna (idx
, line
);
3719 do_assignc (idx
, line
);
3735 /* Build the keyword hash table - put each keyword in the table twice,
3736 once upper and once lower case.*/
3743 for (i
= 0; kinfo
[i
].name
; i
++)
3748 sb_add_string (&label
, kinfo
[i
].name
);
3750 hash_add_to_int_table (&keyword_hash_table
, &label
, kinfo
[i
].code
);
3753 for (j
= 0; kinfo
[i
].name
[j
]; j
++)
3754 sb_add_char (&label
, kinfo
[i
].name
[j
] - 'A' + 'a');
3755 hash_add_to_int_table (&keyword_hash_table
, &label
, kinfo
[i
].code
);
3781 sb_add_char (&value
, *string
);
3784 exp_get_abs ("Invalid expression on command line.\n", 0, &value
, &res
);
3788 sb_add_char (&label
, *string
);
3793 ptr
= hash_create (&vars
, &label
);
3794 free_old_entry (ptr
);
3795 ptr
->type
= hash_integer
;
3801 /* The list of long options. */
3802 static struct option long_options
[] =
3804 { "alternate", no_argument
, 0, 'a' },
3805 { "commentchar", required_argument
, 0, 'c' },
3806 { "copysource", no_argument
, 0, 's' },
3807 { "debug", no_argument
, 0, 'd' },
3808 { "help", no_argument
, 0, 'h' },
3809 { "output", required_argument
, 0, 'o' },
3810 { "print", no_argument
, 0, 'p' },
3811 { "unreasonable", no_argument
, 0, 'u' },
3812 { "version", no_argument
, 0, 'v' },
3813 { "define", required_argument
, 0, 'd' },
3814 { NULL
, no_argument
, 0, 0 }
3817 /* Show a usage message and exit. */
3819 show_usage (file
, status
)
3825 [-a] [--alternate] enter alternate macro mode\n\
3826 [-c char] [--commentchar char] change the comment character from !\n\
3827 [-d] [--debug] print some debugging info\n\
3828 [-h] [--help] print this message\n\
3829 [-o out] [--output out] set the output file\n\
3830 [-p] [--print] print line numbers\n\
3831 [-s] [--copysource] copy source through as comments \n\
3832 [-u] [--unreasonable] allow unreasonable nesting\n\
3833 [-v] [--version] print the program version\n\
3834 [-Dname=value] create preprocessor variable called name, with value\n\
3835 [in-file]\n", program_name
);
3839 /* Display a help message and exit. */
3843 printf ("%s: Gnu Assembler Macro Preprocessor\n",
3845 show_usage (stdout
, 0);
3862 program_name
= argv
[0];
3863 xmalloc_set_program_name (program_name
);
3865 hash_new_table (101, ¯o_table
);
3866 hash_new_table (101, &keyword_hash_table
);
3867 hash_new_table (101, &assign_hash_table
);
3868 hash_new_table (101, &vars
);
3873 while ((opt
= getopt_long (argc
, argv
, "sdhavc:upo:D:", long_options
,
3886 print_line_number
= 1;
3889 comment_char
= optarg
[0];
3907 printf ("GNU %s version %s\n", program_name
, program_version
);
3913 show_usage (stderr
, 1);
3920 outfile
= fopen (out_name
, "w");
3923 fprintf (stderr
, "%s: Can't open output file `%s'.\n",
3924 program_name
, out_name
);
3936 /* Process all the input files */
3938 while (optind
< argc
)
3940 if (new_file (argv
[optind
]))
3946 fprintf (stderr
, "%s: Can't open input file `%s'.\n",
3947 program_name
, argv
[optind
]);