f8e435388923fed121ca15fe99661133d101ef59
[deliverable/binutils-gdb.git] / gas / gasp.c
1 /* gasp.c - Gnu assembler preprocessor main program.
2 Copyright (C) 1994, 95, 96, 97, 1998 Free Software Foundation, Inc.
3
4 Written by Steve and Judy Chamberlain of Cygnus Support,
5 sac@cygnus.com
6
7 This file is part of GASP, the GNU Assembler Preprocessor.
8
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)
12 any later version.
13
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.
18
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 the Free
21 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 02111-1307, USA. */
23
24 /*
25
26 This program translates the input macros and stuff into a form
27 suitable for gas to consume.
28
29
30 gasp [-sdhau] [-c char] [-o <outfile>] <infile>*
31
32 -s copy source to output
33 -c <char> comments are started with <char> instead of !
34 -u allow unreasonable stuff
35 -p print line numbers
36 -d print debugging stats
37 -s semi colons start comments
38 -a use alternate syntax
39 Pseudo ops can start with or without a .
40 Labels have to be in first column.
41 -I specify include dir
42 Macro arg parameters subsituted by name, don't need the &.
43 String can start with ' too.
44 Strings can be surrounded by <..>
45 A %<exp> in a string evaluates the expression
46 Literal char in a string with !
47
48
49 */
50
51 #include "config.h"
52
53 #include <stdio.h>
54 #include <string.h>
55 #include <getopt.h>
56 #include <ctype.h>
57
58 #ifdef HAVE_STDLIB_H
59 #include <stdlib.h>
60 #endif
61
62 #ifdef NEED_MALLOC_DECLARATION
63 extern char *malloc ();
64 #endif
65
66 #include "ansidecl.h"
67 #include "libiberty.h"
68 #include "sb.h"
69 #include "macro.h"
70 #include "asintl.h"
71
72 char *program_version = "1.2";
73
74 /* This is normally declared in as.h, but we don't include that. We
75 need the function because other files linked with gasp.c might call
76 it. */
77 extern void as_abort PARAMS ((const char *, int, const char *));
78
79 #define MAX_INCLUDES 30 /* Maximum include depth */
80 #define MAX_REASONABLE 1000 /* Maximum number of expansions */
81
82 int unreasonable; /* -u on command line */
83 int stats; /* -d on command line */
84 int print_line_number; /* -p flag on command line */
85 int copysource; /* -c flag on command line */
86 int warnings; /* Number of WARNINGs generated so far. */
87 int errors; /* Number of ERRORs generated so far. */
88 int fatals; /* Number of fatal ERRORs generated so far (either 0 or 1). */
89 int alternate = 0; /* -a on command line */
90 int mri = 0; /* -M on command line */
91 char comment_char = '!';
92 int radix = 10; /* Default radix */
93
94 int had_end; /* Seen .END */
95
96 /* The output stream */
97 FILE *outfile;
98
99 /* the attributes of each character are stored as a bit pattern
100 chartype, which gives us quick tests. */
101
102
103 #define FIRSTBIT 1
104 #define NEXTBIT 2
105 #define SEPBIT 4
106 #define WHITEBIT 8
107 #define COMMENTBIT 16
108 #define BASEBIT 32
109 #define ISCOMMENTCHAR(x) (chartype[(unsigned char)(x)] & COMMENTBIT)
110 #define ISFIRSTCHAR(x) (chartype[(unsigned char)(x)] & FIRSTBIT)
111 #define ISNEXTCHAR(x) (chartype[(unsigned char)(x)] & NEXTBIT)
112 #define ISSEP(x) (chartype[(unsigned char)(x)] & SEPBIT)
113 #define ISWHITE(x) (chartype[(unsigned char)(x)] & WHITEBIT)
114 #define ISBASE(x) (chartype[(unsigned char)(x)] & BASEBIT)
115 static char chartype[256];
116
117
118 /* Conditional assembly uses the `ifstack'. Each aif pushes another
119 entry onto the stack, and sets the on flag if it should. The aelse
120 sets hadelse, and toggles on. An aend pops a level. We limit to
121 100 levels of nesting, not because we're facists pigs with read
122 only minds, but because more than 100 levels of nesting is probably
123 a bug in the user's macro structure. */
124
125 #define IFNESTING 100
126 struct
127 {
128 int on; /* is the level being output */
129 int hadelse; /* has an aelse been seen */
130 }
131 ifstack[IFNESTING];
132 int ifi;
133
134 /* The final and intermediate results of expression evaluation are kept in
135 exp_t's. Note that a symbol is not an sb, but a pointer into the input
136 line. It must be coped somewhere safe before the next line is read in. */
137
138 typedef struct
139 {
140 char *name;
141 int len;
142 }
143 symbol;
144
145 typedef struct
146 {
147 int value; /* constant part */
148 symbol add_symbol; /* name part */
149 symbol sub_symbol; /* name part */
150 }
151 exp_t;
152
153
154 /* Hashing is done in a pretty standard way. A hash_table has a
155 pointer to a vector of pointers to hash_entrys, and the size of the
156 vector. A hash_entry contains a union of all the info we like to
157 store in hash table. If there is a hash collision, hash_entries
158 with the same hash are kept in a chain. */
159
160 /* What the data in a hash_entry means */
161 typedef enum
162 {
163 hash_integer, /* name->integer mapping */
164 hash_string, /* name->string mapping */
165 hash_macro, /* name is a macro */
166 hash_formal /* name is a formal argument */
167 } hash_type;
168
169 typedef struct hs
170 {
171 sb key; /* symbol name */
172 hash_type type; /* symbol meaning */
173 union
174 {
175 sb s;
176 int i;
177 struct macro_struct *m;
178 struct formal_struct *f;
179 } value;
180 struct hs *next; /* next hash_entry with same hash key */
181 } hash_entry;
182
183 typedef struct
184 {
185 hash_entry **table;
186 int size;
187 } hash_table;
188
189
190 /* Structures used to store macros.
191
192 Each macro knows its name and included text. It gets built with a
193 list of formal arguments, and also keeps a hash table which points
194 into the list to speed up formal search. Each formal knows its
195 name and its default value. Each time the macro is expanded, the
196 formals get the actual values attatched to them. */
197
198 /* describe the formal arguments to a macro */
199
200 typedef struct formal_struct
201 {
202 struct formal_struct *next; /* next formal in list */
203 sb name; /* name of the formal */
204 sb def; /* the default value */
205 sb actual; /* the actual argument (changed on each expansion) */
206 int index; /* the index of the formal 0..formal_count-1 */
207 }
208 formal_entry;
209
210 /* describe the macro. */
211
212 typedef struct macro_struct
213 {
214 sb sub; /* substitution text. */
215 int formal_count; /* number of formal args. */
216 formal_entry *formals; /* pointer to list of formal_structs */
217 hash_table formal_hash; /* hash table of formals. */
218 }
219 macro_entry;
220
221 /* how we nest files and expand macros etc.
222
223 we keep a stack of of include_stack structs. each include file
224 pushes a new level onto the stack. we keep an sb with a pushback
225 too. unget chars are pushed onto the pushback sb, getchars first
226 checks the pushback sb before reading from the input stream.
227
228 small things are expanded by adding the text of the item onto the
229 pushback sb. larger items are grown by pushing a new level and
230 allocating the entire pushback buf for the item. each time
231 something like a macro is expanded, the stack index is changed. we
232 can then perform an exitm by popping all entries off the stack with
233 the same stack index. if we're being reasonable, we can detect
234 recusive expansion by checking the index is reasonably small.
235 */
236
237 typedef enum
238 {
239 include_file, include_repeat, include_while, include_macro
240 } include_type;
241
242 struct include_stack
243 {
244 sb pushback; /* current pushback stream */
245 int pushback_index; /* next char to read from stream */
246 FILE *handle; /* open file */
247 sb name; /* name of file */
248 int linecount; /* number of lines read so far */
249 include_type type;
250 int index; /* index of this layer */
251 }
252 include_stack[MAX_INCLUDES];
253
254 struct include_stack *sp;
255 #define isp (sp - include_stack)
256
257 /* Include file list */
258
259 typedef struct include_path
260 {
261 struct include_path *next;
262 sb path;
263 } include_path;
264
265 include_path *paths_head;
266 include_path *paths_tail;
267
268
269 static void quit PARAMS ((void));
270 static void hash_new_table PARAMS ((int, hash_table *));
271 static int hash PARAMS ((sb *));
272 static hash_entry *hash_create PARAMS ((hash_table *, sb *));
273 static void hash_add_to_string_table PARAMS ((hash_table *, sb *, sb *, int));
274 static void hash_add_to_int_table PARAMS ((hash_table *, sb *, int));
275 static hash_entry *hash_lookup PARAMS ((hash_table *, sb *));
276 static void checkconst PARAMS ((int, exp_t *));
277 static int sb_strtol PARAMS ((int, sb *, int, int *));
278 static int level_0 PARAMS ((int, sb *, exp_t *));
279 static int level_1 PARAMS ((int, sb *, exp_t *));
280 static int level_2 PARAMS ((int, sb *, exp_t *));
281 static int level_3 PARAMS ((int, sb *, exp_t *));
282 static int level_4 PARAMS ((int, sb *, exp_t *));
283 static int level_5 PARAMS ((int, sb *, exp_t *));
284 static int exp_parse PARAMS ((int, sb *, exp_t *));
285 static void exp_string PARAMS ((exp_t *, sb *));
286 static int exp_get_abs PARAMS ((const char *, int, sb *, int *));
287 #if 0
288 static void strip_comments PARAMS ((sb *));
289 #endif
290 static void unget PARAMS ((int));
291 static void include_buf PARAMS ((sb *, sb *, include_type, int));
292 static void include_print_where_line PARAMS ((FILE *));
293 static void include_print_line PARAMS ((FILE *));
294 static int get_line PARAMS ((sb *));
295 static int grab_label PARAMS ((sb *, sb *));
296 static void change_base PARAMS ((int, sb *, sb *));
297 static void do_end PARAMS ((sb *));
298 static void do_assign PARAMS ((int, int, sb *));
299 static void do_radix PARAMS ((sb *));
300 static int get_opsize PARAMS ((int, sb *, int *));
301 static int eol PARAMS ((int, sb *));
302 static void do_data PARAMS ((int, sb *, int));
303 static void do_datab PARAMS ((int, sb *));
304 static void do_align PARAMS ((int, sb *));
305 static void do_res PARAMS ((int, sb *, int));
306 static void do_export PARAMS ((sb *));
307 static void do_print PARAMS ((int, sb *));
308 static void do_heading PARAMS ((int, sb *));
309 static void do_page PARAMS ((void));
310 static void do_form PARAMS ((int, sb *));
311 static int get_any_string PARAMS ((int, sb *, sb *, int, int));
312 static int skip_openp PARAMS ((int, sb *));
313 static int skip_closep PARAMS ((int, sb *));
314 static int dolen PARAMS ((int, sb *, sb *));
315 static int doinstr PARAMS ((int, sb *, sb *));
316 static int dosubstr PARAMS ((int, sb *, sb *));
317 static void process_assigns PARAMS ((int, sb *, sb *));
318 static int get_and_process PARAMS ((int, sb *, sb *));
319 static void process_file PARAMS ((void));
320 static void free_old_entry PARAMS ((hash_entry *));
321 static void do_assigna PARAMS ((int, sb *));
322 static void do_assignc PARAMS ((int, sb *));
323 static void do_reg PARAMS ((int, sb *));
324 static int condass_lookup_name PARAMS ((sb *, int, sb *, int));
325 static int whatcond PARAMS ((int, sb *, int *));
326 static int istrue PARAMS ((int, sb *));
327 static void do_aif PARAMS ((int, sb *));
328 static void do_aelse PARAMS ((void));
329 static void do_aendi PARAMS ((void));
330 static int condass_on PARAMS ((void));
331 static void do_if PARAMS ((int, sb *, int));
332 static int get_mri_string PARAMS ((int, sb *, sb *, int));
333 static void do_ifc PARAMS ((int, sb *, int));
334 static void do_aendr PARAMS ((void));
335 static void do_awhile PARAMS ((int, sb *));
336 static void do_aendw PARAMS ((void));
337 static void do_exitm PARAMS ((void));
338 static void do_arepeat PARAMS ((int, sb *));
339 static void do_endm PARAMS ((void));
340 static void do_irp PARAMS ((int, sb *, int));
341 static void do_local PARAMS ((int, sb *));
342 static void do_macro PARAMS ((int, sb *));
343 static int macro_op PARAMS ((int, sb *));
344 static int getstring PARAMS ((int, sb *, sb *));
345 static void do_sdata PARAMS ((int, sb *, int));
346 static void do_sdatab PARAMS ((int, sb *));
347 static int new_file PARAMS ((const char *));
348 static void do_include PARAMS ((int, sb *));
349 static void include_pop PARAMS ((void));
350 static int get PARAMS ((void));
351 static int linecount PARAMS ((void));
352 static int include_next_index PARAMS ((void));
353 static void chartype_init PARAMS ((void));
354 static int process_pseudo_op PARAMS ((int, sb *, sb *));
355 static void add_keyword PARAMS ((const char *, int));
356 static void process_init PARAMS ((void));
357 static void do_define PARAMS ((const char *));
358 static void show_usage PARAMS ((FILE *, int));
359 static void show_help PARAMS ((void));
360
361 #define FATAL(x) \
362 do { include_print_where_line (stderr); fprintf x ; fatals++; quit(); } while(0)
363 #define ERROR(x) \
364 do { include_print_where_line (stderr); fprintf x; errors++; } while(0)
365 #define WARNING(x) \
366 do { include_print_where_line (stderr); fprintf x; warnings++;} while(0)
367
368
369
370 /* exit the program and return the right ERROR code. */
371 static void
372 quit ()
373 {
374 int exitcode;
375 if (fatals + errors)
376 exitcode = 1;
377 else
378 exitcode = 0;
379
380 if (stats)
381 {
382 int i;
383 for (i = 0; i < sb_max_power_two; i++)
384 {
385 fprintf (stderr, "strings size %8d : %d\n", 1<<i, string_count[i]);
386 }
387 }
388 exit (exitcode);
389 }
390
391 /* hash table maintenance. */
392
393 /* build a new hash table with size buckets, and fill in the info at ptr. */
394
395 static void
396 hash_new_table (size, ptr)
397 int size;
398 hash_table *ptr;
399 {
400 int i;
401 ptr->size = size;
402 ptr->table = (hash_entry **) xmalloc (size * (sizeof (hash_entry *)));
403 /* Fill with null-pointer, not zero-bit-pattern. */
404 for (i = 0; i < size; i++)
405 ptr->table[i] = 0;
406 }
407
408 /* calculate and return the hash value of the sb at key. */
409
410 static int
411 hash (key)
412 sb *key;
413 {
414 int k = 0x1234;
415 int i;
416 char *p = key->ptr;
417 for (i = 0; i < key->len; i++)
418 {
419 k ^= (k << 2) ^ *p;
420 p++;
421 }
422 return k & 0xf0fff;
423 }
424
425 /* lookup key in hash_table tab, if present, then return it, otherwise
426 build a new one and fill it with hash_integer. */
427
428 static
429 hash_entry *
430 hash_create (tab, key)
431 hash_table *tab;
432 sb *key;
433 {
434 int k = hash (key) % tab->size;
435 hash_entry *p;
436 hash_entry **table = tab->table;
437
438 p = table[k];
439
440 while (1)
441 {
442 if (!p)
443 {
444 hash_entry *n = (hash_entry *) xmalloc (sizeof (hash_entry));
445 n->next = table[k];
446 sb_new (&n->key);
447 sb_add_sb (&n->key, key);
448 table[k] = n;
449 n->type = hash_integer;
450 return n;
451 }
452 if (strncmp (table[k]->key.ptr, key->ptr, key->len) == 0)
453 {
454 return p;
455 }
456 p = p->next;
457 }
458 }
459
460 /* add sb name with key into hash_table tab. if replacing old value
461 and again, then ERROR. */
462
463 static
464 void
465 hash_add_to_string_table (tab, key, name, again)
466 hash_table *tab;
467 sb *key;
468 sb *name;
469 int again;
470 {
471 hash_entry *ptr = hash_create (tab, key);
472 if (ptr->type == hash_integer)
473 {
474 sb_new (&ptr->value.s);
475 }
476 if (ptr->value.s.len)
477 {
478 if (!again)
479 ERROR ((stderr, _("redefinition not allowed\n")));
480 }
481
482 ptr->type = hash_string;
483 sb_reset (&ptr->value.s);
484
485 sb_add_sb (&ptr->value.s, name);
486 }
487
488 /* add integer name to hash_table tab with sb key. */
489
490 static
491 void
492 hash_add_to_int_table (tab, key, name)
493 hash_table *tab;
494 sb *key;
495 int name;
496 {
497 hash_entry *ptr = hash_create (tab, key);
498 ptr->value.i = name;
499 }
500
501 /* lookup sb key in hash_table tab. if found return hash_entry result,
502 else 0. */
503
504 static
505 hash_entry *
506 hash_lookup (tab, key)
507 hash_table *tab;
508 sb *key;
509 {
510 int k = hash (key) % tab->size;
511 hash_entry **table = tab->table;
512 hash_entry *p = table[k];
513 while (p)
514 {
515 if (p->key.len == key->len
516 && strncmp (p->key.ptr, key->ptr, key->len) == 0)
517 return p;
518 p = p->next;
519 }
520 return 0;
521 }
522
523
524 /* expressions
525
526 are handled in a really simple recursive decent way. each bit of
527 the machine takes an index into an sb and a pointer to an exp_t,
528 modifies the *exp_t and returns the index of the first character
529 past the part of the expression parsed.
530
531 expression precedence:
532 ( )
533 unary + - ~
534 * /
535 + -
536 &
537 | ~
538
539 */
540
541
542 /* make sure that the exp_t at term is constant, if not the give the op ERROR. */
543
544 static
545 void
546 checkconst (op, term)
547 int op;
548 exp_t *term;
549 {
550 if (term->add_symbol.len
551 || term->sub_symbol.len)
552 {
553 ERROR ((stderr, _("the %c operator cannot take non-absolute arguments.\n"), op));
554 }
555 }
556
557 /* turn the number in string at idx into a number of base,
558 fill in ptr and return the index of the first character not in the
559 number. */
560
561 static
562 int
563 sb_strtol (idx, string, base, ptr)
564 int idx;
565 sb *string;
566 int base;
567 int *ptr;
568 {
569 int value = 0;
570 idx = sb_skip_white (idx, string);
571
572 while (idx < string->len)
573 {
574 int ch = string->ptr[idx];
575 int dig = 0;
576 if (isdigit (ch))
577 dig = ch - '0';
578 else if (ch >= 'a' && ch <= 'f')
579 dig = ch - 'a' + 10;
580 else if (ch >= 'A' && ch <= 'F')
581 dig = ch - 'A' + 10;
582 else
583 break;
584
585 if (dig >= base)
586 break;
587
588 value = value * base + dig;
589 idx++;
590 }
591 *ptr = value;
592 return idx;
593 }
594
595 static int
596 level_0 (idx, string, lhs)
597 int idx;
598 sb *string;
599 exp_t *lhs;
600 {
601 lhs->add_symbol.len = 0;
602 lhs->add_symbol.name = 0;
603
604 lhs->sub_symbol.len = 0;
605 lhs->sub_symbol.name = 0;
606
607 idx = sb_skip_white (idx, string);
608
609 lhs->value = 0;
610
611 if (isdigit ((unsigned char) string->ptr[idx]))
612 {
613 idx = sb_strtol (idx, string, 10, &lhs->value);
614 }
615 else if (ISFIRSTCHAR (string->ptr[idx]))
616 {
617 int len = 0;
618 lhs->add_symbol.name = string->ptr + idx;
619 while (idx < string->len && ISNEXTCHAR (string->ptr[idx]))
620 {
621 idx++;
622 len++;
623 }
624 lhs->add_symbol.len = len;
625 }
626 else if (string->ptr[idx] == '"')
627 {
628 sb acc;
629 sb_new (&acc);
630 ERROR ((stderr, _("string where expression expected.\n")));
631 idx = getstring (idx, string, &acc);
632 sb_kill (&acc);
633 }
634 else
635 {
636 ERROR ((stderr, _("can't find primary in expression.\n")));
637 idx++;
638 }
639 return sb_skip_white (idx, string);
640 }
641
642
643
644 static int
645 level_1 (idx, string, lhs)
646 int idx;
647 sb *string;
648 exp_t *lhs;
649 {
650 idx = sb_skip_white (idx, string);
651
652 switch (string->ptr[idx])
653 {
654 case '+':
655 idx = level_1 (idx + 1, string, lhs);
656 break;
657 case '~':
658 idx = level_1 (idx + 1, string, lhs);
659 checkconst ('~', lhs);
660 lhs->value = ~lhs->value;
661 break;
662 case '-':
663 {
664 symbol t;
665 idx = level_1 (idx + 1, string, lhs);
666 lhs->value = -lhs->value;
667 t = lhs->add_symbol;
668 lhs->add_symbol = lhs->sub_symbol;
669 lhs->sub_symbol = t;
670 break;
671 }
672 case '(':
673 idx++;
674 idx = level_5 (sb_skip_white (idx, string), string, lhs);
675 if (string->ptr[idx] != ')')
676 ERROR ((stderr, _("misplaced closing parens.\n")));
677 else
678 idx++;
679 break;
680 default:
681 idx = level_0 (idx, string, lhs);
682 break;
683 }
684 return sb_skip_white (idx, string);
685 }
686
687 static int
688 level_2 (idx, string, lhs)
689 int idx;
690 sb *string;
691 exp_t *lhs;
692 {
693 exp_t rhs;
694
695 idx = level_1 (idx, string, lhs);
696
697 while (idx < string->len && (string->ptr[idx] == '*'
698 || string->ptr[idx] == '/'))
699 {
700 char op = string->ptr[idx++];
701 idx = level_1 (idx, string, &rhs);
702 switch (op)
703 {
704 case '*':
705 checkconst ('*', lhs);
706 checkconst ('*', &rhs);
707 lhs->value *= rhs.value;
708 break;
709 case '/':
710 checkconst ('/', lhs);
711 checkconst ('/', &rhs);
712 if (rhs.value == 0)
713 ERROR ((stderr, _("attempt to divide by zero.\n")));
714 else
715 lhs->value /= rhs.value;
716 break;
717 }
718 }
719 return sb_skip_white (idx, string);
720 }
721
722
723 static int
724 level_3 (idx, string, lhs)
725 int idx;
726 sb *string;
727 exp_t *lhs;
728 {
729 exp_t rhs;
730
731 idx = level_2 (idx, string, lhs);
732
733 while (idx < string->len
734 && (string->ptr[idx] == '+'
735 || string->ptr[idx] == '-'))
736 {
737 char op = string->ptr[idx++];
738 idx = level_2 (idx, string, &rhs);
739 switch (op)
740 {
741 case '+':
742 lhs->value += rhs.value;
743 if (lhs->add_symbol.name && rhs.add_symbol.name)
744 {
745 ERROR ((stderr, _("can't add two relocatable expressions\n")));
746 }
747 /* change nn+symbol to symbol + nn */
748 if (rhs.add_symbol.name)
749 {
750 lhs->add_symbol = rhs.add_symbol;
751 }
752 break;
753 case '-':
754 lhs->value -= rhs.value;
755 lhs->sub_symbol = rhs.add_symbol;
756 break;
757 }
758 }
759 return sb_skip_white (idx, string);
760 }
761
762 static int
763 level_4 (idx, string, lhs)
764 int idx;
765 sb *string;
766 exp_t *lhs;
767 {
768 exp_t rhs;
769
770 idx = level_3 (idx, string, lhs);
771
772 while (idx < string->len &&
773 string->ptr[idx] == '&')
774 {
775 char op = string->ptr[idx++];
776 idx = level_3 (idx, string, &rhs);
777 switch (op)
778 {
779 case '&':
780 checkconst ('&', lhs);
781 checkconst ('&', &rhs);
782 lhs->value &= rhs.value;
783 break;
784 }
785 }
786 return sb_skip_white (idx, string);
787 }
788
789 static int
790 level_5 (idx, string, lhs)
791 int idx;
792 sb *string;
793 exp_t *lhs;
794 {
795 exp_t rhs;
796
797 idx = level_4 (idx, string, lhs);
798
799 while (idx < string->len
800 && (string->ptr[idx] == '|' || string->ptr[idx] == '~'))
801 {
802 char op = string->ptr[idx++];
803 idx = level_4 (idx, string, &rhs);
804 switch (op)
805 {
806 case '|':
807 checkconst ('|', lhs);
808 checkconst ('|', &rhs);
809 lhs->value |= rhs.value;
810 break;
811 case '~':
812 checkconst ('~', lhs);
813 checkconst ('~', &rhs);
814 lhs->value ^= rhs.value;
815 break;
816 }
817 }
818 return sb_skip_white (idx, string);
819 }
820
821
822 /* parse the expression at offset idx into string, fill up res with
823 the result. return the index of the first char past the expression.
824 */
825
826 static int
827 exp_parse (idx, string, res)
828 int idx;
829 sb *string;
830 exp_t *res;
831 {
832 return level_5 (sb_skip_white (idx, string), string, res);
833 }
834
835
836 /* turn the expression at exp into text and glue it onto the end of
837 string. */
838
839 static void
840 exp_string (exp, string)
841 exp_t *exp;
842 sb *string;
843 {
844 int np = 0;
845 int ad = 0;
846 sb_reset (string);
847
848 if (exp->add_symbol.len)
849 {
850 sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
851 np = 1;
852 ad = 1;
853 }
854 if (exp->value)
855 {
856 char buf[20];
857 if (np)
858 sb_add_char (string, '+');
859 sprintf (buf, "%d", exp->value);
860 sb_add_string (string, buf);
861 np = 1;
862 ad = 1;
863 }
864 if (exp->sub_symbol.len)
865 {
866 sb_add_char (string, '-');
867 sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
868 np = 0;
869 ad = 1;
870 }
871
872 if (!ad)
873 sb_add_char (string, '0');
874 }
875
876
877 /* parse the expression at offset idx into sb in, return the value in val.
878 if the expression is not constant, give ERROR emsg. returns the index
879 of the first character past the end of the expression. */
880
881 static int
882 exp_get_abs (emsg, idx, in, val)
883 const char *emsg;
884 int idx;
885 sb *in;
886 int *val;
887 {
888 exp_t res;
889 idx = exp_parse (idx, in, &res);
890 if (res.add_symbol.len || res.sub_symbol.len)
891 ERROR ((stderr, emsg));
892 *val = res.value;
893 return idx;
894 }
895
896
897 sb label; /* current label parsed from line */
898 hash_table assign_hash_table; /* hash table for all assigned variables */
899 hash_table keyword_hash_table; /* hash table for keyword */
900 hash_table vars; /* hash table for eq variables */
901
902 #define in_comment ';'
903
904 #if 0
905 static void
906 strip_comments (out)
907 sb *out;
908 {
909 char *s = out->ptr;
910 int i = 0;
911 for (i = 0; i < out->len; i++)
912 {
913 if (ISCOMMENTCHAR(s[i]))
914 {
915 out->len = i;
916 return;
917 }
918 }
919 }
920 #endif
921
922 /* push back character ch so that it can be read again. */
923
924 static void
925 unget (ch)
926 int ch;
927 {
928 if (ch == '\n')
929 {
930 sp->linecount--;
931 }
932 if (sp->pushback_index)
933 sp->pushback_index--;
934 else
935 sb_add_char (&sp->pushback, ch);
936 }
937
938 /* push the sb ptr onto the include stack, with the given name, type and index. */
939
940 static
941 void
942 include_buf (name, ptr, type, index)
943 sb *name;
944 sb *ptr;
945 include_type type;
946 int index;
947 {
948 sp++;
949 if (sp - include_stack >= MAX_INCLUDES)
950 FATAL ((stderr, _("unreasonable nesting.\n")));
951 sb_new (&sp->name);
952 sb_add_sb (&sp->name, name);
953 sp->handle = 0;
954 sp->linecount = 1;
955 sp->pushback_index = 0;
956 sp->type = type;
957 sp->index = index;
958 sb_new (&sp->pushback);
959 sb_add_sb (&sp->pushback, ptr);
960 }
961
962
963 /* used in ERROR messages, print info on where the include stack is onto file. */
964 static
965 void
966 include_print_where_line (file)
967 FILE *file;
968 {
969 struct include_stack *p = include_stack + 1;
970
971 while (p <= sp)
972 {
973 fprintf (file, "%s:%d ", sb_name (&p->name), p->linecount - 1);
974 p++;
975 }
976 }
977
978 /* used in listings, print the line number onto file. */
979 static void
980 include_print_line (file)
981 FILE *file;
982 {
983 int n;
984 struct include_stack *p = include_stack + 1;
985
986 n = fprintf (file, "%4d", p->linecount);
987 p++;
988 while (p <= sp)
989 {
990 n += fprintf (file, ".%d", p->linecount);
991 p++;
992 }
993 while (n < 8 * 3)
994 {
995 fprintf (file, " ");
996 n++;
997 }
998 }
999
1000
1001 /* read a line from the top of the include stack into sb in. */
1002
1003 static int
1004 get_line (in)
1005 sb *in;
1006 {
1007 int online = 0;
1008 int more = 1;
1009
1010 if (copysource)
1011 {
1012 putc (comment_char, outfile);
1013 if (print_line_number)
1014 include_print_line (outfile);
1015 }
1016
1017 while (1)
1018 {
1019 int ch = get ();
1020
1021 while (ch == '\r')
1022 ch = get ();
1023
1024 if (ch == EOF)
1025 {
1026 if (online)
1027 {
1028 WARNING ((stderr, _("End of file not at start of line.\n")));
1029 if (copysource)
1030 putc ('\n', outfile);
1031 ch = '\n';
1032 }
1033 else
1034 more = 0;
1035 break;
1036 }
1037
1038 if (copysource)
1039 {
1040 putc (ch, outfile);
1041 }
1042
1043 if (ch == '\n')
1044 {
1045 ch = get ();
1046 online = 0;
1047 if (ch == '+')
1048 {
1049 /* continued line */
1050 if (copysource)
1051 {
1052 putc (comment_char, outfile);
1053 putc ('+', outfile);
1054 }
1055 ch = get ();
1056 }
1057 else
1058 {
1059 if (ch != EOF)
1060 unget (ch);
1061 break;
1062 }
1063 }
1064 else
1065 {
1066 sb_add_char (in, ch);
1067 }
1068 online++;
1069 }
1070
1071 return more;
1072 }
1073
1074 /* find a label from sb in and put it in out. */
1075
1076 static int
1077 grab_label (in, out)
1078 sb *in;
1079 sb *out;
1080 {
1081 int i = 0;
1082 sb_reset (out);
1083 if (ISFIRSTCHAR (in->ptr[i]))
1084 {
1085 sb_add_char (out, in->ptr[i]);
1086 i++;
1087 while ((ISNEXTCHAR (in->ptr[i])
1088 || in->ptr[i] == '\\'
1089 || in->ptr[i] == '&')
1090 && i < in->len)
1091 {
1092 sb_add_char (out, in->ptr[i]);
1093 i++;
1094 }
1095 }
1096 return i;
1097 }
1098
1099 /* find all strange base stuff and turn into decimal. also
1100 find all the other numbers and convert them from the default radix */
1101
1102 static void
1103 change_base (idx, in, out)
1104 int idx;
1105 sb *in;
1106 sb *out;
1107 {
1108 char buffer[20];
1109
1110 while (idx < in->len)
1111 {
1112 if (in->ptr[idx] == '\\'
1113 && idx + 1 < in->len
1114 && in->ptr[idx + 1] == '(')
1115 {
1116 idx += 2;
1117 while (idx < in->len
1118 && in->ptr[idx] != ')')
1119 {
1120 sb_add_char (out, in->ptr[idx]);
1121 idx++;
1122 }
1123 if (idx < in->len)
1124 idx++;
1125 }
1126 else if (idx < in->len - 1 && in->ptr[idx + 1] == '\'' && ! mri)
1127 {
1128 int base;
1129 int value;
1130 switch (in->ptr[idx])
1131 {
1132 case 'b':
1133 case 'B':
1134 base = 2;
1135 break;
1136 case 'q':
1137 case 'Q':
1138 base = 8;
1139 break;
1140 case 'h':
1141 case 'H':
1142 base = 16;
1143 break;
1144 case 'd':
1145 case 'D':
1146 base = 10;
1147 break;
1148 default:
1149 ERROR ((stderr, _("Illegal base character %c.\n"), in->ptr[idx]));
1150 base = 10;
1151 break;
1152 }
1153
1154 idx = sb_strtol (idx + 2, in, base, &value);
1155 sprintf (buffer, "%d", value);
1156 sb_add_string (out, buffer);
1157 }
1158 else if (ISFIRSTCHAR (in->ptr[idx]))
1159 {
1160 /* copy entire names through quickly */
1161 sb_add_char (out, in->ptr[idx]);
1162 idx++;
1163 while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
1164 {
1165 sb_add_char (out, in->ptr[idx]);
1166 idx++;
1167 }
1168 }
1169 else if (isdigit ((unsigned char) in->ptr[idx]))
1170 {
1171 int value;
1172 /* all numbers must start with a digit, let's chew it and
1173 spit out decimal */
1174 idx = sb_strtol (idx, in, radix, &value);
1175 sprintf (buffer, "%d", value);
1176 sb_add_string (out, buffer);
1177
1178 /* skip all undigsested letters */
1179 while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
1180 {
1181 sb_add_char (out, in->ptr[idx]);
1182 idx++;
1183 }
1184 }
1185 else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
1186 {
1187 char tchar = in->ptr[idx];
1188 /* copy entire names through quickly */
1189 sb_add_char (out, in->ptr[idx]);
1190 idx++;
1191 while (idx < in->len && in->ptr[idx] != tchar)
1192 {
1193 sb_add_char (out, in->ptr[idx]);
1194 idx++;
1195 }
1196 }
1197 else
1198 {
1199 /* nothing special, just pass it through */
1200 sb_add_char (out, in->ptr[idx]);
1201 idx++;
1202 }
1203 }
1204
1205 }
1206
1207 /* .end */
1208 static void
1209 do_end (in)
1210 sb *in;
1211 {
1212 had_end = 1;
1213 if (mri)
1214 fprintf (outfile, "%s\n", sb_name (in));
1215 }
1216
1217 /* .assign */
1218
1219 static void
1220 do_assign (again, idx, in)
1221 int again;
1222 int idx;
1223 sb *in;
1224 {
1225 /* stick label in symbol table with following value */
1226 exp_t e;
1227 sb acc;
1228
1229 sb_new (&acc);
1230 idx = exp_parse (idx, in, &e);
1231 exp_string (&e, &acc);
1232 hash_add_to_string_table (&assign_hash_table, &label, &acc, again);
1233 sb_kill (&acc);
1234 }
1235
1236
1237 /* .radix [b|q|d|h] */
1238
1239 static
1240 void
1241 do_radix (ptr)
1242 sb *ptr;
1243 {
1244 int idx = sb_skip_white (0, ptr);
1245 switch (ptr->ptr[idx])
1246 {
1247 case 'B':
1248 case 'b':
1249 radix = 2;
1250 break;
1251 case 'q':
1252 case 'Q':
1253 radix = 8;
1254 break;
1255 case 'd':
1256 case 'D':
1257 radix = 10;
1258 break;
1259 case 'h':
1260 case 'H':
1261 radix = 16;
1262 break;
1263 default:
1264 ERROR ((stderr, _("radix is %c must be one of b, q, d or h"), radix));
1265 }
1266 }
1267
1268
1269 /* Parse off a .b, .w or .l */
1270
1271 static int
1272 get_opsize (idx, in, size)
1273 int idx;
1274 sb *in;
1275 int *size;
1276 {
1277 *size = 4;
1278 if (in->ptr[idx] == '.')
1279 {
1280 idx++;
1281 }
1282 switch (in->ptr[idx])
1283 {
1284 case 'b':
1285 case 'B':
1286 *size = 1;
1287 break;
1288 case 'w':
1289 case 'W':
1290 *size = 2;
1291 break;
1292 case 'l':
1293 case 'L':
1294 *size = 4;
1295 break;
1296 case ' ':
1297 case '\t':
1298 break;
1299 default:
1300 ERROR ((stderr, _("size must be one of b, w or l, is %c.\n"), in->ptr[idx]));
1301 break;
1302 }
1303 idx++;
1304
1305 return idx;
1306 }
1307
1308 static
1309 int eol(idx, line)
1310 int idx;
1311 sb *line;
1312 {
1313 idx = sb_skip_white (idx, line);
1314 if (idx < line->len
1315 && ISCOMMENTCHAR(line->ptr[idx]))
1316 return 1;
1317 if (idx >= line->len)
1318 return 1;
1319 return 0;
1320 }
1321
1322 /* .data [.b|.w|.l] <data>*
1323 or d[bwl] <data>* */
1324
1325 static void
1326 do_data (idx, in, size)
1327 int idx;
1328 sb *in;
1329 int size;
1330 {
1331 int opsize = 4;
1332 char *opname = ".yikes!";
1333 sb acc;
1334 sb_new (&acc);
1335
1336 if (!size)
1337 {
1338 idx = get_opsize (idx, in, &opsize);
1339 }
1340 else {
1341 opsize = size;
1342 }
1343 switch (opsize)
1344 {
1345 case 4:
1346 opname = ".long";
1347 break;
1348 case 2:
1349 opname = ".short";
1350 break;
1351 case 1:
1352 opname = ".byte";
1353 break;
1354 }
1355
1356
1357 fprintf (outfile, "%s\t", opname);
1358
1359 idx = sb_skip_white (idx, in);
1360
1361 if (alternate
1362 && idx < in->len
1363 && in->ptr[idx] == '"')
1364 {
1365 int i;
1366 idx = getstring (idx, in, &acc);
1367 for (i = 0; i < acc.len; i++)
1368 {
1369 if (i)
1370 fprintf(outfile,",");
1371 fprintf (outfile, "%d", acc.ptr[i]);
1372 }
1373 }
1374 else
1375 {
1376 while (!eol (idx, in))
1377 {
1378 exp_t e;
1379 idx = exp_parse (idx, in, &e);
1380 exp_string (&e, &acc);
1381 sb_add_char (&acc, 0);
1382 fprintf (outfile, acc.ptr);
1383 if (idx < in->len && in->ptr[idx] == ',')
1384 {
1385 fprintf (outfile, ",");
1386 idx++;
1387 }
1388 }
1389 }
1390 sb_kill (&acc);
1391 sb_print_at (outfile, idx, in);
1392 fprintf (outfile, "\n");
1393 }
1394
1395 /* .datab [.b|.w|.l] <repeat>,<fill> */
1396
1397 static void
1398 do_datab (idx, in)
1399 int idx;
1400 sb *in;
1401 {
1402 int opsize;
1403 int repeat;
1404 int fill;
1405
1406 idx = get_opsize (idx, in, &opsize);
1407
1408 idx = exp_get_abs (_("datab repeat must be constant.\n"), idx, in, &repeat);
1409 idx = sb_skip_comma (idx, in);
1410 idx = exp_get_abs (_("datab data must be absolute.\n"), idx, in, &fill);
1411
1412 fprintf (outfile, ".fill\t%d,%d,%d\n", repeat, opsize, fill);
1413 }
1414
1415 /* .align <size> */
1416
1417 static void
1418 do_align (idx, in)
1419 int idx;
1420 sb *in;
1421 {
1422 int al, have_fill, fill;
1423
1424 idx = exp_get_abs (_("align needs absolute expression.\n"), idx, in, &al);
1425 idx = sb_skip_white (idx, in);
1426 have_fill = 0;
1427 fill = 0;
1428 if (! eol (idx, in))
1429 {
1430 idx = sb_skip_comma (idx, in);
1431 idx = exp_get_abs (_(".align needs absolute fill value.\n"), idx, in,
1432 &fill);
1433 have_fill = 1;
1434 }
1435
1436 if (al != 1
1437 && al != 2
1438 && al != 4)
1439 WARNING ((stderr, _("alignment must be one of 1, 2 or 4.\n")));
1440
1441 fprintf (outfile, ".align %d", al);
1442 if (have_fill)
1443 fprintf (outfile, ",%d", fill);
1444 fprintf (outfile, "\n");
1445 }
1446
1447 /* .res[.b|.w|.l] <size> */
1448
1449 static void
1450 do_res (idx, in, type)
1451 int idx;
1452 sb *in;
1453 int type;
1454 {
1455 int size = 4;
1456 int count = 0;
1457
1458 idx = get_opsize (idx, in, &size);
1459 while (!eol(idx, in))
1460 {
1461 idx = sb_skip_white (idx, in);
1462 if (in->ptr[idx] == ',')
1463 idx++;
1464 idx = exp_get_abs (_("res needs absolute expression for fill count.\n"), idx, in, &count);
1465
1466 if (type == 'c' || type == 'z')
1467 count++;
1468
1469 fprintf (outfile, ".space %d\n", count * size);
1470 }
1471 }
1472
1473
1474 /* .export */
1475
1476 static void
1477 do_export (in)
1478 sb *in;
1479 {
1480 fprintf (outfile, ".global %s\n", sb_name (in));
1481 }
1482
1483 /* .print [list] [nolist] */
1484
1485 static void
1486 do_print (idx, in)
1487 int idx;
1488 sb *in;
1489 {
1490 idx = sb_skip_white (idx, in);
1491 while (idx < in->len)
1492 {
1493 if (strncasecmp (in->ptr + idx, "LIST", 4) == 0)
1494 {
1495 fprintf (outfile, ".list\n");
1496 idx += 4;
1497 }
1498 else if (strncasecmp (in->ptr + idx, "NOLIST", 6) == 0)
1499 {
1500 fprintf (outfile, ".nolist\n");
1501 idx += 6;
1502 }
1503 idx++;
1504 }
1505 }
1506
1507 /* .head */
1508 static void
1509 do_heading (idx, in)
1510 int idx;
1511 sb *in;
1512 {
1513 sb head;
1514 sb_new (&head);
1515 idx = getstring (idx, in, &head);
1516 fprintf (outfile, ".title \"%s\"\n", sb_name (&head));
1517 sb_kill (&head);
1518 }
1519
1520 /* .page */
1521
1522 static void
1523 do_page ()
1524 {
1525 fprintf (outfile, ".eject\n");
1526 }
1527
1528 /* .form [lin=<value>] [col=<value>] */
1529 static void
1530 do_form (idx, in)
1531 int idx;
1532 sb *in;
1533 {
1534 int lines = 60;
1535 int columns = 132;
1536 idx = sb_skip_white (idx, in);
1537
1538 while (idx < in->len)
1539 {
1540
1541 if (strncasecmp (in->ptr + idx, "LIN=", 4) == 0)
1542 {
1543 idx += 4;
1544 idx = exp_get_abs (_("form LIN= needs absolute expresssion.\n"), idx, in, &lines);
1545 }
1546
1547 if (strncasecmp (in->ptr + idx, _("COL="), 4) == 0)
1548 {
1549 idx += 4;
1550 idx = exp_get_abs (_("form COL= needs absolute expresssion.\n"), idx, in, &columns);
1551 }
1552
1553 idx++;
1554 }
1555 fprintf (outfile, ".psize %d,%d\n", lines, columns);
1556
1557 }
1558
1559
1560 /* Fetch string from the input stream,
1561 rules:
1562 'Bxyx<whitespace> -> return 'Bxyza
1563 %<char> -> return string of decimal value of x
1564 "<string>" -> return string
1565 xyx<whitespace> -> return xyz
1566 */
1567 static int
1568 get_any_string (idx, in, out, expand, pretend_quoted)
1569 int idx;
1570 sb *in;
1571 sb *out;
1572 int expand;
1573 int pretend_quoted;
1574 {
1575 sb_reset (out);
1576 idx = sb_skip_white (idx, in);
1577
1578 if (idx < in->len)
1579 {
1580 if (in->len > 2 && in->ptr[idx+1] == '\'' && ISBASE (in->ptr[idx]))
1581 {
1582 while (!ISSEP (in->ptr[idx]))
1583 sb_add_char (out, in->ptr[idx++]);
1584 }
1585 else if (in->ptr[idx] == '%'
1586 && alternate
1587 && expand)
1588 {
1589 int val;
1590 char buf[20];
1591 /* Turns the next expression into a string */
1592 idx = exp_get_abs (_("% operator needs absolute expression"),
1593 idx + 1,
1594 in,
1595 &val);
1596 sprintf(buf, "%d", val);
1597 sb_add_string (out, buf);
1598 }
1599 else if (in->ptr[idx] == '"'
1600 || in->ptr[idx] == '<'
1601 || (alternate && in->ptr[idx] == '\''))
1602 {
1603 if (alternate && expand)
1604 {
1605 /* Keep the quotes */
1606 sb_add_char (out, '\"');
1607
1608 idx = getstring (idx, in, out);
1609 sb_add_char (out, '\"');
1610
1611 }
1612 else {
1613 idx = getstring (idx, in, out);
1614 }
1615 }
1616 else
1617 {
1618 while (idx < in->len
1619 && (in->ptr[idx] == '"'
1620 || in->ptr[idx] == '\''
1621 || pretend_quoted
1622 || !ISSEP (in->ptr[idx])))
1623 {
1624 if (in->ptr[idx] == '"'
1625 || in->ptr[idx] == '\'')
1626 {
1627 char tchar = in->ptr[idx];
1628 sb_add_char (out, in->ptr[idx++]);
1629 while (idx < in->len
1630 && in->ptr[idx] != tchar)
1631 sb_add_char (out, in->ptr[idx++]);
1632 if (idx == in->len)
1633 return idx;
1634 }
1635 sb_add_char (out, in->ptr[idx++]);
1636 }
1637 }
1638 }
1639
1640 return idx;
1641 }
1642
1643
1644 /* skip along sb in starting at idx, suck off whitespace a ( and more
1645 whitespace. return the idx of the next char */
1646
1647 static int
1648 skip_openp (idx, in)
1649 int idx;
1650 sb *in;
1651 {
1652 idx = sb_skip_white (idx, in);
1653 if (in->ptr[idx] != '(')
1654 ERROR ((stderr, _("misplaced ( .\n")));
1655 idx = sb_skip_white (idx + 1, in);
1656 return idx;
1657 }
1658
1659 /* skip along sb in starting at idx, suck off whitespace a ) and more
1660 whitespace. return the idx of the next char */
1661
1662 static int
1663 skip_closep (idx, in)
1664 int idx;
1665 sb *in;
1666 {
1667 idx = sb_skip_white (idx, in);
1668 if (in->ptr[idx] != ')')
1669 ERROR ((stderr, _("misplaced ).\n")));
1670 idx = sb_skip_white (idx + 1, in);
1671 return idx;
1672 }
1673
1674 /* .len */
1675
1676 static int
1677 dolen (idx, in, out)
1678 int idx;
1679 sb *in;
1680 sb *out;
1681 {
1682
1683 sb stringout;
1684 char buffer[10];
1685
1686 sb_new (&stringout);
1687 idx = skip_openp (idx, in);
1688 idx = get_and_process (idx, in, &stringout);
1689 idx = skip_closep (idx, in);
1690 sprintf (buffer, "%d", stringout.len);
1691 sb_add_string (out, buffer);
1692
1693 sb_kill (&stringout);
1694 return idx;
1695 }
1696
1697
1698 /* .instr */
1699
1700 static
1701 int
1702 doinstr (idx, in, out)
1703 int idx;
1704 sb *in;
1705 sb *out;
1706 {
1707 sb string;
1708 sb search;
1709 int i;
1710 int start;
1711 int res;
1712 char buffer[10];
1713
1714 sb_new (&string);
1715 sb_new (&search);
1716 idx = skip_openp (idx, in);
1717 idx = get_and_process (idx, in, &string);
1718 idx = sb_skip_comma (idx, in);
1719 idx = get_and_process (idx, in, &search);
1720 idx = sb_skip_comma (idx, in);
1721 if (isdigit ((unsigned char) in->ptr[idx]))
1722 {
1723 idx = exp_get_abs (_(".instr needs absolute expresson.\n"), idx, in, &start);
1724 }
1725 else
1726 {
1727 start = 0;
1728 }
1729 idx = skip_closep (idx, in);
1730 res = -1;
1731 for (i = start; i < string.len; i++)
1732 {
1733 if (strncmp (string.ptr + i, search.ptr, search.len) == 0)
1734 {
1735 res = i;
1736 break;
1737 }
1738 }
1739 sprintf (buffer, "%d", res);
1740 sb_add_string (out, buffer);
1741 sb_kill (&string);
1742 sb_kill (&search);
1743 return idx;
1744 }
1745
1746
1747 static int
1748 dosubstr (idx, in, out)
1749 int idx;
1750 sb *in;
1751 sb *out;
1752 {
1753 sb string;
1754 int pos;
1755 int len;
1756 sb_new (&string);
1757
1758 idx = skip_openp (idx, in);
1759 idx = get_and_process (idx, in, &string);
1760 idx = sb_skip_comma (idx, in);
1761 idx = exp_get_abs (_("need absolute position.\n"), idx, in, &pos);
1762 idx = sb_skip_comma (idx, in);
1763 idx = exp_get_abs (_("need absolute length.\n"), idx, in, &len);
1764 idx = skip_closep (idx, in);
1765
1766
1767 if (len < 0 || pos < 0 ||
1768 pos > string.len
1769 || pos + len > string.len)
1770 {
1771 sb_add_string (out, " ");
1772 }
1773 else
1774 {
1775 sb_add_char (out, '"');
1776 while (len > 0)
1777 {
1778 sb_add_char (out, string.ptr[pos++]);
1779 len--;
1780 }
1781 sb_add_char (out, '"');
1782 }
1783 sb_kill(&string);
1784 return idx;
1785 }
1786
1787 /* scan line, change tokens in the hash table to their replacements */
1788 static void
1789 process_assigns (idx, in, buf)
1790 int idx;
1791 sb *in;
1792 sb *buf;
1793 {
1794 while (idx < in->len)
1795 {
1796 hash_entry *ptr;
1797 if (in->ptr[idx] == '\\'
1798 && idx + 1 < in->len
1799 && in->ptr[idx + 1] == '(')
1800 {
1801 do
1802 {
1803 sb_add_char (buf, in->ptr[idx]);
1804 idx++;
1805 }
1806 while (idx < in->len && in->ptr[idx - 1] != ')');
1807 }
1808 else if (in->ptr[idx] == '\\'
1809 && idx + 1 < in->len
1810 && in->ptr[idx + 1] == '&')
1811 {
1812 idx = condass_lookup_name (in, idx + 2, buf, 1);
1813 }
1814 else if (in->ptr[idx] == '\\'
1815 && idx + 1 < in->len
1816 && in->ptr[idx + 1] == '$')
1817 {
1818 idx = condass_lookup_name (in, idx + 2, buf, 0);
1819 }
1820 else if (idx + 3 < in->len
1821 && in->ptr[idx] == '.'
1822 && toupper ((unsigned char) in->ptr[idx + 1]) == 'L'
1823 && toupper ((unsigned char) in->ptr[idx + 2]) == 'E'
1824 && toupper ((unsigned char) in->ptr[idx + 3]) == 'N')
1825 idx = dolen (idx + 4, in, buf);
1826 else if (idx + 6 < in->len
1827 && in->ptr[idx] == '.'
1828 && toupper ((unsigned char) in->ptr[idx + 1]) == 'I'
1829 && toupper ((unsigned char) in->ptr[idx + 2]) == 'N'
1830 && toupper ((unsigned char) in->ptr[idx + 3]) == 'S'
1831 && toupper ((unsigned char) in->ptr[idx + 4]) == 'T'
1832 && toupper ((unsigned char) in->ptr[idx + 5]) == 'R')
1833 idx = doinstr (idx + 6, in, buf);
1834 else if (idx + 7 < in->len
1835 && in->ptr[idx] == '.'
1836 && toupper ((unsigned char) in->ptr[idx + 1]) == 'S'
1837 && toupper ((unsigned char) in->ptr[idx + 2]) == 'U'
1838 && toupper ((unsigned char) in->ptr[idx + 3]) == 'B'
1839 && toupper ((unsigned char) in->ptr[idx + 4]) == 'S'
1840 && toupper ((unsigned char) in->ptr[idx + 5]) == 'T'
1841 && toupper ((unsigned char) in->ptr[idx + 6]) == 'R')
1842 idx = dosubstr (idx + 7, in, buf);
1843 else if (ISFIRSTCHAR (in->ptr[idx]))
1844 {
1845 /* may be a simple name subsitution, see if we have a word */
1846 sb acc;
1847 int cur = idx + 1;
1848 while (cur < in->len
1849 && (ISNEXTCHAR (in->ptr[cur])))
1850 cur++;
1851
1852 sb_new (&acc);
1853 sb_add_buffer (&acc, in->ptr + idx, cur - idx);
1854 ptr = hash_lookup (&assign_hash_table, &acc);
1855 if (ptr)
1856 {
1857 /* Found a definition for it */
1858 sb_add_sb (buf, &ptr->value.s);
1859 }
1860 else
1861 {
1862 /* No definition, just copy the word */
1863 sb_add_sb (buf, &acc);
1864 }
1865 sb_kill (&acc);
1866 idx = cur;
1867 }
1868 else
1869 {
1870 sb_add_char (buf, in->ptr[idx++]);
1871 }
1872 }
1873 }
1874
1875 static int
1876 get_and_process (idx, in, out)
1877 int idx;
1878 sb *in;
1879 sb *out;
1880 {
1881 sb t;
1882 sb_new (&t);
1883 idx = get_any_string (idx, in, &t, 1, 0);
1884 process_assigns (0, &t, out);
1885 sb_kill (&t);
1886 return idx;
1887 }
1888
1889 static
1890 void
1891 process_file ()
1892 {
1893 sb line;
1894 sb t1, t2;
1895 sb acc;
1896 sb label_in;
1897 int more;
1898
1899 sb_new (&line);
1900 sb_new (&t1);
1901 sb_new (&t2);
1902 sb_new(&acc);
1903 sb_new (&label_in);
1904 sb_reset (&line);
1905 more = get_line (&line);
1906 while (more)
1907 {
1908 /* Find any label and pseudo op that we're intested in */
1909 int l;
1910 if (line.len == 0)
1911 {
1912 if (condass_on ())
1913 fprintf (outfile, "\n");
1914 }
1915 else if (mri
1916 && (line.ptr[0] == '*'
1917 || line.ptr[0] == '!'))
1918 {
1919 /* MRI line comment. */
1920 fprintf (outfile, sb_name (&line));
1921 }
1922 else
1923 {
1924 l = grab_label (&line, &label_in);
1925 sb_reset (&label);
1926
1927 if (line.ptr[l] == ':')
1928 l++;
1929 while (ISWHITE (line.ptr[l]) && l < line.len)
1930 l++;
1931
1932 if (label_in.len)
1933 {
1934 int do_assigns;
1935
1936 /* Munge the label, unless this is EQU or ASSIGN. */
1937 do_assigns = 1;
1938 if (l < line.len
1939 && (line.ptr[l] == '.' || alternate || mri))
1940 {
1941 int lx = l;
1942
1943 if (line.ptr[lx] == '.')
1944 ++lx;
1945 if (lx + 3 <= line.len
1946 && strncasecmp ("EQU", line.ptr + lx, 3) == 0
1947 && (lx + 3 == line.len
1948 || ! ISFIRSTCHAR (line.ptr[lx + 3])))
1949 do_assigns = 0;
1950 else if (lx + 6 <= line.len
1951 && strncasecmp ("ASSIGN", line.ptr + lx, 6) == 0
1952 && (lx + 6 == line.len
1953 || ! ISFIRSTCHAR (line.ptr[lx + 6])))
1954 do_assigns = 0;
1955 }
1956
1957 if (do_assigns)
1958 process_assigns (0, &label_in, &label);
1959 else
1960 sb_add_sb (&label, &label_in);
1961 }
1962
1963 if (l < line.len)
1964 {
1965 if (process_pseudo_op (l, &line, &acc))
1966 {
1967
1968
1969
1970 }
1971 else if (condass_on ())
1972 {
1973 if (macro_op (l, &line))
1974 {
1975
1976
1977 }
1978 else
1979 {
1980 {
1981 if (label.len)
1982 {
1983 fprintf (outfile, "%s:\t", sb_name (&label));
1984 }
1985 else
1986 fprintf (outfile, "\t");
1987 sb_reset(&t1);
1988 process_assigns (l, &line, &t1);
1989 sb_reset (&t2);
1990 change_base (0, &t1, &t2);
1991 fprintf (outfile, "%s\n", sb_name (&t2));
1992 }
1993 }
1994 }
1995 }
1996 else {
1997 /* Only a label on this line */
1998 if (label.len && condass_on())
1999 {
2000 fprintf (outfile, "%s:\n", sb_name (&label));
2001 }
2002 }
2003 }
2004
2005 if (had_end)
2006 break;
2007 sb_reset (&line);
2008 more = get_line (&line);
2009 }
2010
2011 if (!had_end && !mri)
2012 WARNING ((stderr, _("END missing from end of file.\n")));
2013 }
2014
2015
2016
2017
2018
2019 static void
2020 free_old_entry (ptr)
2021 hash_entry *ptr;
2022 {
2023 if (ptr)
2024 {
2025 if (ptr->type == hash_string)
2026 sb_kill(&ptr->value.s);
2027 }
2028 }
2029
2030 /* name: .ASSIGNA <value> */
2031
2032 static void
2033 do_assigna (idx, in)
2034 int idx;
2035 sb *in;
2036 {
2037 sb tmp;
2038 int val;
2039 sb_new (&tmp);
2040
2041 process_assigns (idx, in, &tmp);
2042 idx = exp_get_abs (_(".ASSIGNA needs constant expression argument.\n"), 0, &tmp, &val);
2043
2044 if (!label.len)
2045 {
2046 ERROR ((stderr, _(".ASSIGNA without label.\n")));
2047 }
2048 else
2049 {
2050 hash_entry *ptr = hash_create (&vars, &label);
2051 free_old_entry (ptr);
2052 ptr->type = hash_integer;
2053 ptr->value.i = val;
2054 }
2055 sb_kill (&tmp);
2056 }
2057
2058 /* name: .ASSIGNC <string> */
2059
2060 static void
2061 do_assignc (idx, in)
2062 int idx;
2063 sb *in;
2064 {
2065 sb acc;
2066 sb_new (&acc);
2067 idx = getstring (idx, in, &acc);
2068
2069 if (!label.len)
2070 {
2071 ERROR ((stderr, _(".ASSIGNS without label.\n")));
2072 }
2073 else
2074 {
2075 hash_entry *ptr = hash_create (&vars, &label);
2076 free_old_entry (ptr);
2077 ptr->type = hash_string;
2078 sb_new (&ptr->value.s);
2079 sb_add_sb (&ptr->value.s, &acc);
2080 }
2081 sb_kill (&acc);
2082 }
2083
2084
2085 /* name: .REG (reg) */
2086
2087 static void
2088 do_reg (idx, in)
2089 int idx;
2090 sb *in;
2091 {
2092 /* remove reg stuff from inside parens */
2093 sb what;
2094 if (!mri)
2095 idx = skip_openp (idx, in);
2096 else
2097 idx = sb_skip_white (idx, in);
2098 sb_new (&what);
2099 while (idx < in->len
2100 && (mri
2101 ? ! eol (idx, in)
2102 : in->ptr[idx] != ')'))
2103 {
2104 sb_add_char (&what, in->ptr[idx]);
2105 idx++;
2106 }
2107 hash_add_to_string_table (&assign_hash_table, &label, &what, 1);
2108 sb_kill (&what);
2109 }
2110
2111
2112 static int
2113 condass_lookup_name (inbuf, idx, out, warn)
2114 sb *inbuf;
2115 int idx;
2116 sb *out;
2117 int warn;
2118 {
2119 hash_entry *ptr;
2120 sb condass_acc;
2121 sb_new (&condass_acc);
2122
2123 while (idx < inbuf->len
2124 && ISNEXTCHAR (inbuf->ptr[idx]))
2125 {
2126 sb_add_char (&condass_acc, inbuf->ptr[idx++]);
2127 }
2128
2129 if (inbuf->ptr[idx] == '\'')
2130 idx++;
2131 ptr = hash_lookup (&vars, &condass_acc);
2132
2133
2134 if (!ptr)
2135 {
2136 if (warn)
2137 {
2138 WARNING ((stderr, _("Can't find preprocessor variable %s.\n"), sb_name (&condass_acc)));
2139 }
2140 else
2141 {
2142 sb_add_string (out, "0");
2143 }
2144 }
2145 else
2146 {
2147 if (ptr->type == hash_integer)
2148 {
2149 char buffer[30];
2150 sprintf (buffer, "%d", ptr->value.i);
2151 sb_add_string (out, buffer);
2152 }
2153 else
2154 {
2155 sb_add_sb (out, &ptr->value.s);
2156 }
2157 }
2158 sb_kill (&condass_acc);
2159 return idx;
2160 }
2161
2162 #define EQ 1
2163 #define NE 2
2164 #define GE 3
2165 #define LT 4
2166 #define LE 5
2167 #define GT 6
2168 #define NEVER 7
2169
2170 static int
2171 whatcond (idx, in, val)
2172 int idx;
2173 sb *in;
2174 int *val;
2175 {
2176 int cond;
2177
2178 idx = sb_skip_white (idx, in);
2179 cond = NEVER;
2180 if (idx + 1 < in->len)
2181 {
2182 char *p;
2183 char a, b;
2184
2185 p = in->ptr + idx;
2186 a = toupper ((unsigned char) p[0]);
2187 b = toupper ((unsigned char) p[1]);
2188 if (a == 'E' && b == 'Q')
2189 cond = EQ;
2190 else if (a == 'N' && b == 'E')
2191 cond = NE;
2192 else if (a == 'L' && b == 'T')
2193 cond = LT;
2194 else if (a == 'L' && b == 'E')
2195 cond = LE;
2196 else if (a == 'G' && b == 'T')
2197 cond = GT;
2198 else if (a == 'G' && b == 'E')
2199 cond = GE;
2200 }
2201 if (cond == NEVER)
2202 {
2203 ERROR ((stderr, _("Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n")));
2204 cond = NEVER;
2205 }
2206 idx = sb_skip_white (idx + 2, in);
2207 *val = cond;
2208 return idx;
2209 }
2210
2211 static int
2212 istrue (idx, in)
2213 int idx;
2214 sb *in;
2215 {
2216 int res;
2217 sb acc_a;
2218 sb cond;
2219 sb acc_b;
2220 sb_new (&acc_a);
2221 sb_new (&cond);
2222 sb_new (&acc_b);
2223 idx = sb_skip_white (idx, in);
2224
2225 if (in->ptr[idx] == '"')
2226 {
2227 int cond;
2228 int same;
2229 /* This is a string comparision */
2230 idx = getstring (idx, in, &acc_a);
2231 idx = whatcond (idx, in, &cond);
2232 idx = getstring (idx, in, &acc_b);
2233 same = acc_a.len == acc_b.len && (strncmp (acc_a.ptr, acc_b.ptr, acc_a.len) == 0);
2234
2235 if (cond != EQ && cond != NE)
2236 {
2237 ERROR ((stderr, _("Comparison operator for strings must be EQ or NE\n")));
2238 res = 0;
2239 }
2240 else
2241 res = (cond != EQ) ^ same;
2242 }
2243 else
2244 /* This is a numeric expression */
2245 {
2246 int vala;
2247 int valb;
2248 int cond;
2249 idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"), idx, in, &vala);
2250 idx = whatcond (idx, in, &cond);
2251 idx = sb_skip_white (idx, in);
2252 if (in->ptr[idx] == '"')
2253 {
2254 WARNING ((stderr, _("String compared against expression.\n")));
2255 res = 0;
2256 }
2257 else
2258 {
2259 idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"), idx, in, &valb);
2260 switch (cond)
2261 {
2262 default:
2263 res = 42;
2264 break;
2265 case EQ:
2266 res = vala == valb;
2267 break;
2268 case NE:
2269 res = vala != valb;
2270 break;
2271 case LT:
2272 res = vala < valb;
2273 break;
2274 case LE:
2275 res = vala <= valb;
2276 break;
2277 case GT:
2278 res = vala > valb;
2279 break;
2280 case GE:
2281 res = vala >= valb;
2282 break;
2283 case NEVER:
2284 res = 0;
2285 break;
2286 }
2287 }
2288 }
2289
2290 sb_kill (&acc_a);
2291 sb_kill (&cond);
2292 sb_kill (&acc_b);
2293 return res;
2294 }
2295
2296 /* .AIF */
2297 static void
2298 do_aif (idx, in)
2299 int idx;
2300 sb *in;
2301 {
2302 if (ifi >= IFNESTING)
2303 {
2304 FATAL ((stderr, _("AIF nesting unreasonable.\n")));
2305 }
2306 ifi++;
2307 ifstack[ifi].on = ifstack[ifi-1].on ? istrue (idx, in) : 0;
2308 ifstack[ifi].hadelse = 0;
2309 }
2310
2311
2312 /* .AELSE */
2313 static void
2314 do_aelse ()
2315 {
2316 ifstack[ifi].on = ifstack[ifi-1].on ? !ifstack[ifi].on : 0;
2317 if (ifstack[ifi].hadelse)
2318 {
2319 ERROR ((stderr, _("Multiple AELSEs in AIF.\n")));
2320 }
2321 ifstack[ifi].hadelse = 1;
2322 }
2323
2324
2325 /* .AENDI */
2326 static void
2327 do_aendi ()
2328 {
2329 if (ifi != 0)
2330 {
2331 ifi--;
2332 }
2333 else
2334 {
2335 ERROR ((stderr, _("AENDI without AIF.\n")));
2336 }
2337 }
2338
2339 static int
2340 condass_on ()
2341 {
2342 return ifstack[ifi].on;
2343 }
2344
2345 /* MRI IFEQ, IFNE, IFLT, IFLE, IFGE, IFGT. */
2346
2347 static void
2348 do_if (idx, in, cond)
2349 int idx;
2350 sb *in;
2351 int cond;
2352 {
2353 int val;
2354 int res;
2355
2356 if (ifi >= IFNESTING)
2357 {
2358 FATAL ((stderr, _("IF nesting unreasonable.\n")));
2359 }
2360
2361 idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"),
2362 idx, in, &val);
2363 switch (cond)
2364 {
2365 default:
2366 case EQ: res = val == 0; break;
2367 case NE: res = val != 0; break;
2368 case LT: res = val < 0; break;
2369 case LE: res = val <= 0; break;
2370 case GE: res = val >= 0; break;
2371 case GT: res = val > 0; break;
2372 }
2373
2374 ifi++;
2375 ifstack[ifi].on = ifstack[ifi-1].on ? res: 0;
2376 ifstack[ifi].hadelse = 0;
2377 }
2378
2379 /* Get a string for the MRI IFC or IFNC pseudo-ops. */
2380
2381 static int
2382 get_mri_string (idx, in, val, terminator)
2383 int idx;
2384 sb *in;
2385 sb *val;
2386 int terminator;
2387 {
2388 idx = sb_skip_white (idx, in);
2389
2390 if (idx < in->len
2391 && in->ptr[idx] == '\'')
2392 {
2393 sb_add_char (val, '\'');
2394 for (++idx; idx < in->len; ++idx)
2395 {
2396 sb_add_char (val, in->ptr[idx]);
2397 if (in->ptr[idx] == '\'')
2398 {
2399 ++idx;
2400 if (idx >= in->len
2401 || in->ptr[idx] != '\'')
2402 break;
2403 }
2404 }
2405 idx = sb_skip_white (idx, in);
2406 }
2407 else
2408 {
2409 int i;
2410
2411 while (idx < in->len
2412 && in->ptr[idx] != terminator)
2413 {
2414 sb_add_char (val, in->ptr[idx]);
2415 ++idx;
2416 }
2417 i = val->len - 1;
2418 while (i >= 0 && ISWHITE (val->ptr[i]))
2419 --i;
2420 val->len = i + 1;
2421 }
2422
2423 return idx;
2424 }
2425
2426 /* MRI IFC, IFNC. */
2427
2428 static void
2429 do_ifc (idx, in, ifnc)
2430 int idx;
2431 sb *in;
2432 int ifnc;
2433 {
2434 sb first;
2435 sb second;
2436 int res;
2437
2438 if (ifi >= IFNESTING)
2439 {
2440 FATAL ((stderr, _("IF nesting unreasonable.\n")));
2441 }
2442
2443 sb_new (&first);
2444 sb_new (&second);
2445
2446 idx = get_mri_string (idx, in, &first, ',');
2447
2448 if (idx >= in->len || in->ptr[idx] != ',')
2449 {
2450 ERROR ((stderr, _("Bad format for IF or IFNC.\n")));
2451 return;
2452 }
2453
2454 idx = get_mri_string (idx + 1, in, &second, ';');
2455
2456 res = (first.len == second.len
2457 && strncmp (first.ptr, second.ptr, first.len) == 0);
2458 res ^= ifnc;
2459
2460 ifi++;
2461 ifstack[ifi].on = ifstack[ifi-1].on ? res : 0;
2462 ifstack[ifi].hadelse = 0;
2463 }
2464
2465 /* .ENDR */
2466 static void
2467 do_aendr ()
2468 {
2469 if (!mri)
2470 ERROR ((stderr, _("AENDR without a AREPEAT.\n")));
2471 else
2472 ERROR ((stderr, _("ENDR without a REPT.\n")));
2473 }
2474
2475 /* .AWHILE */
2476
2477 static
2478 void
2479 do_awhile (idx, in)
2480 int idx;
2481 sb *in;
2482 {
2483 int line = linecount ();
2484 sb exp;
2485 sb sub;
2486 int doit;
2487
2488 sb_new (&sub);
2489 sb_new (&exp);
2490
2491 process_assigns (idx, in, &exp);
2492 doit = istrue (0, &exp);
2493
2494 if (! buffer_and_nest ("AWHILE", "AENDW", &sub, get_line))
2495 FATAL ((stderr, _("AWHILE without a AENDW at %d.\n"), line - 1));
2496
2497 /* Turn
2498 .AWHILE exp
2499 foo
2500 .AENDW
2501 into
2502 foo
2503 .AWHILE exp
2504 foo
2505 .ENDW
2506 */
2507
2508 if (doit)
2509 {
2510 int index = include_next_index ();
2511
2512 sb copy;
2513 sb_new (&copy);
2514 sb_add_sb (&copy, &sub);
2515 sb_add_sb (&copy, in);
2516 sb_add_string (&copy, "\n");
2517 sb_add_sb (&copy, &sub);
2518 sb_add_string (&copy, "\t.AENDW\n");
2519 /* Push another WHILE */
2520 include_buf (&exp, &copy, include_while, index);
2521 sb_kill (&copy);
2522 }
2523 sb_kill (&exp);
2524 sb_kill (&sub);
2525 }
2526
2527
2528 /* .AENDW */
2529
2530 static void
2531 do_aendw ()
2532 {
2533 ERROR ((stderr, _("AENDW without a AENDW.\n")));
2534 }
2535
2536
2537 /* .EXITM
2538
2539 Pop things off the include stack until the type and index changes */
2540
2541 static void
2542 do_exitm ()
2543 {
2544 include_type type = sp->type;
2545 if (type == include_repeat
2546 || type == include_while
2547 || type == include_macro)
2548 {
2549 int index = sp->index;
2550 include_pop ();
2551 while (sp->index == index
2552 && sp->type == type)
2553 {
2554 include_pop ();
2555 }
2556 }
2557 }
2558
2559 /* .AREPEAT */
2560
2561 static void
2562 do_arepeat (idx, in)
2563 int idx;
2564 sb *in;
2565 {
2566 int line = linecount ();
2567 sb exp; /* buffer with expression in it */
2568 sb copy; /* expanded repeat block */
2569 sb sub; /* contents of AREPEAT */
2570 int rc;
2571 int ret;
2572 char buffer[30];
2573
2574 sb_new (&exp);
2575 sb_new (&copy);
2576 sb_new (&sub);
2577 process_assigns (idx, in, &exp);
2578 idx = exp_get_abs (_("AREPEAT must have absolute operand.\n"), 0, &exp, &rc);
2579 if (!mri)
2580 ret = buffer_and_nest ("AREPEAT", "AENDR", &sub, get_line);
2581 else
2582 ret = buffer_and_nest ("REPT", "ENDR", &sub, get_line);
2583 if (! ret)
2584 FATAL ((stderr, _("AREPEAT without a AENDR at %d.\n"), line - 1));
2585 if (rc > 0)
2586 {
2587 /* Push back the text following the repeat, and another repeat block
2588 so
2589 .AREPEAT 20
2590 foo
2591 .AENDR
2592 gets turned into
2593 foo
2594 .AREPEAT 19
2595 foo
2596 .AENDR
2597 */
2598 int index = include_next_index ();
2599 sb_add_sb (&copy, &sub);
2600 if (rc > 1)
2601 {
2602 if (!mri)
2603 sprintf (buffer, "\t.AREPEAT %d\n", rc - 1);
2604 else
2605 sprintf (buffer, "\tREPT %d\n", rc - 1);
2606 sb_add_string (&copy, buffer);
2607 sb_add_sb (&copy, &sub);
2608 if (!mri)
2609 sb_add_string (&copy, " .AENDR\n");
2610 else
2611 sb_add_string (&copy, " ENDR\n");
2612 }
2613
2614 include_buf (&exp, &copy, include_repeat, index);
2615 }
2616 sb_kill (&exp);
2617 sb_kill (&sub);
2618 sb_kill (&copy);
2619 }
2620
2621 /* .ENDM */
2622
2623 static void
2624 do_endm ()
2625 {
2626 ERROR ((stderr, _(".ENDM without a matching .MACRO.\n")));
2627 }
2628
2629 /* MRI IRP pseudo-op. */
2630
2631 static void
2632 do_irp (idx, in, irpc)
2633 int idx;
2634 sb *in;
2635 int irpc;
2636 {
2637 const char *err;
2638 sb out;
2639
2640 sb_new (&out);
2641
2642 err = expand_irp (irpc, idx, in, &out, get_line, comment_char);
2643 if (err != NULL)
2644 ERROR ((stderr, "%s\n", err));
2645
2646 fprintf (outfile, "%s", sb_terminate (&out));
2647
2648 sb_kill (&out);
2649 }
2650
2651 /* MACRO PROCESSING */
2652
2653 /* Parse off LOCAL n1, n2,... Invent a label name for it */
2654 static
2655 void
2656 do_local (idx, line)
2657 int idx;
2658 sb *line;
2659 {
2660 ERROR ((stderr, _("LOCAL outside of MACRO")));
2661 }
2662
2663 static void
2664 do_macro (idx, in)
2665 int idx;
2666 sb *in;
2667 {
2668 const char *err;
2669 int line = linecount ();
2670
2671 err = define_macro (idx, in, &label, get_line, (const char **) NULL);
2672 if (err != NULL)
2673 ERROR ((stderr, _("macro at line %d: %s\n"), line - 1, err));
2674 }
2675
2676 static int
2677 macro_op (idx, in)
2678 int idx;
2679 sb *in;
2680 {
2681 const char *err;
2682 sb out;
2683 sb name;
2684
2685 if (! macro_defined)
2686 return 0;
2687
2688 sb_terminate (in);
2689 if (! check_macro (in->ptr + idx, &out, comment_char, &err))
2690 return 0;
2691
2692 if (err != NULL)
2693 ERROR ((stderr, "%s\n", err));
2694
2695 sb_new (&name);
2696 sb_add_string (&name, _("macro expansion"));
2697
2698 include_buf (&name, &out, include_macro, include_next_index ());
2699
2700 sb_kill (&name);
2701 sb_kill (&out);
2702
2703 return 1;
2704 }
2705
2706 /* STRING HANDLING */
2707
2708 static int
2709 getstring (idx, in, acc)
2710 int idx;
2711 sb *in;
2712 sb *acc;
2713 {
2714 idx = sb_skip_white (idx, in);
2715
2716 while (idx < in->len
2717 && (in->ptr[idx] == '"'
2718 || in->ptr[idx] == '<'
2719 || (in->ptr[idx] == '\'' && alternate)))
2720 {
2721 if (in->ptr[idx] == '<')
2722 {
2723 if (alternate || mri)
2724 {
2725 int nest = 0;
2726 idx++;
2727 while ((in->ptr[idx] != '>' || nest)
2728 && idx < in->len)
2729 {
2730 if (in->ptr[idx] == '!')
2731 {
2732 idx++ ;
2733 sb_add_char (acc, in->ptr[idx++]);
2734 }
2735 else {
2736 if (in->ptr[idx] == '>')
2737 nest--;
2738 if (in->ptr[idx] == '<')
2739 nest++;
2740 sb_add_char (acc, in->ptr[idx++]);
2741 }
2742 }
2743 idx++;
2744 }
2745 else {
2746 int code;
2747 idx++;
2748 idx = exp_get_abs (_("Character code in string must be absolute expression.\n"),
2749 idx, in, &code);
2750 sb_add_char (acc, code);
2751
2752 if (in->ptr[idx] != '>')
2753 ERROR ((stderr, _("Missing > for character code.\n")));
2754 idx++;
2755 }
2756 }
2757 else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
2758 {
2759 char tchar = in->ptr[idx];
2760 idx++;
2761 while (idx < in->len)
2762 {
2763 if (alternate && in->ptr[idx] == '!')
2764 {
2765 idx++ ;
2766 sb_add_char (acc, in->ptr[idx++]);
2767 }
2768 else {
2769 if (in->ptr[idx] == tchar)
2770 {
2771 idx++;
2772 if (idx >= in->len || in->ptr[idx] != tchar)
2773 break;
2774 }
2775 sb_add_char (acc, in->ptr[idx]);
2776 idx++;
2777 }
2778 }
2779 }
2780 }
2781
2782 return idx;
2783 }
2784
2785 /* .SDATA[C|Z] <string> */
2786
2787 static
2788 void
2789 do_sdata (idx, in, type)
2790 int idx;
2791 sb *in;
2792 int type;
2793 {
2794 int nc = 0;
2795 int pidx = -1;
2796 sb acc;
2797 sb_new (&acc);
2798 fprintf (outfile, ".byte\t");
2799
2800 while (!eol (idx, in))
2801 {
2802 int i;
2803 sb_reset (&acc);
2804 idx = sb_skip_white (idx, in);
2805 while (!eol (idx, in))
2806 {
2807 pidx = idx = get_any_string (idx, in, &acc, 0, 1);
2808 if (type == 'c')
2809 {
2810 if (acc.len > 255)
2811 {
2812 ERROR ((stderr, _("string for SDATAC longer than 255 characters (%d).\n"), acc.len));
2813 }
2814 fprintf (outfile, "%d", acc.len);
2815 nc = 1;
2816 }
2817
2818 for (i = 0; i < acc.len; i++)
2819 {
2820 if (nc)
2821 {
2822 fprintf (outfile, ",");
2823 }
2824 fprintf (outfile, "%d", acc.ptr[i]);
2825 nc = 1;
2826 }
2827
2828 if (type == 'z')
2829 {
2830 if (nc)
2831 fprintf (outfile, ",");
2832 fprintf (outfile, "0");
2833 }
2834 idx = sb_skip_comma (idx, in);
2835 if (idx == pidx) break;
2836 }
2837 if (!alternate && in->ptr[idx] != ',' && idx != in->len)
2838 {
2839 fprintf (outfile, "\n");
2840 ERROR ((stderr, _("illegal character in SDATA line (0x%x).\n"), in->ptr[idx]));
2841 break;
2842 }
2843 idx++;
2844 }
2845 sb_kill (&acc);
2846 fprintf (outfile, "\n");
2847 }
2848
2849 /* .SDATAB <count> <string> */
2850
2851 static void
2852 do_sdatab (idx, in)
2853 int idx;
2854 sb *in;
2855 {
2856 int repeat;
2857 int i;
2858 sb acc;
2859 sb_new (&acc);
2860
2861 idx = exp_get_abs (_("Must have absolute SDATAB repeat count.\n"), idx, in, &repeat);
2862 if (repeat <= 0)
2863 {
2864 ERROR ((stderr, _("Must have positive SDATAB repeat count (%d).\n"), repeat));
2865 repeat = 1;
2866 }
2867
2868 idx = sb_skip_comma (idx, in);
2869 idx = getstring (idx, in, &acc);
2870
2871 for (i = 0; i < repeat; i++)
2872 {
2873 if (i)
2874 fprintf (outfile, "\t");
2875 fprintf (outfile, ".byte\t");
2876 sb_print (outfile, &acc);
2877 fprintf (outfile, "\n");
2878 }
2879 sb_kill (&acc);
2880
2881 }
2882
2883 static int
2884 new_file (name)
2885 const char *name;
2886 {
2887 FILE *newone = fopen (name, "r");
2888 if (!newone)
2889 return 0;
2890
2891 if (isp == MAX_INCLUDES)
2892 FATAL ((stderr, _("Unreasonable include depth (%ld).\n"), (long) isp));
2893
2894 sp++;
2895 sp->handle = newone;
2896
2897 sb_new (&sp->name);
2898 sb_add_string (&sp->name, name);
2899
2900 sp->linecount = 1;
2901 sp->pushback_index = 0;
2902 sp->type = include_file;
2903 sp->index = 0;
2904 sb_new (&sp->pushback);
2905 return 1;
2906 }
2907
2908 static void
2909 do_include (idx, in)
2910 int idx;
2911 sb *in;
2912 {
2913 sb t;
2914 sb cat;
2915 include_path *includes;
2916
2917 sb_new (&t);
2918 sb_new (&cat);
2919
2920 if (! mri)
2921 idx = getstring (idx, in, &t);
2922 else
2923 {
2924 idx = sb_skip_white (idx, in);
2925 while (idx < in->len && ! ISWHITE (in->ptr[idx]))
2926 {
2927 sb_add_char (&t, in->ptr[idx]);
2928 ++idx;
2929 }
2930 }
2931
2932 for (includes = paths_head; includes; includes = includes->next)
2933 {
2934 sb_reset (&cat);
2935 sb_add_sb (&cat, &includes->path);
2936 sb_add_char (&cat, '/');
2937 sb_add_sb (&cat, &t);
2938 if (new_file (sb_name (&cat)))
2939 {
2940 break;
2941 }
2942 }
2943 if (!includes)
2944 {
2945 if (! new_file (sb_name (&t)))
2946 FATAL ((stderr, _("Can't open include file `%s'.\n"), sb_name (&t)));
2947 }
2948 sb_kill (&cat);
2949 sb_kill (&t);
2950 }
2951
2952 static void
2953 include_pop ()
2954 {
2955 if (sp != include_stack)
2956 {
2957 if (sp->handle)
2958 fclose (sp->handle);
2959 sp--;
2960 }
2961 }
2962
2963 /* Get the next character from the include stack. If there's anything
2964 in the pushback buffer, take that first. If we're at eof, pop from
2965 the stack and try again. Keep the linecount up to date. */
2966
2967 static int
2968 get ()
2969 {
2970 int r;
2971
2972 if (sp->pushback.len != sp->pushback_index)
2973 {
2974 r = (char) (sp->pushback.ptr[sp->pushback_index++]);
2975 /* When they've all gone, reset the pointer */
2976 if (sp->pushback_index == sp->pushback.len)
2977 {
2978 sp->pushback.len = 0;
2979 sp->pushback_index = 0;
2980 }
2981 }
2982 else if (sp->handle)
2983 {
2984 r = getc (sp->handle);
2985 }
2986 else
2987 r = EOF;
2988
2989 if (r == EOF && isp)
2990 {
2991 include_pop ();
2992 r = get ();
2993 while (r == EOF && isp)
2994 {
2995 include_pop ();
2996 r = get ();
2997 }
2998 return r;
2999 }
3000 if (r == '\n')
3001 {
3002 sp->linecount++;
3003 }
3004
3005 return r;
3006 }
3007
3008 static int
3009 linecount ()
3010 {
3011 return sp->linecount;
3012 }
3013
3014 static int
3015 include_next_index ()
3016 {
3017 static int index;
3018 if (!unreasonable
3019 && index > MAX_REASONABLE)
3020 FATAL ((stderr, _("Unreasonable expansion (-u turns off check).\n")));
3021 return ++index;
3022 }
3023
3024
3025 /* Initialize the chartype vector. */
3026
3027 static void
3028 chartype_init ()
3029 {
3030 int x;
3031 for (x = 0; x < 256; x++)
3032 {
3033 if (isalpha (x) || x == '_' || x == '$')
3034 chartype[x] |= FIRSTBIT;
3035
3036 if (mri && x == '.')
3037 chartype[x] |= FIRSTBIT;
3038
3039 if (isdigit (x) || isalpha (x) || x == '_' || x == '$')
3040 chartype[x] |= NEXTBIT;
3041
3042 if (x == ' ' || x == '\t' || x == ',' || x == '"' || x == ';'
3043 || x == '"' || x == '<' || x == '>' || x == ')' || x == '(')
3044 chartype[x] |= SEPBIT;
3045
3046 if (x == 'b' || x == 'B'
3047 || x == 'q' || x == 'Q'
3048 || x == 'h' || x == 'H'
3049 || x == 'd' || x == 'D')
3050 chartype [x] |= BASEBIT;
3051
3052 if (x == ' ' || x == '\t')
3053 chartype[x] |= WHITEBIT;
3054
3055 if (x == comment_char)
3056 chartype[x] |= COMMENTBIT;
3057 }
3058 }
3059
3060
3061
3062 /* What to do with all the keywords */
3063 #define PROCESS 0x1000 /* Run substitution over the line */
3064 #define LAB 0x2000 /* Spit out the label */
3065
3066 #define K_EQU (PROCESS|1)
3067 #define K_ASSIGN (PROCESS|2)
3068 #define K_REG (PROCESS|3)
3069 #define K_ORG (PROCESS|4)
3070 #define K_RADIX (PROCESS|5)
3071 #define K_DATA (LAB|PROCESS|6)
3072 #define K_DATAB (LAB|PROCESS|7)
3073 #define K_SDATA (LAB|PROCESS|8)
3074 #define K_SDATAB (LAB|PROCESS|9)
3075 #define K_SDATAC (LAB|PROCESS|10)
3076 #define K_SDATAZ (LAB|PROCESS|11)
3077 #define K_RES (LAB|PROCESS|12)
3078 #define K_SRES (LAB|PROCESS|13)
3079 #define K_SRESC (LAB|PROCESS|14)
3080 #define K_SRESZ (LAB|PROCESS|15)
3081 #define K_EXPORT (LAB|PROCESS|16)
3082 #define K_GLOBAL (LAB|PROCESS|17)
3083 #define K_PRINT (LAB|PROCESS|19)
3084 #define K_FORM (LAB|PROCESS|20)
3085 #define K_HEADING (LAB|PROCESS|21)
3086 #define K_PAGE (LAB|PROCESS|22)
3087 #define K_IMPORT (LAB|PROCESS|23)
3088 #define K_PROGRAM (LAB|PROCESS|24)
3089 #define K_END (PROCESS|25)
3090 #define K_INCLUDE (PROCESS|26)
3091 #define K_IGNORED (PROCESS|27)
3092 #define K_ASSIGNA (PROCESS|28)
3093 #define K_ASSIGNC (29)
3094 #define K_AIF (PROCESS|30)
3095 #define K_AELSE (PROCESS|31)
3096 #define K_AENDI (PROCESS|32)
3097 #define K_AREPEAT (PROCESS|33)
3098 #define K_AENDR (PROCESS|34)
3099 #define K_AWHILE (35)
3100 #define K_AENDW (PROCESS|36)
3101 #define K_EXITM (37)
3102 #define K_MACRO (PROCESS|38)
3103 #define K_ENDM (39)
3104 #define K_ALIGN (PROCESS|LAB|40)
3105 #define K_ALTERNATE (41)
3106 #define K_DB (LAB|PROCESS|42)
3107 #define K_DW (LAB|PROCESS|43)
3108 #define K_DL (LAB|PROCESS|44)
3109 #define K_LOCAL (45)
3110 #define K_IFEQ (PROCESS|46)
3111 #define K_IFNE (PROCESS|47)
3112 #define K_IFLT (PROCESS|48)
3113 #define K_IFLE (PROCESS|49)
3114 #define K_IFGE (PROCESS|50)
3115 #define K_IFGT (PROCESS|51)
3116 #define K_IFC (PROCESS|52)
3117 #define K_IFNC (PROCESS|53)
3118 #define K_IRP (PROCESS|54)
3119 #define K_IRPC (PROCESS|55)
3120
3121
3122 struct keyword
3123 {
3124 char *name;
3125 int code;
3126 int extra;
3127 };
3128
3129 static struct keyword kinfo[] =
3130 {
3131 { "EQU", K_EQU, 0 },
3132 { "ALTERNATE", K_ALTERNATE, 0 },
3133 { "ASSIGN", K_ASSIGN, 0 },
3134 { "REG", K_REG, 0 },
3135 { "ORG", K_ORG, 0 },
3136 { "RADIX", K_RADIX, 0 },
3137 { "DATA", K_DATA, 0 },
3138 { "DB", K_DB, 0 },
3139 { "DW", K_DW, 0 },
3140 { "DL", K_DL, 0 },
3141 { "DATAB", K_DATAB, 0 },
3142 { "SDATA", K_SDATA, 0 },
3143 { "SDATAB", K_SDATAB, 0 },
3144 { "SDATAZ", K_SDATAZ, 0 },
3145 { "SDATAC", K_SDATAC, 0 },
3146 { "RES", K_RES, 0 },
3147 { "SRES", K_SRES, 0 },
3148 { "SRESC", K_SRESC, 0 },
3149 { "SRESZ", K_SRESZ, 0 },
3150 { "EXPORT", K_EXPORT, 0 },
3151 { "GLOBAL", K_GLOBAL, 0 },
3152 { "PRINT", K_PRINT, 0 },
3153 { "FORM", K_FORM, 0 },
3154 { "HEADING", K_HEADING, 0 },
3155 { "PAGE", K_PAGE, 0 },
3156 { "PROGRAM", K_IGNORED, 0 },
3157 { "END", K_END, 0 },
3158 { "INCLUDE", K_INCLUDE, 0 },
3159 { "ASSIGNA", K_ASSIGNA, 0 },
3160 { "ASSIGNC", K_ASSIGNC, 0 },
3161 { "AIF", K_AIF, 0 },
3162 { "AELSE", K_AELSE, 0 },
3163 { "AENDI", K_AENDI, 0 },
3164 { "AREPEAT", K_AREPEAT, 0 },
3165 { "AENDR", K_AENDR, 0 },
3166 { "EXITM", K_EXITM, 0 },
3167 { "MACRO", K_MACRO, 0 },
3168 { "ENDM", K_ENDM, 0 },
3169 { "AWHILE", K_AWHILE, 0 },
3170 { "ALIGN", K_ALIGN, 0 },
3171 { "AENDW", K_AENDW, 0 },
3172 { "ALTERNATE", K_ALTERNATE, 0 },
3173 { "LOCAL", K_LOCAL, 0 },
3174 { NULL, 0, 0 }
3175 };
3176
3177 /* Although the conditional operators are handled by gas, we need to
3178 handle them here as well, in case they are used in a recursive
3179 macro to end the recursion. */
3180
3181 static struct keyword mrikinfo[] =
3182 {
3183 { "IFEQ", K_IFEQ, 0 },
3184 { "IFNE", K_IFNE, 0 },
3185 { "IFLT", K_IFLT, 0 },
3186 { "IFLE", K_IFLE, 0 },
3187 { "IFGE", K_IFGE, 0 },
3188 { "IFGT", K_IFGT, 0 },
3189 { "IFC", K_IFC, 0 },
3190 { "IFNC", K_IFNC, 0 },
3191 { "ELSEC", K_AELSE, 0 },
3192 { "ENDC", K_AENDI, 0 },
3193 { "MEXIT", K_EXITM, 0 },
3194 { "REPT", K_AREPEAT, 0 },
3195 { "IRP", K_IRP, 0 },
3196 { "IRPC", K_IRPC, 0 },
3197 { "ENDR", K_AENDR, 0 },
3198 { NULL, 0, 0 }
3199 };
3200
3201 /* Look for a pseudo op on the line. If one's there then call
3202 its handler. */
3203
3204 static int
3205 process_pseudo_op (idx, line, acc)
3206 int idx;
3207 sb *line;
3208 sb *acc;
3209 {
3210 int oidx = idx;
3211
3212 if (line->ptr[idx] == '.' || alternate || mri)
3213 {
3214 /* Scan forward and find pseudo name */
3215 char *in;
3216 hash_entry *ptr;
3217
3218 char *s;
3219 char *e;
3220 if (line->ptr[idx] == '.')
3221 idx++;
3222 in = line->ptr + idx;
3223 s = in;
3224 e = s;
3225 sb_reset (acc);
3226
3227 while (idx < line->len && *e && ISFIRSTCHAR (*e))
3228 {
3229 sb_add_char (acc, *e);
3230 e++;
3231 idx++;
3232 }
3233
3234 ptr = hash_lookup (&keyword_hash_table, acc);
3235
3236 if (!ptr)
3237 {
3238 #if 0
3239 /* This one causes lots of pain when trying to preprocess
3240 ordinary code */
3241 WARNING ((stderr, _("Unrecognised pseudo op `%s'.\n"), sb_name (acc)));
3242 #endif
3243 return 0;
3244 }
3245 if (ptr->value.i & LAB)
3246 { /* output the label */
3247 if (label.len)
3248 {
3249 fprintf (outfile, "%s:\t", sb_name (&label));
3250 }
3251 else
3252 fprintf (outfile, "\t");
3253 }
3254
3255 if (mri && ptr->value.i == K_END)
3256 {
3257 sb t;
3258
3259 sb_new (&t);
3260 sb_add_buffer (&t, line->ptr + oidx, idx - oidx);
3261 fprintf (outfile, "\t%s", sb_name (&t));
3262 sb_kill (&t);
3263 }
3264
3265 if (ptr->value.i & PROCESS)
3266 {
3267 /* Polish the rest of the line before handling the pseudo op */
3268 #if 0
3269 strip_comments(line);
3270 #endif
3271 sb_reset (acc);
3272 process_assigns (idx, line, acc);
3273 sb_reset(line);
3274 change_base (0, acc, line);
3275 idx = 0;
3276 }
3277 if (!condass_on ())
3278 {
3279 switch (ptr->value.i)
3280 {
3281 case K_AIF:
3282 do_aif (idx, line);
3283 break;
3284 case K_AELSE:
3285 do_aelse ();
3286 break;
3287 case K_AENDI:
3288 do_aendi ();
3289 break;
3290 }
3291 return 1;
3292 }
3293 else
3294 {
3295 switch (ptr->value.i)
3296 {
3297 case K_ALTERNATE:
3298 alternate = 1;
3299 macro_init (1, mri, 0, exp_get_abs);
3300 return 1;
3301 case K_AELSE:
3302 do_aelse ();
3303 return 1;
3304 case K_AENDI:
3305 do_aendi ();
3306 return 1;
3307 case K_ORG:
3308 ERROR ((stderr, _("ORG command not allowed.\n")));
3309 break;
3310 case K_RADIX:
3311 do_radix (line);
3312 return 1;
3313 case K_DB:
3314 do_data (idx, line, 1);
3315 return 1;
3316 case K_DW:
3317 do_data (idx, line, 2);
3318 return 1;
3319 case K_DL:
3320 do_data (idx, line, 4);
3321 return 1;
3322 case K_DATA:
3323 do_data (idx, line, 0);
3324 return 1;
3325 case K_DATAB:
3326 do_datab (idx, line);
3327 return 1;
3328 case K_SDATA:
3329 do_sdata (idx, line, 0);
3330 return 1;
3331 case K_SDATAB:
3332 do_sdatab (idx, line);
3333 return 1;
3334 case K_SDATAC:
3335 do_sdata (idx, line, 'c');
3336 return 1;
3337 case K_SDATAZ:
3338 do_sdata (idx, line, 'z');
3339 return 1;
3340 case K_ASSIGN:
3341 do_assign (0, 0, line);
3342 return 1;
3343 case K_AIF:
3344 do_aif (idx, line);
3345 return 1;
3346 case K_AREPEAT:
3347 do_arepeat (idx, line);
3348 return 1;
3349 case K_AENDW:
3350 do_aendw ();
3351 return 1;
3352 case K_AWHILE:
3353 do_awhile (idx, line);
3354 return 1;
3355 case K_AENDR:
3356 do_aendr ();
3357 return 1;
3358 case K_EQU:
3359 do_assign (1, idx, line);
3360 return 1;
3361 case K_ALIGN:
3362 do_align (idx, line);
3363 return 1;
3364 case K_RES:
3365 do_res (idx, line, 0);
3366 return 1;
3367 case K_SRES:
3368 do_res (idx, line, 's');
3369 return 1;
3370 case K_INCLUDE:
3371 do_include (idx, line);
3372 return 1;
3373 case K_LOCAL:
3374 do_local (idx, line);
3375 return 1;
3376 case K_MACRO:
3377 do_macro (idx, line);
3378 return 1;
3379 case K_ENDM:
3380 do_endm ();
3381 return 1;
3382 case K_SRESC:
3383 do_res (idx, line, 'c');
3384 return 1;
3385 case K_PRINT:
3386 do_print (idx, line);
3387 return 1;
3388 case K_FORM:
3389 do_form (idx, line);
3390 return 1;
3391 case K_HEADING:
3392 do_heading (idx, line);
3393 return 1;
3394 case K_PAGE:
3395 do_page ();
3396 return 1;
3397 case K_GLOBAL:
3398 case K_EXPORT:
3399 do_export (line);
3400 return 1;
3401 case K_IMPORT:
3402 return 1;
3403 case K_SRESZ:
3404 do_res (idx, line, 'z');
3405 return 1;
3406 case K_IGNORED:
3407 return 1;
3408 case K_END:
3409 do_end (line);
3410 return 1;
3411 case K_ASSIGNA:
3412 do_assigna (idx, line);
3413 return 1;
3414 case K_ASSIGNC:
3415 do_assignc (idx, line);
3416 return 1;
3417 case K_EXITM:
3418 do_exitm ();
3419 return 1;
3420 case K_REG:
3421 do_reg (idx, line);
3422 return 1;
3423 case K_IFEQ:
3424 do_if (idx, line, EQ);
3425 return 1;
3426 case K_IFNE:
3427 do_if (idx, line, NE);
3428 return 1;
3429 case K_IFLT:
3430 do_if (idx, line, LT);
3431 return 1;
3432 case K_IFLE:
3433 do_if (idx, line, LE);
3434 return 1;
3435 case K_IFGE:
3436 do_if (idx, line, GE);
3437 return 1;
3438 case K_IFGT:
3439 do_if (idx, line, GT);
3440 return 1;
3441 case K_IFC:
3442 do_ifc (idx, line, 0);
3443 return 1;
3444 case K_IFNC:
3445 do_ifc (idx, line, 1);
3446 return 1;
3447 case K_IRP:
3448 do_irp (idx, line, 0);
3449 return 1;
3450 case K_IRPC:
3451 do_irp (idx, line, 1);
3452 return 1;
3453 }
3454 }
3455 }
3456 return 0;
3457 }
3458
3459
3460
3461 /* Add a keyword to the hash table. */
3462
3463 static void
3464 add_keyword (name, code)
3465 const char *name;
3466 int code;
3467 {
3468 sb label;
3469 int j;
3470
3471 sb_new (&label);
3472 sb_add_string (&label, name);
3473
3474 hash_add_to_int_table (&keyword_hash_table, &label, code);
3475
3476 sb_reset (&label);
3477 for (j = 0; name[j]; j++)
3478 sb_add_char (&label, name[j] - 'A' + 'a');
3479 hash_add_to_int_table (&keyword_hash_table, &label, code);
3480
3481 sb_kill (&label);
3482 }
3483
3484 /* Build the keyword hash table - put each keyword in the table twice,
3485 once upper and once lower case.*/
3486
3487 static void
3488 process_init ()
3489 {
3490 int i;
3491
3492 for (i = 0; kinfo[i].name; i++)
3493 add_keyword (kinfo[i].name, kinfo[i].code);
3494
3495 if (mri)
3496 {
3497 for (i = 0; mrikinfo[i].name; i++)
3498 add_keyword (mrikinfo[i].name, mrikinfo[i].code);
3499 }
3500 }
3501
3502
3503 static void
3504 do_define (string)
3505 const char *string;
3506 {
3507 sb label;
3508 int res = 1;
3509 hash_entry *ptr;
3510 sb_new (&label);
3511
3512
3513 while (*string)
3514 {
3515 if (*string == '=')
3516 {
3517 sb value;
3518 sb_new (&value);
3519 string++;
3520 while (*string)
3521 {
3522 sb_add_char (&value, *string);
3523 string++;
3524 }
3525 exp_get_abs (_("Invalid expression on command line.\n"), 0, &value, &res);
3526 sb_kill (&value);
3527 break;
3528 }
3529 sb_add_char (&label, *string);
3530
3531 string ++;
3532 }
3533
3534 ptr = hash_create (&vars, &label);
3535 free_old_entry (ptr);
3536 ptr->type = hash_integer;
3537 ptr->value.i = res;
3538 sb_kill (&label);
3539 }
3540 char *program_name;
3541
3542 /* The list of long options. */
3543 static struct option long_options[] =
3544 {
3545 { "alternate", no_argument, 0, 'a' },
3546 { "include", required_argument, 0, 'I' },
3547 { "commentchar", required_argument, 0, 'c' },
3548 { "copysource", no_argument, 0, 's' },
3549 { "debug", no_argument, 0, 'd' },
3550 { "help", no_argument, 0, 'h' },
3551 { "mri", no_argument, 0, 'M' },
3552 { "output", required_argument, 0, 'o' },
3553 { "print", no_argument, 0, 'p' },
3554 { "unreasonable", no_argument, 0, 'u' },
3555 { "version", no_argument, 0, 'v' },
3556 { "define", required_argument, 0, 'd' },
3557 { NULL, no_argument, 0, 0 }
3558 };
3559
3560 /* Show a usage message and exit. */
3561 static void
3562 show_usage (file, status)
3563 FILE *file;
3564 int status;
3565 {
3566 fprintf (file, _("\
3567 Usage: %s \n\
3568 [-a] [--alternate] enter alternate macro mode\n\
3569 [-c char] [--commentchar char] change the comment character from !\n\
3570 [-d] [--debug] print some debugging info\n\
3571 [-h] [--help] print this message\n\
3572 [-M] [--mri] enter MRI compatibility mode\n\
3573 [-o out] [--output out] set the output file\n\
3574 [-p] [--print] print line numbers\n"), program_name);
3575 fprintf (file, _("\
3576 [-s] [--copysource] copy source through as comments \n\
3577 [-u] [--unreasonable] allow unreasonable nesting\n\
3578 [-v] [--version] print the program version\n\
3579 [-Dname=value] create preprocessor variable called name, with value\n\
3580 [-Ipath] add to include path list\n\
3581 [in-file]\n"));
3582 if (status == 0)
3583 printf (_("\nReport bugs to bug-gnu-utils@gnu.org\n"));
3584 exit (status);
3585 }
3586
3587 /* Display a help message and exit. */
3588 static void
3589 show_help ()
3590 {
3591 printf (_("%s: Gnu Assembler Macro Preprocessor\n"),
3592 program_name);
3593 show_usage (stdout, 0);
3594 }
3595
3596 int
3597 main (argc, argv)
3598 int argc;
3599 char **argv;
3600 {
3601 int opt;
3602 char *out_name = 0;
3603 sp = include_stack;
3604
3605 ifstack[0].on = 1;
3606 ifi = 0;
3607
3608 #ifdef HAVE_SETLOCALE
3609 setlocale (LC_MESSAGES, "");
3610 #endif
3611 bindtextdomain (PACKAGE, LOCALEDIR);
3612 textdomain (PACKAGE);
3613
3614 program_name = argv[0];
3615 xmalloc_set_program_name (program_name);
3616
3617 hash_new_table (101, &keyword_hash_table);
3618 hash_new_table (101, &assign_hash_table);
3619 hash_new_table (101, &vars);
3620
3621 sb_new (&label);
3622
3623 while ((opt = getopt_long (argc, argv, "I:sdhavc:upo:D:M", long_options,
3624 (int *) NULL))
3625 != EOF)
3626 {
3627 switch (opt)
3628 {
3629 case 'o':
3630 out_name = optarg;
3631 break;
3632 case 'u':
3633 unreasonable = 1;
3634 break;
3635 case 'I':
3636 {
3637 include_path *p = (include_path *) xmalloc (sizeof (include_path));
3638 p->next = NULL;
3639 sb_new (&p->path);
3640 sb_add_string (&p->path, optarg);
3641 if (paths_tail)
3642 paths_tail->next = p;
3643 else
3644 paths_head = p;
3645 paths_tail = p;
3646 }
3647 break;
3648 case 'p':
3649 print_line_number = 1;
3650 break;
3651 case 'c':
3652 comment_char = optarg[0];
3653 break;
3654 case 'a':
3655 alternate = 1;
3656 break;
3657 case 's':
3658 copysource = 1;
3659 break;
3660 case 'd':
3661 stats = 1;
3662 break;
3663 case 'D':
3664 do_define (optarg);
3665 break;
3666 case 'M':
3667 mri = 1;
3668 comment_char = ';';
3669 break;
3670 case 'h':
3671 show_help ();
3672 /*NOTREACHED*/
3673 case 'v':
3674 /* This output is intended to follow the GNU standards document. */
3675 printf (_("GNU assembler pre-processor %s\n"), program_version);
3676 printf (_("Copyright 1996 Free Software Foundation, Inc.\n"));
3677 printf (_("\
3678 This program is free software; you may redistribute it under the terms of\n\
3679 the GNU General Public License. This program has absolutely no warranty.\n"));
3680 exit (0);
3681 /*NOTREACHED*/
3682 case 0:
3683 break;
3684 default:
3685 show_usage (stderr, 1);
3686 /*NOTREACHED*/
3687 }
3688 }
3689
3690 process_init ();
3691
3692 macro_init (alternate, mri, 0, exp_get_abs);
3693
3694 if (out_name) {
3695 outfile = fopen (out_name, "w");
3696 if (!outfile)
3697 {
3698 fprintf (stderr, _("%s: Can't open output file `%s'.\n"),
3699 program_name, out_name);
3700 exit (1);
3701 }
3702 }
3703 else {
3704 outfile = stdout;
3705 }
3706
3707 chartype_init ();
3708 if (!outfile)
3709 outfile = stdout;
3710
3711 /* Process all the input files */
3712
3713 while (optind < argc)
3714 {
3715 if (new_file (argv[optind]))
3716 {
3717 process_file ();
3718 }
3719 else
3720 {
3721 fprintf (stderr, _("%s: Can't open input file `%s'.\n"),
3722 program_name, argv[optind]);
3723 exit (1);
3724 }
3725 optind++;
3726 }
3727
3728 quit ();
3729 return 0;
3730 }
3731
3732 /* This function is used because an abort in some of the other files
3733 may be compiled into as_abort because they include as.h. */
3734
3735 void
3736 as_abort (file, line, fn)
3737 const char *file, *fn;
3738 int line;
3739 {
3740 fprintf (stderr, _("Internal error, aborting at %s line %d"), file, line);
3741 if (fn)
3742 fprintf (stderr, " in %s", fn);
3743 fprintf (stderr, _("\nPlease report this bug.\n"));
3744 exit (1);
3745 }
This page took 0.149752 seconds and 4 git commands to generate.