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