1 /* gasp.c - Gnu assembler preprocessor main program.
2 Copyright (C) 1994 Free Software Foundation, Inc.
4 Written by Steve and Judy Chamberlain of Cygnus Support,
7 This file is part of GASP, the GNU Assembler Preprocessor.
9 GASP is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
14 GASP is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GASP; see the file COPYING. If not, write to
21 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
25 This program translates the input macros and stuff into a form
26 suitable for gas to consume.
29 gasp [-sdhau] [-c char] [-o <outfile>] <infile>*
31 -s copy source to output
32 -c <char> comments are started with <char> instead of !
33 -u allow unreasonable stuff
35 -d print debugging stats
36 -s semi colons start comments
37 -a use alternate syntax
38 Pseudo ops can start with or without a .
39 Labels have to be in first column.
40 Macro arg parameters subsituted by name, don't need the &.
41 String can start with ' too.
42 Strings can be surrounded by <..>
43 A %<exp> in a string evaluates the expression
44 Literal char in a string with !
55 #include "libiberty.h"
57 char *program_version
= "1.2";
59 #define MAX_INCLUDES 30 /* Maximum include depth */
60 #define MAX_REASONABLE 1000 /* Maximum number of expansions */
62 int unreasonable
; /* -u on command line */
63 int stats
; /* -d on command line */
64 int print_line_number
; /* -p flag on command line */
65 int copysource
; /* -c flag on command line */
66 int warnings
; /* Number of WARNINGs generated so far. */
67 int errors
; /* Number of ERRORs generated so far. */
68 int fatals
; /* Number of fatal ERRORs generated so far (either 0 or 1). */
69 int alternate
= 0; /* -a on command line */
70 char comment_char
= '!';
71 int radix
= 10; /* Default radix */
73 int had_end
; /* Seen .END */
75 /* The output stream */
79 /* Forward declarations. */
80 static int condass_lookup_name();
81 static int condass_on();
83 static int get_and_process();
84 static int get_token();
85 static int getstring();
86 static int include_next_index();
87 static int macro_op();
88 static int linecount();
89 static int process_pseudo_op();
90 static void include_pop();
91 static void include_print_where_line();
94 I had a couple of choices when deciding upon this data structure.
95 gas uses null terminated strings for all its internal work. This
96 often means that parts of the program that want to examine
97 substrings have to manipulate the data in the string to do the
98 right thing (a common operation is to single out a bit of text by
99 saving away the character after it, nulling it out, operating on
100 the substring and then replacing the character which was under the
101 null). This is a pain and I remember a load of problems that I had with
102 code in gas which almost got this right. Also, it's harder to grow and
103 allocate null terminated strings efficiently.
105 Obstacks provide all the functionality needed, but are too
106 complicated, hence the sb.
108 An sb is allocated by the caller, and is initialzed to point to an
109 sb_element. sb_elements are kept on a free lists, and used when
110 needed, replaced onto the free list when unused.
113 #define max_power_two 30 /* don't allow strings more than
114 2^max_power_two long */
115 /* structure of an sb */
118 char *ptr
; /* points to the current block. */
119 int len
; /* how much is used. */
120 int pot
; /* the maximum length is 1<<pot */
125 /* Structure of the free list object of an sb */
137 sb_element
*size
[max_power_two
];
140 sb_list_vector free_list
;
142 int string_count
[max_power_two
];
144 /* the attributes of each character are stored as a bit pattern
145 chartype, which gives us quick tests. */
152 #define COMMENTBIT 16
154 #define ISCOMMENTCHAR(x) (chartype[(unsigned)(x)] & COMMENTBIT)
155 #define ISFIRSTCHAR(x) (chartype[(unsigned)(x)] & FIRSTBIT)
156 #define ISNEXTCHAR(x) (chartype[(unsigned)(x)] & NEXTBIT)
157 #define ISSEP(x) (chartype[(unsigned)(x)] & SEPBIT)
158 #define ISWHITE(x) (chartype[(unsigned)(x)] & WHITEBIT)
159 #define ISBASE(x) (chartype[(unsigned)(x)] & BASEBIT)
160 static char chartype
[256];
163 /* Conditional assembly uses the `ifstack'. Each aif pushes another
164 entry onto the stack, and sets the on flag if it should. The aelse
165 sets hadelse, and toggles on. An aend pops a level. We limit to
166 100 levels of nesting, not because we're facists pigs with read
167 only minds, but because more than 100 levels of nesting is probably
168 a bug in the user's macro structure. */
170 #define IFNESTING 100
173 int on
; /* is the level being output */
174 int hadelse
; /* has an aelse been seen */
179 /* The final and intermediate results of expression evaluation are kept in
180 exp_t's. Note that a symbol is not an sb, but a pointer into the input
181 line. It must be coped somewhere safe before the next line is read in. */
192 int value
; /* constant part */
193 symbol add_symbol
; /* name part */
194 symbol sub_symbol
; /* name part */
199 /* Hashing is done in a pretty standard way. A hash_table has a
200 pointer to a vector of pointers to hash_entrys, and the size of the
201 vector. A hash_entry contains a union of all the info we like to
202 store in hash table. If there is a hash collision, hash_entries
203 with the same hash are kept in a chain. */
205 /* What the data in a hash_entry means */
208 hash_integer
, /* name->integer mapping */
209 hash_string
, /* name->string mapping */
210 hash_macro
, /* name is a macro */
211 hash_formal
/* name is a formal argument */
216 sb key
; /* symbol name */
217 hash_type type
; /* symbol meaning */
222 struct macro_struct
*m
;
223 struct formal_struct
*f
;
225 struct hs
*next
; /* next hash_entry with same hash key */
235 /* Structures used to store macros.
237 Each macro knows its name and included text. It gets built with a
238 list of formal arguments, and also keeps a hash table which points
239 into the list to speed up formal search. Each formal knows its
240 name and its default value. Each time the macro is expanded, the
241 formals get the actual values attatched to them. */
243 /* describe the formal arguments to a macro */
245 typedef struct formal_struct
247 struct formal_struct
*next
; /* next formal in list */
248 sb name
; /* name of the formal */
249 sb def
; /* the default value */
250 sb actual
; /* the actual argument (changed on each expansion) */
251 int index
; /* the index of the formal 0..formal_count-1 */
255 /* describe the macro. */
257 typedef struct macro_struct
259 sb sub
; /* substitution text. */
260 int formal_count
; /* number of formal args. */
261 formal_entry
*formals
; /* pointer to list of formal_structs */
262 hash_table formal_hash
; /* hash table of formals. */
266 /* how we nest files and expand macros etc.
268 we keep a stack of of include_stack structs. each include file
269 pushes a new level onto the stack. we keep an sb with a pushback
270 too. unget chars are pushed onto the pushback sb, getchars first
271 checks the pushback sb before reading from the input stream.
273 small things are expanded by adding the text of the item onto the
274 pushback sb. larger items are grown by pushing a new level and
275 allocating the entire pushback buf for the item. each time
276 something like a macro is expanded, the stack index is changed. we
277 can then perform an exitm by popping all entries off the stack with
278 the same stack index. if we're being reasonable, we can detect
279 recusive expansion by checking the index is reasonably small.
284 include_file
, include_repeat
, include_while
, include_macro
289 sb pushback
; /* current pushback stream */
290 int pushback_index
; /* next char to read from stream */
291 FILE *handle
; /* open file */
292 sb name
; /* name of file */
293 int linecount
; /* number of lines read so far */
295 int index
; /* index of this layer */
297 include_stack
[MAX_INCLUDES
];
299 struct include_stack
*sp
;
300 #define isp (sp - include_stack)
305 void include_print_where_line ();
309 do { include_print_where_line (stderr); fprintf x ; fatals++; quit(); } while(0)
311 do { include_print_where_line (stderr); fprintf x; errors++; } while(0)
313 do { include_print_where_line (stderr); fprintf x; warnings++;} while(0)
317 /* exit the program and return the right ERROR code. */
330 for (i
= 0; i
< max_power_two
; i
++)
332 fprintf (stderr
, "strings size %8d : %d\n", 1<<i
, string_count
[i
]);
339 /* this program is about manipulating strings.
340 they are managed in things called `sb's which is an abbreviation
341 for string buffers. an sb has to be created, things can be glued
342 on to it, and at the end of it's life it should be freed. the
343 contents should never be pointed at whilst it is still growing,
344 since it could be moved at any time
348 sb_grow... (&foo,...);
354 /* initializes an sb. */
361 /* see if we can find one to allocate */
364 if (size
> max_power_two
)
366 FATAL ((stderr
, "string longer than %d bytes requested.\n",
367 1 << max_power_two
));
369 e
= free_list
.size
[size
];
372 /* nothing there, allocate one and stick into the free list */
373 e
= (sb_element
*) xmalloc (sizeof (sb_element
) + (1 << size
));
374 e
->next
= free_list
.size
[size
];
376 free_list
.size
[size
] = e
;
377 string_count
[size
]++;
380 /* remove from free list */
382 free_list
.size
[size
] = e
->next
;
384 /* copy into callers world */
396 sb_build (ptr
, dsize
);
399 /* deallocate the sb at ptr */
406 /* return item to free list */
407 ptr
->item
->next
= free_list
.size
[ptr
->pot
];
408 free_list
.size
[ptr
->pot
] = ptr
->item
;
411 /* add the sb at s to the end of the sb at ptr */
413 static void sb_check ();
421 sb_check (ptr
, s
->len
);
422 memcpy (ptr
->ptr
+ ptr
->len
, s
->ptr
, s
->len
);
426 /* make sure that the sb at ptr has room for another len characters,
427 and grow it if it doesn't. */
434 if (ptr
->len
+ len
>= 1 << ptr
->pot
)
438 while (ptr
->len
+ len
>= 1 << pot
)
440 sb_build (&tmp
, pot
);
441 sb_add_sb (&tmp
, ptr
);
447 /* make the sb at ptr point back to the beginning. */
456 /* add character c to the end of the sb at ptr. */
464 ptr
->ptr
[ptr
->len
++] = c
;
467 /* add null terminated string s to the end of sb at ptr. */
470 sb_add_string (ptr
, s
)
474 int len
= strlen (s
);
476 memcpy (ptr
->ptr
+ ptr
->len
, s
, len
);
480 /* add string at s of length len to sb at ptr */
483 sb_add_buffer (ptr
, s
, len
)
489 memcpy (ptr
->ptr
+ ptr
->len
, s
, len
);
494 /* print the sb at ptr to the output file */
504 for (i
= 0; i
< ptr
->len
; i
++)
508 fprintf (outfile
, ",");
510 fprintf (outfile
, "%d", ptr
->ptr
[i
]);
517 sb_print_at (idx
, ptr
)
522 for (i
= idx
; i
< ptr
->len
; i
++)
523 putc (ptr
->ptr
[i
], outfile
);
525 /* put a null at the end of the sb at in and return the start of the
526 string, so that it can be used as an arg to printf %s. */
533 /* stick a null on the end of the string */
538 /* start at the index idx into the string in sb at ptr and skip
539 whitespace. return the index of the first non whitespace character */
542 sb_skip_white (idx
, ptr
)
546 while (idx
< ptr
->len
&& ISWHITE (ptr
->ptr
[idx
]))
551 /* start at the index idx into the sb at ptr. skips whitespace,
552 a comma and any following whitespace. returnes the index of the
556 sb_skip_comma (idx
, ptr
)
560 while (idx
< ptr
->len
&& ISWHITE (ptr
->ptr
[idx
]))
564 && ptr
->ptr
[idx
] == ',')
567 while (idx
< ptr
->len
&& ISWHITE (ptr
->ptr
[idx
]))
574 /* hash table maintenance. */
576 /* build a new hash table with size buckets, and fill in the info at ptr. */
579 hash_new_table (size
, ptr
)
585 ptr
->table
= (hash_entry
**) xmalloc (size
* (sizeof (hash_entry
*)));
586 /* Fill with null-pointer, not zero-bit-pattern. */
587 for (i
= 0; i
< size
; i
++)
591 /* calculate and return the hash value of the sb at key. */
600 for (i
= 0; i
< key
->len
; i
++)
608 /* lookup key in hash_table tab, if present, then return it, otherwise
609 build a new one and fill it with hash_integer. */
613 hash_create (tab
, key
)
617 int k
= hash (key
) % tab
->size
;
619 hash_entry
**table
= tab
->table
;
627 hash_entry
*n
= (hash_entry
*) xmalloc (sizeof (hash_entry
));
630 sb_add_sb (&n
->key
, key
);
632 n
->type
= hash_integer
;
635 if (strncmp (table
[k
]->key
.ptr
, key
->ptr
, key
->len
) == 0)
643 /* add sb name with key into hash_table tab. if replacing old value
644 and again, then ERROR. */
648 hash_add_to_string_table (tab
, key
, name
, again
)
654 hash_entry
*ptr
= hash_create (tab
, key
);
655 if (ptr
->type
== hash_integer
)
657 sb_new (&ptr
->value
.s
);
659 if (ptr
->value
.s
.len
)
662 ERROR ((stderr
, "redefintion not allowed"));
665 ptr
->type
= hash_string
;
666 sb_reset (&ptr
->value
.s
);
668 sb_add_sb (&ptr
->value
.s
, name
);
671 /* add integer name to hash_table tab with sb key. */
675 hash_add_to_int_table (tab
, key
, name
)
680 hash_entry
*ptr
= hash_create (tab
, key
);
684 /* lookup sb key in hash_table tab. if found return hash_entry result,
689 hash_lookup (tab
, key
)
693 int k
= hash (key
) % tab
->size
;
694 hash_entry
**table
= tab
->table
;
695 hash_entry
*p
= table
[k
];
698 if (p
->key
.len
== key
->len
699 && strncmp (p
->key
.ptr
, key
->ptr
, key
->len
) == 0)
709 are handled in a really simple recursive decent way. each bit of
710 the machine takes an index into an sb and a pointer to an exp_t,
711 modifies the *exp_t and returns the index of the first character
712 past the part of the expression parsed.
714 expression precedence:
725 /* make sure that the exp_t at term is constant, if not the give the op ERROR. */
729 checkconst (op
, term
)
733 if (term
->add_symbol
.len
734 || term
->sub_symbol
.len
)
736 ERROR ((stderr
, "the %c operator cannot take non-absolute arguments.\n", op
));
740 /* turn the number in string at idx into a number of base,
741 fill in ptr and return the index of the first character not in the
746 sb_strtol (idx
, string
, base
, ptr
)
753 idx
= sb_skip_white (idx
, string
);
755 while (idx
< string
->len
)
757 int ch
= string
->ptr
[idx
];
761 else if (ch
>= 'a' && ch
<= 'f')
763 else if (ch
>= 'A' && ch
<= 'F')
771 value
= value
* base
+ dig
;
778 static int level_5 ();
781 level_0 (idx
, string
, lhs
)
786 lhs
->add_symbol
.len
= 0;
787 lhs
->add_symbol
.name
= 0;
789 lhs
->sub_symbol
.len
= 0;
790 lhs
->sub_symbol
.name
= 0;
792 idx
= sb_skip_white (idx
, string
);
796 if (isdigit (string
->ptr
[idx
]))
798 idx
= sb_strtol (idx
, string
, 10, &lhs
->value
);
800 else if (ISFIRSTCHAR (string
->ptr
[idx
]))
803 lhs
->add_symbol
.name
= string
->ptr
+ idx
;
804 while (idx
< string
->len
&& ISNEXTCHAR (string
->ptr
[idx
]))
809 lhs
->add_symbol
.len
= len
;
811 else if (string
->ptr
[idx
] == '"')
815 ERROR ((stderr
, "string where expression expected.\n"));
816 idx
= getstring (idx
, string
, &acc
);
821 ERROR ((stderr
, "can't find primary in expression.\n"));
824 return sb_skip_white (idx
, string
);
830 level_1 (idx
, string
, lhs
)
835 idx
= sb_skip_white (idx
, string
);
837 switch (string
->ptr
[idx
])
840 idx
= level_1 (idx
+ 1, string
, lhs
);
843 idx
= level_1 (idx
+ 1, string
, lhs
);
844 checkconst ('~', lhs
);
845 lhs
->value
= ~lhs
->value
;
850 idx
= level_1 (idx
+ 1, string
, lhs
);
851 lhs
->value
= -lhs
->value
;
853 lhs
->add_symbol
= lhs
->sub_symbol
;
859 idx
= level_5 (sb_skip_white (idx
, string
), string
, lhs
);
860 if (string
->ptr
[idx
] != ')')
861 ERROR ((stderr
, "misplaced closing parens.\n"));
866 idx
= level_0 (idx
, string
, lhs
);
869 return sb_skip_white (idx
, string
);
873 level_2 (idx
, string
, lhs
)
880 idx
= level_1 (idx
, string
, lhs
);
882 while (idx
< string
->len
&& (string
->ptr
[idx
] == '*'
883 || string
->ptr
[idx
] == '/'))
885 char op
= string
->ptr
[idx
++];
886 idx
= level_1 (idx
, string
, &rhs
);
890 checkconst ('*', lhs
);
891 checkconst ('*', &rhs
);
892 lhs
->value
*= rhs
.value
;
895 checkconst ('/', lhs
);
896 checkconst ('/', &rhs
);
898 ERROR ((stderr
, "attempt to divide by zero.\n"));
900 lhs
->value
/= rhs
.value
;
904 return sb_skip_white (idx
, string
);
909 level_3 (idx
, string
, lhs
)
916 idx
= level_2 (idx
, string
, lhs
);
918 while (idx
< string
->len
919 && (string
->ptr
[idx
] == '+'
920 || string
->ptr
[idx
] == '-'))
922 char op
= string
->ptr
[idx
++];
923 idx
= level_2 (idx
, string
, &rhs
);
927 lhs
->value
+= rhs
.value
;
928 if (lhs
->add_symbol
.name
&& rhs
.add_symbol
.name
)
930 ERROR ((stderr
, "can't add two relocatable expressions\n"));
932 /* change nn+symbol to symbol + nn */
933 if (rhs
.add_symbol
.name
)
935 lhs
->add_symbol
= rhs
.add_symbol
;
939 lhs
->value
-= rhs
.value
;
940 lhs
->sub_symbol
= rhs
.add_symbol
;
944 return sb_skip_white (idx
, string
);
948 level_4 (idx
, string
, lhs
)
955 idx
= level_3 (idx
, string
, lhs
);
957 while (idx
< string
->len
&&
958 string
->ptr
[idx
] == '&')
960 char op
= string
->ptr
[idx
++];
961 idx
= level_3 (idx
, string
, &rhs
);
965 checkconst ('&', lhs
);
966 checkconst ('&', &rhs
);
967 lhs
->value
&= rhs
.value
;
971 return sb_skip_white (idx
, string
);
975 level_5 (idx
, string
, lhs
)
982 idx
= level_4 (idx
, string
, lhs
);
984 while (idx
< string
->len
985 && (string
->ptr
[idx
] == '|' || string
->ptr
[idx
] == '~'))
987 char op
= string
->ptr
[idx
++];
988 idx
= level_4 (idx
, string
, &rhs
);
992 checkconst ('|', lhs
);
993 checkconst ('|', &rhs
);
994 lhs
->value
|= rhs
.value
;
997 checkconst ('~', lhs
);
998 checkconst ('~', &rhs
);
999 lhs
->value
^= rhs
.value
;
1003 return sb_skip_white (idx
, string
);
1007 /* parse the expression at offset idx into string, fill up res with
1008 the result. return the index of the first char past the expression.
1012 exp_parse (idx
, string
, res
)
1017 return level_5 (sb_skip_white (idx
, string
), string
, res
);
1021 /* turn the expression at exp into text and glue it onto the end of
1025 exp_string (exp
, string
)
1033 if (exp
->add_symbol
.len
)
1035 sb_add_buffer (string
, exp
->add_symbol
.name
, exp
->add_symbol
.len
);
1043 sb_add_char (string
, '+');
1044 sprintf (buf
, "%d", exp
->value
);
1045 sb_add_string (string
, buf
);
1049 if (exp
->sub_symbol
.len
)
1051 sb_add_char (string
, '-');
1052 sb_add_buffer (string
, exp
->add_symbol
.name
, exp
->add_symbol
.len
);
1058 sb_add_char (string
, '0');
1062 /* parse the expression at offset idx into sb in, return the value in val.
1063 if the expression is not constant, give ERROR emsg. returns the index
1064 of the first character past the end of the expression. */
1067 exp_get_abs (emsg
, idx
, in
, val
)
1074 idx
= exp_parse (idx
, in
, &res
);
1075 if (res
.add_symbol
.len
|| res
.sub_symbol
.len
)
1076 ERROR ((stderr
, emsg
));
1082 sb label
; /* current label parsed from line */
1083 hash_table assign_hash_table
; /* hash table for all assigned variables */
1084 hash_table keyword_hash_table
; /* hash table for keyword */
1085 hash_table vars
; /* hash table for eq variables */
1087 #define in_comment ';'
1091 strip_comments (out
)
1096 for (i
= 0; i
< out
->len
; i
++)
1098 if (ISCOMMENTCHAR(s
[i
]))
1107 /* push back character ch so that it can be read again. */
1117 if (sp
->pushback_index
)
1118 sp
->pushback_index
--;
1120 sb_add_char (&sp
->pushback
, ch
);
1123 /* push the sb ptr onto the include stack, with the given name, type and index. */
1127 include_buf (name
, ptr
, type
, index
)
1134 if (sp
- include_stack
>= MAX_INCLUDES
)
1135 FATAL ((stderr
, "unreasonable nesting.\n"));
1137 sb_add_sb (&sp
->name
, name
);
1140 sp
->pushback_index
= 0;
1143 sb_new (&sp
->pushback
);
1144 sb_add_sb (&sp
->pushback
, ptr
);
1148 /* used in ERROR messages, print info on where the include stack is onto file. */
1151 include_print_where_line (file
)
1154 struct include_stack
*p
= include_stack
+ 1;
1158 fprintf (file
, "%s:%d ", sb_name (&p
->name
), p
->linecount
- ((p
== sp
) ? 1 : 0));
1163 /* used in listings, print the line number onto file. */
1165 include_print_line (file
)
1169 struct include_stack
*p
= include_stack
+ 1;
1171 n
= fprintf (file
, "%4d", p
->linecount
);
1175 n
+= fprintf (file
, ".%d", p
->linecount
);
1180 fprintf (file
, " ");
1186 /* read a line from the top of the include stack into sb in. */
1197 putc (comment_char
, outfile
);
1198 if (print_line_number
)
1199 include_print_line (outfile
);
1213 WARNING ((stderr
, "End of file not at start of line.\n"));
1215 putc ('\n', outfile
);
1234 /* continued line */
1237 putc (comment_char
, outfile
);
1238 putc ('+', outfile
);
1251 sb_add_char (in
, ch
);
1259 /* find a label from sb in and put it in out. */
1262 grab_label (in
, out
)
1268 if (ISFIRSTCHAR (in
->ptr
[i
]))
1270 sb_add_char (out
, in
->ptr
[i
]);
1272 while ((ISNEXTCHAR (in
->ptr
[i
])
1273 || in
->ptr
[i
] == '\\'
1274 || in
->ptr
[i
] == '&')
1277 sb_add_char (out
, in
->ptr
[i
]);
1284 /* find all strange base stuff and turn into decimal. also
1285 find all the other numbers and convert them from the default radix */
1288 change_base (idx
, in
, out
)
1295 while (idx
< in
->len
)
1297 if (idx
< in
->len
- 1 && in
->ptr
[idx
+ 1] == '\'')
1301 switch (in
->ptr
[idx
])
1320 ERROR ((stderr
, "Illegal base character %c.\n", in
->ptr
[idx
]));
1325 idx
= sb_strtol (idx
+ 2, in
, base
, &value
);
1326 sprintf (buffer
, "%d", value
);
1327 sb_add_string (out
, buffer
);
1329 else if (ISFIRSTCHAR (in
->ptr
[idx
]))
1331 /* copy entire names through quickly */
1332 sb_add_char (out
, in
->ptr
[idx
]);
1334 while (idx
< in
->len
&& ISNEXTCHAR (in
->ptr
[idx
]))
1336 sb_add_char (out
, in
->ptr
[idx
]);
1340 else if (isdigit (in
->ptr
[idx
]))
1343 /* all numbers must start with a digit, let's chew it and
1345 idx
= sb_strtol (idx
, in
, radix
, &value
);
1346 sprintf (buffer
, "%d", value
);
1347 sb_add_string (out
, buffer
);
1349 /* skip all undigsested letters */
1350 while (idx
< in
->len
&& ISNEXTCHAR (in
->ptr
[idx
]))
1352 sb_add_char (out
, in
->ptr
[idx
]);
1358 /* nothing special, just pass it through */
1359 sb_add_char (out
, in
->ptr
[idx
]);
1376 do_assign (again
, idx
, in
)
1381 /* stick label in symbol table with following value */
1386 idx
= exp_parse (idx
, in
, &e
);
1387 exp_string (&e
, &acc
);
1388 hash_add_to_string_table (&assign_hash_table
, &label
, &acc
, again
);
1393 /* .radix [b|q|d|h] */
1400 int idx
= sb_skip_white (0, ptr
);
1401 switch (ptr
->ptr
[idx
])
1420 ERROR ((stderr
, "radix is %c must be one of b, q, d or h", radix
));
1425 /* Parse off a .b, .w or .l */
1428 get_opsize (idx
, in
, size
)
1434 if (in
->ptr
[idx
] == '.')
1438 switch (in
->ptr
[idx
])
1456 ERROR ((stderr
, "size must be one of b, w or l, is %c.\n", in
->ptr
[idx
]));
1469 idx
= sb_skip_white (idx
, line
);
1471 && ISCOMMENTCHAR(line
->ptr
[idx
]))
1473 if (idx
>= line
->len
)
1478 /* .data [.b|.w|.l] <data>*
1479 or d[bwl] <data>* */
1482 do_data (idx
, in
, size
)
1494 idx
= get_opsize (idx
, in
, &opsize
);
1513 fprintf (outfile
, "%s\t", opname
);
1515 idx
= sb_skip_white (idx
, in
);
1519 && in
->ptr
[idx
] == '"')
1522 idx
= getstring (idx
, in
, &acc
);
1523 for (i
= 0; i
< acc
.len
; i
++)
1526 fprintf(outfile
,",");
1527 fprintf (outfile
, "%d", acc
.ptr
[i
]);
1532 while (!eol (idx
, in
))
1535 idx
= exp_parse (idx
, in
, &e
);
1536 exp_string (&e
, &acc
);
1537 sb_add_char (&acc
, 0);
1538 fprintf (outfile
, acc
.ptr
);
1539 if (idx
< in
->len
&& in
->ptr
[idx
] == ',')
1541 fprintf (outfile
, ",");
1547 sb_print_at (idx
, in
);
1548 fprintf (outfile
, "\n");
1551 /* .datab [.b|.w|.l] <repeat>,<fill> */
1562 idx
= get_opsize (idx
, in
, &opsize
);
1564 idx
= exp_get_abs ("datab repeat must be constant.\n", idx
, in
, &repeat
);
1565 idx
= sb_skip_comma (idx
, in
);
1566 idx
= exp_get_abs ("datab data must be absolute.\n", idx
, in
, &fill
);
1568 fprintf (outfile
, ".fill\t%d,%d,%d\n", repeat
, opsize
, fill
);
1579 idx
= exp_get_abs ("align needs absolute expression.\n", idx
, in
, &al
);
1584 WARNING ((stderr
, "alignment must be one of 1, 2 or 4.\n"));
1586 fprintf (outfile
, ".align %d\n", al
);
1589 /* .res[.b|.w|.l] <size> */
1592 do_res (idx
, in
, type
)
1600 idx
= get_opsize (idx
, in
, &size
);
1601 while (!eol(idx
, in
))
1603 idx
= sb_skip_white (idx
, in
);
1604 if (in
->ptr
[idx
] == ',')
1606 idx
= exp_get_abs ("res needs absolute expression for fill count.\n", idx
, in
, &count
);
1608 if (type
== 'c' || type
== 'z')
1611 fprintf (outfile
, ".space %d\n", count
* size
);
1622 fprintf (outfile
, ".global %s\n", sb_name (in
));
1625 /* .print [list] [nolist] */
1632 idx
= sb_skip_white (idx
, in
);
1633 while (idx
< in
->len
)
1635 if (strncmp (in
->ptr
+ idx
, "LIST", 4) == 0)
1637 fprintf (outfile
, ".list\n");
1640 else if (strncmp (in
->ptr
+ idx
, "NOLIST", 6) == 0)
1642 fprintf (outfile
, ".nolist\n");
1651 do_heading (idx
, in
)
1657 idx
= getstring (idx
, in
, &head
);
1658 fprintf (outfile
, ".title \"%s\"\n", sb_name (&head
));
1667 fprintf (outfile
, ".eject\n");
1670 /* .form [lin=<value>] [col=<value>] */
1678 idx
= sb_skip_white (idx
, in
);
1680 while (idx
< in
->len
)
1683 if (strncmp (in
->ptr
+ idx
, "LIN=", 4) == 0)
1686 idx
= exp_get_abs ("form LIN= needs absolute expresssion.\n", idx
, in
, &lines
);
1689 if (strncmp (in
->ptr
+ idx
, "COL=", 4) == 0)
1692 idx
= exp_get_abs ("form COL= needs absolute expresssion.\n", idx
, in
, &columns
);
1697 fprintf (outfile
, ".psize %d,%d\n", lines
, columns
);
1702 /* Fetch string from the input stream,
1704 'Bxyx<whitespace> -> return 'Bxyza
1705 %<char> -> return string of decimal value of x
1706 "<string>" -> return string
1707 xyx<whitespace> -> return xyz
1710 get_any_string (idx
, in
, out
, expand
, pretend_quoted
)
1718 idx
= sb_skip_white (idx
, in
);
1722 if (in
->len
> 2 && in
->ptr
[idx
+1] == '\'' && ISBASE (in
->ptr
[idx
]))
1724 while (!ISSEP (in
->ptr
[idx
]))
1725 sb_add_char (out
, in
->ptr
[idx
++]);
1727 else if (in
->ptr
[idx
] == '%'
1733 /* Turns the next expression into a string */
1734 idx
= exp_get_abs ("% operator needs absolute expression",
1738 sprintf(buf
, "%d", val
);
1739 sb_add_string (out
, buf
);
1741 else if (in
->ptr
[idx
] == '"'
1742 || in
->ptr
[idx
] == '<'
1743 || (alternate
&& in
->ptr
[idx
] == '\''))
1745 if (alternate
&& expand
)
1747 /* Keep the quotes */
1748 sb_add_char (out
, '\"');
1750 idx
= getstring (idx
, in
, out
);
1751 sb_add_char (out
, '\"');
1755 idx
= getstring (idx
, in
, out
);
1760 while (idx
< in
->len
1761 && (in
->ptr
[idx
] == '"'
1762 || in
->ptr
[idx
] == '\''
1764 || !ISSEP (in
->ptr
[idx
])))
1766 if (in
->ptr
[idx
] == '"'
1767 || in
->ptr
[idx
] == '\'')
1769 char tchar
= in
->ptr
[idx
];
1770 sb_add_char (out
, in
->ptr
[idx
++]);
1771 while (idx
< in
->len
1772 && in
->ptr
[idx
] != tchar
)
1773 sb_add_char (out
, in
->ptr
[idx
++]);
1777 sb_add_char (out
, in
->ptr
[idx
++]);
1786 /* skip along sb in starting at idx, suck off whitespace a ( and more
1787 whitespace. return the idx of the next char */
1790 skip_openp (idx
, in
)
1794 idx
= sb_skip_white (idx
, in
);
1795 if (in
->ptr
[idx
] != '(')
1796 ERROR ((stderr
, "misplaced ( .\n"));
1797 idx
= sb_skip_white (idx
+ 1, in
);
1801 /* skip along sb in starting at idx, suck off whitespace a ) and more
1802 whitespace. return the idx of the next char */
1805 skip_closep (idx
, in
)
1809 idx
= sb_skip_white (idx
, in
);
1810 if (in
->ptr
[idx
] != ')')
1811 ERROR ((stderr
, "misplaced ).\n"));
1812 idx
= sb_skip_white (idx
+ 1, in
);
1819 dolen (idx
, in
, out
)
1828 sb_new (&stringout
);
1829 idx
= skip_openp (idx
, in
);
1830 idx
= get_and_process (idx
, in
, &stringout
);
1831 idx
= skip_closep (idx
, in
);
1832 sprintf (buffer
, "%d", stringout
.len
);
1833 sb_add_string (out
, buffer
);
1835 sb_kill (&stringout
);
1844 doinstr (idx
, in
, out
)
1858 idx
= skip_openp (idx
, in
);
1859 idx
= get_and_process (idx
, in
, &string
);
1860 idx
= sb_skip_comma (idx
, in
);
1861 idx
= get_and_process (idx
, in
, &search
);
1862 idx
= sb_skip_comma (idx
, in
);
1863 if (isdigit (in
->ptr
[idx
]))
1865 idx
= exp_get_abs (".instr needs absolute expresson.\n", idx
, in
, &start
);
1871 idx
= skip_closep (idx
, in
);
1873 for (i
= start
; i
< string
.len
; i
++)
1875 if (strncmp (string
.ptr
+ i
, search
.ptr
, search
.len
) == 0)
1881 sprintf (buffer
, "%d", res
);
1882 sb_add_string (out
, buffer
);
1890 dosubstr (idx
, in
, out
)
1900 idx
= skip_openp (idx
, in
);
1901 idx
= get_and_process (idx
, in
, &string
);
1902 idx
= sb_skip_comma (idx
, in
);
1903 idx
= exp_get_abs ("need absolute position.\n", idx
, in
, &pos
);
1904 idx
= sb_skip_comma (idx
, in
);
1905 idx
= exp_get_abs ("need absolute length.\n", idx
, in
, &len
);
1906 idx
= skip_closep (idx
, in
);
1909 if (len
< 0 || pos
< 0 ||
1911 || pos
+ len
> string
.len
)
1913 sb_add_string (out
, " ");
1917 sb_add_char (out
, '"');
1920 sb_add_char (out
, string
.ptr
[pos
++]);
1923 sb_add_char (out
, '"');
1929 /* scan line, change tokens in the hash table to their replacements */
1931 process_assigns (idx
, in
, buf
)
1936 while (idx
< in
->len
)
1939 if (in
->ptr
[idx
] == '\\'
1940 && in
->ptr
[idx
+ 1] == '&')
1942 idx
= condass_lookup_name (in
, idx
+ 2, buf
, 1);
1944 else if (in
->ptr
[idx
] == '\\'
1945 && in
->ptr
[idx
+ 1] == '$')
1947 idx
= condass_lookup_name (in
, idx
+ 2, buf
, 0);
1949 else if (idx
+ 3 < in
->len
1950 && in
->ptr
[idx
] == '.'
1951 && in
->ptr
[idx
+ 1] == 'L'
1952 && in
->ptr
[idx
+ 2] == 'E'
1953 && in
->ptr
[idx
+ 3] == 'N')
1954 idx
= dolen (idx
+ 4, in
, buf
);
1955 else if (idx
+ 6 < in
->len
1956 && in
->ptr
[idx
] == '.'
1957 && in
->ptr
[idx
+ 1] == 'I'
1958 && in
->ptr
[idx
+ 2] == 'N'
1959 && in
->ptr
[idx
+ 3] == 'S'
1960 && in
->ptr
[idx
+ 4] == 'T'
1961 && in
->ptr
[idx
+ 5] == 'R')
1962 idx
= doinstr (idx
+ 6, in
, buf
);
1963 else if (idx
+ 7 < in
->len
1964 && in
->ptr
[idx
] == '.'
1965 && in
->ptr
[idx
+ 1] == 'S'
1966 && in
->ptr
[idx
+ 2] == 'U'
1967 && in
->ptr
[idx
+ 3] == 'B'
1968 && in
->ptr
[idx
+ 4] == 'S'
1969 && in
->ptr
[idx
+ 5] == 'T'
1970 && in
->ptr
[idx
+ 6] == 'R')
1971 idx
= dosubstr (idx
+ 7, in
, buf
);
1972 else if (ISFIRSTCHAR (in
->ptr
[idx
]))
1974 /* may be a simple name subsitution, see if we have a word */
1977 while (cur
< in
->len
1978 && (ISNEXTCHAR (in
->ptr
[cur
])))
1982 sb_add_buffer (&acc
, in
->ptr
+ idx
, cur
- idx
);
1983 ptr
= hash_lookup (&assign_hash_table
, &acc
);
1986 /* Found a definition for it */
1987 sb_add_sb (buf
, &ptr
->value
.s
);
1991 /* No definition, just copy the word */
1992 sb_add_sb (buf
, &acc
);
1999 sb_add_char (buf
, in
->ptr
[idx
++]);
2005 get_and_process (idx
, in
, out
)
2012 idx
= get_any_string (idx
, in
, &t
, 1, 0);
2013 process_assigns (0, &t
, out
);
2034 more
= get_line (&line
);
2037 /* Find any label and pseudo op that we're intested in */
2042 fprintf (outfile
, "\n");
2046 l
= grab_label (&line
, &label_in
);
2050 /* Munge any label */
2053 process_assigns (0, &label_in
, &label
);
2056 if (line
.ptr
[l
] == ':')
2058 while (ISWHITE (line
.ptr
[l
]) && l
< line
.len
)
2063 if (process_pseudo_op (l
, &line
, &acc
))
2069 else if (condass_on ())
2071 if (macro_op (l
, &line
))
2081 fprintf (outfile
, "%s:\t", sb_name (&label
));
2084 fprintf (outfile
, "\t");
2086 process_assigns (l
, &line
, &t1
);
2088 change_base (0, &t1
, &t2
);
2089 fprintf (outfile
, "%s\n", sb_name (&t2
));
2095 /* Only a label on this line */
2096 if (label
.len
&& condass_on())
2098 fprintf (outfile
, "%s:\n", sb_name (&label
));
2106 more
= get_line (&line
);
2110 WARNING ((stderr
, "END missing from end of file.\n"));
2118 free_old_entry (ptr
)
2123 if (ptr
->type
== hash_string
)
2124 sb_kill(&ptr
->value
.s
);
2128 /* name: .ASSIGNA <value> */
2131 do_assigna (idx
, in
)
2139 process_assigns (idx
, in
, &tmp
);
2140 idx
= exp_get_abs (".ASSIGNA needs constant expression argument.\n", 0, &tmp
, &val
);
2144 ERROR ((stderr
, ".ASSIGNA without label.\n"));
2148 hash_entry
*ptr
= hash_create (&vars
, &label
);
2149 free_old_entry (ptr
);
2150 ptr
->type
= hash_integer
;
2156 /* name: .ASSIGNC <string> */
2159 do_assignc (idx
, in
)
2165 idx
= getstring (idx
, in
, &acc
);
2169 ERROR ((stderr
, ".ASSIGNS without label.\n"));
2173 hash_entry
*ptr
= hash_create (&vars
, &label
);
2174 free_old_entry (ptr
);
2175 ptr
->type
= hash_string
;
2176 sb_new (&ptr
->value
.s
);
2177 sb_add_sb (&ptr
->value
.s
, &acc
);
2183 /* name: .REG (reg) */
2190 /* remove reg stuff from inside parens */
2192 idx
= skip_openp (idx
, in
);
2194 while (idx
< in
->len
&& in
->ptr
[idx
] != ')')
2196 sb_add_char (&what
, in
->ptr
[idx
]);
2199 hash_add_to_string_table (&assign_hash_table
, &label
, &what
, 1);
2205 condass_lookup_name (inbuf
, idx
, out
, warn
)
2213 sb_new (&condass_acc
);
2215 while (idx
< inbuf
->len
2216 && ISNEXTCHAR (inbuf
->ptr
[idx
]))
2218 sb_add_char (&condass_acc
, inbuf
->ptr
[idx
++]);
2221 if (inbuf
->ptr
[idx
] == '\'')
2223 ptr
= hash_lookup (&vars
, &condass_acc
);
2230 WARNING ((stderr
, "Can't find preprocessor variable %s.\n", sb_name (&condass_acc
)));
2234 sb_add_string (out
, "0");
2239 if (ptr
->type
== hash_integer
)
2242 sprintf (buffer
, "%d", ptr
->value
.i
);
2243 sb_add_string (out
, buffer
);
2247 sb_add_sb (out
, &ptr
->value
.s
);
2250 sb_kill (&condass_acc
);
2263 whatcond (idx
, in
, val
)
2270 idx
= sb_skip_white (idx
, in
);
2272 if (p
[0] == 'E' && p
[1] == 'Q')
2274 else if (p
[0] == 'N' && p
[1] == 'E')
2276 else if (p
[0] == 'L' && p
[1] == 'T')
2278 else if (p
[0] == 'L' && p
[1] == 'E')
2280 else if (p
[0] == 'G' && p
[1] == 'T')
2282 else if (p
[0] == 'G' && p
[1] == 'E')
2286 ERROR ((stderr
, "Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n"));
2289 idx
= sb_skip_white (idx
+ 2, in
);
2306 idx
= sb_skip_white (idx
, in
);
2308 if (in
->ptr
[idx
] == '"')
2312 /* This is a string comparision */
2313 idx
= getstring (idx
, in
, &acc_a
);
2314 idx
= whatcond (idx
, in
, &cond
);
2315 idx
= getstring (idx
, in
, &acc_b
);
2316 same
= acc_a
.len
== acc_b
.len
&& (strncmp (acc_a
.ptr
, acc_b
.ptr
, acc_a
.len
) == 0);
2318 if (cond
!= EQ
&& cond
!= NE
)
2320 ERROR ((stderr
, "Comparison operator for strings must be EQ or NE\n"));
2324 res
= cond
== EQ
&& same
;
2327 /* This is a numeric expression */
2332 idx
= exp_get_abs ("Conditional operator must have absolute operands.\n", idx
, in
, &vala
);
2333 idx
= whatcond (idx
, in
, &cond
);
2334 idx
= sb_skip_white (idx
, in
);
2335 if (in
->ptr
[idx
] == '"')
2337 WARNING ((stderr
, "String compared against expression.\n"));
2342 idx
= exp_get_abs ("Conditional operator must have absolute operands.\n", idx
, in
, &valb
);
2382 if (ifi
>= IFNESTING
)
2384 FATAL ((stderr
, "AIF nesting unreasonable.\n"));
2387 ifstack
[ifi
].on
= ifstack
[ifi
-1].on
? istrue (idx
, in
) : 0;
2388 ifstack
[ifi
].hadelse
= 0;
2396 ifstack
[ifi
].on
= ifstack
[ifi
-1].on
? !ifstack
[ifi
].on
: 0;
2397 if (ifstack
[ifi
].hadelse
)
2399 ERROR ((stderr
, "Multiple AELSEs in AIF.\n"));
2401 ifstack
[ifi
].hadelse
= 1;
2415 ERROR ((stderr
, "AENDI without AIF.\n"));
2422 return ifstack
[ifi
].on
;
2426 /* Read input lines till we get to a TO string.
2427 Increase nesting depth if we geta FROM string.
2428 Put the results into sb at PTR. */
2431 buffer_and_nest (from
, to
, ptr
)
2436 int from_len
= strlen (from
);
2437 int to_len
= strlen (to
);
2439 int line_start
= ptr
->len
;
2440 int line
= linecount ();
2442 int more
= get_line (ptr
);
2446 /* Try and find the first pseudo op on the line */
2451 /* With normal syntax we can suck what we want till we get to the dot.
2452 With the alternate, labels have to start in the first column, since
2453 we cant tell what's a label and whats a pseudoop */
2455 /* Skip leading whitespace */
2457 && ISWHITE (ptr
->ptr
[i
]))
2460 /* Skip over a label */
2462 && ISNEXTCHAR (ptr
->ptr
[i
]))
2467 && ptr
->ptr
[i
] == ':')
2471 /* Skip trailing whitespace */
2473 && ISWHITE (ptr
->ptr
[i
]))
2476 if (i
< ptr
->len
&& (ptr
->ptr
[i
] == '.'
2479 if (ptr
->ptr
[i
] == '.')
2481 if (strncmp (ptr
->ptr
+ i
, from
, from_len
) == 0)
2483 if (strncmp (ptr
->ptr
+ i
, to
, to_len
) == 0)
2488 /* Reset the string to not include the ending rune */
2489 ptr
->len
= line_start
;
2495 /* Add a CR to the end and keep running */
2496 sb_add_char (ptr
, '\n');
2497 line_start
= ptr
->len
;
2498 more
= get_line (ptr
);
2503 FATAL ((stderr
, "End of file whilst inside %s, started on line %d.\n", from
, line
));
2511 ERROR ((stderr
, "AENDR without a AREPEAT.\n"));
2530 process_assigns (idx
, in
, &exp
);
2531 doit
= istrue (0, &exp
);
2533 buffer_and_nest ("AWHILE", "AENDW", &sub
);
2548 int index
= include_next_index ();
2552 sb_add_sb (©
, &sub
);
2553 sb_add_sb (©
, in
);
2554 sb_add_string (©
, "\n");
2555 sb_add_sb (©
, &sub
);
2556 sb_add_string (©
, "\t.AENDW\n");
2557 /* Push another WHILE */
2558 include_buf (&exp
, ©
, include_while
, index
);
2571 ERROR ((stderr
, "AENDW without a AENDW.\n"));
2577 Pop things off the include stack until the type and index changes */
2582 include_type type
= sp
->type
;
2583 if (type
== include_repeat
2584 || type
== include_while
2585 || type
== include_macro
)
2587 int index
= sp
->index
;
2589 while (sp
->index
== index
2590 && sp
->type
== type
)
2600 do_arepeat (idx
, in
)
2604 sb exp
; /* buffer with expression in it */
2605 sb copy
; /* expanded repeat block */
2606 sb sub
; /* contents of AREPEAT */
2612 process_assigns (idx
, in
, &exp
);
2613 idx
= exp_get_abs ("AREPEAT must have absolute operand.\n", 0, &exp
, &rc
);
2614 buffer_and_nest ("AREPEAT", "AENDR", &sub
);
2617 /* Push back the text following the repeat, and another repeat block
2628 int index
= include_next_index ();
2629 sb_add_sb (©
, &sub
);
2632 sprintf (buffer
, "\t.AREPEAT %d\n", rc
- 1);
2633 sb_add_string (©
, buffer
);
2634 sb_add_sb (©
, &sub
);
2635 sb_add_string (©
, " .AENDR\n");
2638 include_buf (&exp
, ©
, include_repeat
, index
);
2650 ERROR ((stderr
, ".ENDM without a matching .MACRO.\n"));
2654 /* MARRO PROCESSING */
2657 hash_table macro_table
;
2667 do_formals (macro
, idx
, in
)
2672 formal_entry
**p
= ¯o
->formals
;
2673 macro
->formal_count
= 0;
2674 hash_new_table (5, ¯o
->formal_hash
);
2675 while (idx
< in
->len
)
2677 formal_entry
*formal
;
2679 formal
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
2681 sb_new (&formal
->name
);
2682 sb_new (&formal
->def
);
2683 sb_new (&formal
->actual
);
2685 idx
= sb_skip_white (idx
, in
);
2686 idx
= get_token (idx
, in
, &formal
->name
);
2687 if (formal
->name
.len
== 0)
2689 idx
= sb_skip_white (idx
, in
);
2690 if (formal
->name
.len
)
2692 /* This is a formal */
2693 if (idx
< in
->len
&& in
->ptr
[idx
] == '=')
2696 idx
= get_any_string (idx
+ 1, in
, &formal
->def
, 1, 0);
2701 /* Add to macro's hash table */
2703 hash_entry
*p
= hash_create (¯o
->formal_hash
, &formal
->name
);
2704 p
->type
= hash_formal
;
2705 p
->value
.f
= formal
;
2708 formal
->index
= macro
->formal_count
;
2709 idx
= sb_skip_comma (idx
, in
);
2710 macro
->formal_count
++;
2717 /* Parse off LOCAL n1, n2,... Invent a label name for it */
2720 do_local (idx
, line
)
2730 idx
= sb_skip_white (idx
, line
);
2731 while (!eol(idx
, line
))
2736 sprintf(subs
, "LL%04x", ln
);
2737 idx
= get_token(idx
, line
, &acc
);
2738 sb_add_string (&sub
, subs
);
2739 hash_add_to_string_table (&assign_hash_table
, &acc
, &sub
, 1);
2740 idx
= sb_skip_comma (idx
, line
);
2755 macro
= (macro_entry
*) xmalloc (sizeof (macro_entry
));
2756 sb_new (¯o
->sub
);
2759 macro
->formal_count
= 0;
2762 idx
= sb_skip_white (idx
, in
);
2763 buffer_and_nest ("MACRO", "ENDM", ¯o
->sub
);
2767 sb_add_sb (&name
, &label
);
2768 if (in
->ptr
[idx
] == '(')
2770 /* It's the label: MACRO (formals,...) sort */
2771 idx
= do_formals (macro
, idx
+ 1, in
);
2772 if (in
->ptr
[idx
] != ')')
2773 ERROR ((stderr
, "Missing ) after formals.\n"));
2776 /* It's the label: MACRO formals,... sort */
2777 idx
= do_formals (macro
, idx
, in
);
2782 idx
= get_token (idx
, in
, &name
);
2783 idx
= sb_skip_white (idx
, in
);
2784 idx
= do_formals (macro
, idx
, in
);
2787 /* and stick it in the macro hash table */
2788 hash_create (¯o_table
, &name
)->value
.m
= macro
;
2793 get_token (idx
, in
, name
)
2799 && ISFIRSTCHAR (in
->ptr
[idx
]))
2801 sb_add_char (name
, in
->ptr
[idx
++]);
2802 while (idx
< in
->len
2803 && ISNEXTCHAR (in
->ptr
[idx
]))
2805 sb_add_char (name
, in
->ptr
[idx
++]);
2808 /* Ignore trailing & */
2809 if (alternate
&& idx
< in
->len
&& in
->ptr
[idx
] == '&')
2814 /* Scan a token, but stop if a ' is seen */
2816 get_apost_token (idx
, in
, name
, kind
)
2822 idx
= get_token (idx
, in
, name
);
2823 if (idx
< in
->len
&& in
->ptr
[idx
] == kind
)
2829 sub_actual (src
, in
, t
, m
, kind
, out
, copyifnotthere
)
2838 /* This is something to take care of */
2840 src
= get_apost_token (src
, in
, t
, kind
);
2841 /* See if it's in the macro's hash table */
2842 ptr
= hash_lookup (&m
->formal_hash
, t
);
2845 if (ptr
->value
.f
->actual
.len
)
2847 sb_add_sb (out
, &ptr
->value
.f
->actual
);
2851 sb_add_sb (out
, &ptr
->value
.f
->def
);
2854 else if (copyifnotthere
)
2860 sb_add_char (out
, '\\');
2868 macro_expand (name
, idx
, in
, m
)
2878 int is_positional
= 0;
2884 /* Reset any old value the actuals may have */
2885 for (f
= m
->formals
; f
; f
= f
->next
)
2886 sb_reset (&f
->actual
);
2888 /* Peel off the actuals and store them away in the hash tables' actuals */
2889 while (!eol(idx
, in
))
2892 idx
= sb_skip_white (idx
, in
);
2893 /* Look and see if it's a positional or keyword arg */
2895 while (scan
< in
->len
2896 && !ISSEP (in
->ptr
[scan
])
2897 && (!alternate
&& in
->ptr
[scan
] != '='))
2899 if (scan
< in
->len
&& (!alternate
) && in
->ptr
[scan
] == '=')
2904 ERROR ((stderr
, "Can't mix positional and keyword arguments.\n"));
2907 /* This is a keyword arg, fetch the formal name and
2908 then the actual stuff */
2910 idx
= get_token (idx
, in
, &t
);
2911 if (in
->ptr
[idx
] != '=')
2912 ERROR ((stderr
, "confused about formal params.\n"));
2914 /* Lookup the formal in the macro's list */
2915 ptr
= hash_lookup (&m
->formal_hash
, &t
);
2918 ERROR ((stderr
, "MACRO formal argument %s does not exist.\n", sb_name (&t
)));
2923 /* Insert this value into the right place */
2924 sb_reset (&ptr
->value
.f
->actual
);
2925 idx
= get_any_string (idx
+ 1, in
, &ptr
->value
.f
->actual
, 0, 0);
2930 /* This is a positional arg */
2934 ERROR ((stderr
, "Can't mix positional and keyword arguments.\n"));
2939 ERROR ((stderr
, "Too many positional arguments.\n"));
2943 sb_reset (&f
->actual
);
2944 idx
= get_any_string (idx
, in
, &f
->actual
, 1, 0);
2947 idx
= sb_skip_comma (idx
, in
);
2950 /* Copy the stuff from the macro buffer into a safe place and substitute any args */
2958 while (src
< in
->len
)
2960 if (in
->ptr
[src
] == '&')
2963 src
= sub_actual (src
+ 1, in
, &t
, m
, '&', &out
, 0);
2965 else if (in
->ptr
[src
] == '\\')
2968 if (in
->ptr
[src
] == comment_char
)
2970 /* This is a comment, just drop the rest of the line */
2971 while (src
< in
->len
2972 && in
->ptr
[src
] != '\n')
2976 else if (in
->ptr
[src
] == '(')
2978 /* Sub in till the next ')' literally */
2980 while (src
< in
->len
&& in
->ptr
[src
] != ')')
2982 sb_add_char (&out
, in
->ptr
[src
++]);
2984 if (in
->ptr
[src
] == ')')
2987 ERROR ((stderr
, "Missplaced ).\n"));
2989 else if (in
->ptr
[src
] == '@')
2991 /* Sub in the macro invocation number */
2995 sprintf (buffer
, "%05d", number
);
2996 sb_add_string (&out
, buffer
);
2998 else if (in
->ptr
[src
] == '&')
3000 /* This is a preprocessor variable name, we don't do them
3002 sb_add_char (&out
, '\\');
3003 sb_add_char (&out
, '&');
3009 src
= sub_actual (src
, in
, &t
, m
, '\'', &out
, 0);
3012 else if (ISFIRSTCHAR (in
->ptr
[src
]) && alternate
)
3015 src
= sub_actual (src
, in
, &t
, m
, '\'', &out
, 1);
3017 else if (ISCOMMENTCHAR (in
->ptr
[src
])
3018 && src
+ 1 < in
->len
3019 && ISCOMMENTCHAR (in
->ptr
[src
+1])
3022 /* Two comment chars in a row cause the rest of the line to be dropped */
3023 while (src
< in
->len
&& in
->ptr
[src
] != '\n')
3026 else if (in
->ptr
[src
] == '"')
3029 sb_add_char (&out
, in
->ptr
[src
++]);
3033 sb_add_char (&out
, in
->ptr
[src
++]);
3036 include_buf (name
, &out
, include_macro
, include_next_index ());
3049 /* The macro name must be the first thing on the line */
3055 idx
= get_token (idx
, in
, &name
);
3059 /* Got a name, look it up */
3061 ptr
= hash_lookup (¯o_table
, &name
);
3065 /* It's in the table, copy out the stuff and convert any macro args */
3066 macro_expand (&name
, idx
, in
, ptr
->value
.m
);
3078 /* STRING HANDLING */
3081 getstring (idx
, in
, acc
)
3086 idx
= sb_skip_white (idx
, in
);
3088 while (idx
< in
->len
3089 && (in
->ptr
[idx
] == '"'
3090 || in
->ptr
[idx
] == '<'
3091 || (in
->ptr
[idx
] == '\'' && alternate
)))
3093 if (in
->ptr
[idx
] == '<')
3099 while ((in
->ptr
[idx
] != '>' || nest
)
3102 if (in
->ptr
[idx
] == '!')
3105 sb_add_char (acc
, in
->ptr
[idx
++]);
3108 if (in
->ptr
[idx
] == '>')
3110 if (in
->ptr
[idx
] == '<')
3112 sb_add_char (acc
, in
->ptr
[idx
++]);
3120 idx
= exp_get_abs ("Character code in string must be absolute expression.\n",
3122 sb_add_char (acc
, code
);
3124 if (in
->ptr
[idx
] != '>')
3125 ERROR ((stderr
, "Missing > for character code.\n"));
3129 else if (in
->ptr
[idx
] == '"' || in
->ptr
[idx
] == '\'')
3131 char tchar
= in
->ptr
[idx
];
3133 while (idx
< in
->len
)
3135 if (alternate
&& in
->ptr
[idx
] == '!')
3138 sb_add_char (acc
, in
->ptr
[idx
++]);
3141 if (in
->ptr
[idx
] == tchar
)
3144 if (idx
>= in
->len
|| in
->ptr
[idx
] != tchar
)
3147 sb_add_char (acc
, in
->ptr
[idx
]);
3157 /* .SDATA[C|Z] <string> */
3161 do_sdata (idx
, in
, type
)
3170 fprintf (outfile
, ".byte\t");
3172 while (!eol (idx
, in
))
3176 idx
= sb_skip_white (idx
, in
);
3177 while (!eol (idx
, in
))
3179 pidx
= idx
= get_any_string (idx
, in
, &acc
, 0, 1);
3184 ERROR ((stderr
, "string for SDATAC longer than 255 characters (%d).\n", acc
.len
));
3186 fprintf (outfile
, "%d", acc
.len
);
3190 for (i
= 0; i
< acc
.len
; i
++)
3194 fprintf (outfile
, ",");
3196 fprintf (outfile
, "%d", acc
.ptr
[i
]);
3203 fprintf (outfile
, ",");
3204 fprintf (outfile
, "0");
3206 idx
= sb_skip_comma (idx
, in
);
3207 if (idx
== pidx
) break;
3209 if (!alternate
&& in
->ptr
[idx
] != ',' && idx
!= in
->len
)
3211 fprintf (outfile
, "\n");
3212 ERROR ((stderr
, "illegal character in SDATA line (0x%x).\n", in
->ptr
[idx
]));
3218 fprintf (outfile
, "\n");
3221 /* .SDATAB <count> <string> */
3233 idx
= exp_get_abs ("Must have absolute SDATAB repeat count.\n", idx
, in
, &repeat
);
3236 ERROR ((stderr
, "Must have positive SDATAB repeat count (%d).\n", repeat
));
3240 idx
= sb_skip_comma (idx
, in
);
3241 idx
= getstring (idx
, in
, &acc
);
3243 for (i
= 0; i
< repeat
; i
++)
3246 fprintf (outfile
, "\t");
3247 fprintf (outfile
, ".byte\t");
3249 fprintf (outfile
, "\n");
3259 FILE *newone
= fopen (name
, "r");
3263 if (isp
== MAX_INCLUDES
)
3264 FATAL ((stderr
, "Unreasonable include depth (%d).\n", isp
));
3267 sp
->handle
= newone
;
3270 sb_add_string (&sp
->name
, name
);
3273 sp
->pushback_index
= 0;
3274 sp
->type
= include_file
;
3276 sb_new (&sp
->pushback
);
3281 do_include (idx
, in
)
3288 idx
= getstring (idx
, in
, &t
);
3289 text
= sb_name (&t
);
3290 if (!new_file (text
))
3292 FATAL ((stderr
, "Can't open include file `%s'.\n", text
));
3300 if (sp
!= include_stack
)
3303 fclose (sp
->handle
);
3308 /* Get the next character from the include stack. If there's anything
3309 in the pushback buffer, take that first. If we're at eof, pop from
3310 the stack and try again. Keep the linecount up to date. */
3317 if (sp
->pushback
.len
!= sp
->pushback_index
)
3319 r
= (char) (sp
->pushback
.ptr
[sp
->pushback_index
++]);
3320 /* When they've all gone, reset the pointer */
3321 if (sp
->pushback_index
== sp
->pushback
.len
)
3323 sp
->pushback
.len
= 0;
3324 sp
->pushback_index
= 0;
3327 else if (sp
->handle
)
3329 r
= getc (sp
->handle
);
3334 if (r
== EOF
&& isp
)
3338 while (r
== EOF
&& isp
)
3356 return sp
->linecount
;
3360 include_next_index ()
3364 && index
> MAX_REASONABLE
)
3365 FATAL ((stderr
, "Unreasonable expansion (-u turns off check).\n"));
3370 /* Initialize the chartype vector. */
3376 for (x
= 0; x
< 256; x
++)
3378 if (isalpha (x
) || x
== '_' || x
== '$')
3379 chartype
[x
] |= FIRSTBIT
;
3381 if (isdigit (x
) || isalpha (x
) || x
== '_' || x
== '$')
3382 chartype
[x
] |= NEXTBIT
;
3384 if (x
== ' ' || x
== '\t' || x
== ',' || x
== '"' || x
== ';'
3385 || x
== '"' || x
== '<' || x
== '>' || x
== ')' || x
== '(')
3386 chartype
[x
] |= SEPBIT
;
3388 if (x
== 'b' || x
== 'B'
3389 || x
== 'q' || x
== 'Q'
3390 || x
== 'h' || x
== 'H'
3391 || x
== 'd' || x
== 'D')
3392 chartype
[x
] |= BASEBIT
;
3394 if (x
== ' ' || x
== '\t')
3395 chartype
[x
] |= WHITEBIT
;
3397 if (x
== comment_char
)
3398 chartype
[x
] |= COMMENTBIT
;
3404 /* What to do with all the keywords */
3405 #define PROCESS 0x1000 /* Run substitution over the line */
3406 #define LAB 0x2000 /* Spit out the label */
3408 #define K_EQU PROCESS|1
3409 #define K_ASSIGN PROCESS|2
3410 #define K_REG PROCESS|3
3411 #define K_ORG PROCESS|4
3412 #define K_RADIX PROCESS|5
3413 #define K_DATA LAB|PROCESS|6
3414 #define K_DATAB LAB|PROCESS|7
3415 #define K_SDATA LAB|PROCESS|8
3416 #define K_SDATAB LAB|PROCESS|9
3417 #define K_SDATAC LAB|PROCESS|10
3418 #define K_SDATAZ LAB|PROCESS|11
3419 #define K_RES LAB|PROCESS|12
3420 #define K_SRES LAB|PROCESS|13
3421 #define K_SRESC LAB|PROCESS|14
3422 #define K_SRESZ LAB|PROCESS|15
3423 #define K_EXPORT LAB|PROCESS|16
3424 #define K_GLOBAL LAB|PROCESS|17
3425 #define K_PRINT LAB|PROCESS|19
3426 #define K_FORM LAB|PROCESS|20
3427 #define K_HEADING LAB|PROCESS|21
3428 #define K_PAGE LAB|PROCESS|22
3429 #define K_IMPORT LAB|PROCESS|23
3430 #define K_PROGRAM LAB|PROCESS|24
3431 #define K_END PROCESS|25
3432 #define K_INCLUDE PROCESS|26
3433 #define K_IGNORED PROCESS|27
3434 #define K_ASSIGNA PROCESS|28
3435 #define K_ASSIGNC 29
3436 #define K_AIF PROCESS|30
3437 #define K_AELSE PROCESS|31
3438 #define K_AENDI PROCESS|32
3439 #define K_AREPEAT PROCESS|33
3440 #define K_AENDR PROCESS|34
3442 #define K_AENDW PROCESS|36
3444 #define K_MACRO PROCESS|38
3446 #define K_ALIGN PROCESS|LAB|40
3447 #define K_ALTERNATE 41
3448 #define K_DB LAB|PROCESS|42
3449 #define K_DW LAB|PROCESS|43
3450 #define K_DL LAB|PROCESS|44
3462 { "EQU", K_EQU
, 0 },
3463 { "ALTERNATE", K_ALTERNATE
, 0 },
3464 { "ASSIGN", K_ASSIGN
, 0 },
3465 { "REG", K_REG
, 0 },
3466 { "ORG", K_ORG
, 0 },
3467 { "RADIX", K_RADIX
, 0 },
3468 { "DATA", K_DATA
, 0 },
3472 { "DATAB", K_DATAB
, 0 },
3473 { "SDATA", K_SDATA
, 0 },
3474 { "SDATAB", K_SDATAB
, 0 },
3475 { "SDATAZ", K_SDATAZ
, 0 },
3476 { "SDATAC", K_SDATAC
, 0 },
3477 { "RES", K_RES
, 0 },
3478 { "SRES", K_SRES
, 0 },
3479 { "SRESC", K_SRESC
, 0 },
3480 { "SRESZ", K_SRESZ
, 0 },
3481 { "EXPORT", K_EXPORT
, 0 },
3482 { "GLOBAL", K_GLOBAL
, 0 },
3483 { "PRINT", K_PRINT
, 0 },
3484 { "FORM", K_FORM
, 0 },
3485 { "HEADING", K_HEADING
, 0 },
3486 { "PAGE", K_PAGE
, 0 },
3487 { "PROGRAM", K_IGNORED
, 0 },
3488 { "END", K_END
, 0 },
3489 { "INCLUDE", K_INCLUDE
, 0 },
3490 { "ASSIGNA", K_ASSIGNA
, 0 },
3491 { "ASSIGNC", K_ASSIGNC
, 0 },
3492 { "AIF", K_AIF
, 0 },
3493 { "AELSE", K_AELSE
, 0 },
3494 { "AENDI", K_AENDI
, 0 },
3495 { "AREPEAT", K_AREPEAT
, 0 },
3496 { "AENDR", K_AENDR
, 0 },
3497 { "EXITM", K_EXITM
, 0 },
3498 { "MACRO", K_MACRO
, 0 },
3499 { "ENDM", K_ENDM
, 0 },
3500 { "AWHILE", K_AWHILE
, 0 },
3501 { "ALIGN", K_ALIGN
, 0 },
3502 { "AENDW", K_AENDW
, 0 },
3503 { "ALTERNATE", K_ALTERNATE
, 0 },
3504 { "LOCAL", K_LOCAL
, 0 },
3508 /* Look for a pseudo op on the line. If one's there then call
3512 process_pseudo_op (idx
, line
, acc
)
3519 if (line
->ptr
[idx
] == '.' || alternate
)
3521 /* Scan forward and find pseudo name */
3527 if (line
->ptr
[idx
] == '.')
3529 in
= line
->ptr
+ idx
;
3534 while (idx
< line
->len
&& *e
&& ISFIRSTCHAR (*e
))
3536 sb_add_char (acc
, *e
);
3541 ptr
= hash_lookup (&keyword_hash_table
, acc
);
3546 /* This one causes lots of pain when trying to preprocess
3548 WARNING ((stderr
, "Unrecognised pseudo op `%s'.\n", sb_name (acc
)));
3552 if (ptr
->value
.i
& LAB
)
3553 { /* output the label */
3556 fprintf (outfile
, "%s:\t", sb_name (&label
));
3559 fprintf (outfile
, "\t");
3562 if (ptr
->value
.i
& PROCESS
)
3564 /* Polish the rest of the line before handling the pseudo op */
3566 strip_comments(line
);
3569 process_assigns (idx
, line
, acc
);
3571 change_base (0, acc
, line
);
3576 switch (ptr
->value
.i
)
3592 switch (ptr
->value
.i
)
3604 ERROR ((stderr
, "ORG command not allowed.\n"));
3610 do_data (idx
, line
, 1);
3613 do_data (idx
, line
, 2);
3616 do_data (idx
, line
, 4);
3619 do_data (idx
, line
, 0);
3622 do_datab (idx
, line
);
3625 do_sdata (idx
, line
, 0);
3628 do_sdatab (idx
, line
);
3631 do_sdata (idx
, line
, 'c');
3634 do_sdata (idx
, line
, 'z');
3637 do_assign (1, 0, line
);
3643 do_arepeat (idx
, line
);
3649 do_awhile (idx
, line
);
3655 do_assign (0, idx
, line
);
3658 do_align (idx
, line
);
3661 do_res (idx
, line
, 0);
3664 do_res (idx
, line
, 's');
3667 do_include (idx
, line
);
3670 do_local (idx
, line
);
3673 do_macro (idx
, line
);
3679 do_res (idx
, line
, 'c');
3682 do_print (idx
, line
);
3685 do_form (idx
, line
);
3688 do_heading (idx
, line
);
3700 do_res (idx
, line
, 'z');
3708 do_assigna (idx
, line
);
3711 do_assignc (idx
, line
);
3727 /* Build the keyword hash table - put each keyword in the table twice,
3728 once upper and once lower case.*/
3735 for (i
= 0; kinfo
[i
].name
; i
++)
3740 sb_add_string (&label
, kinfo
[i
].name
);
3742 hash_add_to_int_table (&keyword_hash_table
, &label
, kinfo
[i
].code
);
3745 for (j
= 0; kinfo
[i
].name
[j
]; j
++)
3746 sb_add_char (&label
, kinfo
[i
].name
[j
] - 'A' + 'a');
3747 hash_add_to_int_table (&keyword_hash_table
, &label
, kinfo
[i
].code
);
3773 sb_add_char (&value
, *string
);
3776 exp_get_abs ("Invalid expression on command line.\n", 0, &value
, &res
);
3780 sb_add_char (&label
, *string
);
3785 ptr
= hash_create (&vars
, &label
);
3786 free_old_entry (ptr
);
3787 ptr
->type
= hash_integer
;
3793 /* The list of long options. */
3794 static struct option long_options
[] =
3796 { "alternate", no_argument
, 0, 'a' },
3797 { "commentchar", required_argument
, 0, 'c' },
3798 { "copysource", no_argument
, 0, 's' },
3799 { "debug", no_argument
, 0, 'd' },
3800 { "help", no_argument
, 0, 'h' },
3801 { "output", required_argument
, 0, 'o' },
3802 { "print", no_argument
, 0, 'p' },
3803 { "unreasonable", no_argument
, 0, 'u' },
3804 { "version", no_argument
, 0, 'v' },
3805 { "define", required_argument
, 0, 'd' },
3806 { NULL
, no_argument
, 0, 0 }
3809 /* Show a usage message and exit. */
3811 show_usage (file
, status
)
3817 [-a] [--alternate] enter alternate macro mode\n\
3818 [-c char] [--commentchar char] change the comment character from !\n\
3819 [-d] [--debug] print some debugging info\n\
3820 [-h] [--help] print this message\n\
3821 [-o out] [--output out] set the output file\n\
3822 [-p] [--print] print line numbers\n\
3823 [-s] [--copysource] copy source through as comments \n\
3824 [-u] [--unreasonable] allow unreasonable nesting\n\
3825 [-v] [--version] print the program version\n\
3826 [-Dname=value] create preprocessor variable called name, with value\n\
3827 [in-file]\n", program_name
);
3831 /* Display a help message and exit. */
3835 printf ("%s: Gnu Assembler Macro Preprocessor\n",
3837 show_usage (stdout
, 0);
3854 program_name
= argv
[0];
3855 xmalloc_set_program_name (program_name
);
3857 hash_new_table (101, ¯o_table
);
3858 hash_new_table (101, &keyword_hash_table
);
3859 hash_new_table (101, &assign_hash_table
);
3860 hash_new_table (101, &vars
);
3865 while ((opt
= getopt_long (argc
, argv
, "sdhavc:upo:D:", long_options
,
3878 print_line_number
= 1;
3881 comment_char
= optarg
[0];
3899 printf ("GNU %s version %s\n", program_name
, program_version
);
3905 show_usage (stderr
, 1);
3912 outfile
= fopen (out_name
, "w");
3915 fprintf (stderr
, "%s: Can't open output file `%s'.\n",
3916 program_name
, out_name
);
3928 /* Process all the input files */
3930 while (optind
< argc
)
3932 if (new_file (argv
[optind
]))
3938 fprintf (stderr
, "%s: Can't open input file `%s'.\n",
3939 program_name
, argv
[optind
]);