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