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