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