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