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