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