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