]> git.pld-linux.org Git - packages/binutils.git/blame - binutils-gasp.patch
- added gas-alpha-segv patch; release 3
[packages/binutils.git] / binutils-gasp.patch
CommitLineData
2859501d
JB
1diff -Nur binutils-2.13.90.0.18.orig/gas/Makefile.am binutils-2.13.90.0.18/gas/Makefile.am
2--- binutils-2.13.90.0.18.orig/gas/Makefile.am Sun Feb 2 03:21:17 2003
3+++ binutils-2.13.90.0.18/gas/Makefile.am Sun Feb 2 12:25:10 2003
4@@ -197,7 +197,7 @@
5 symbols.c \
6 write.c
7
8-CFILES = $(GAS_CFILES) itbl-ops.c
9+CFILES = $(GAS_CFILES) gasp.c itbl-ops.c
10
11 HFILES = \
12 as.h \
13@@ -452,7 +452,8 @@
14
15 # Note: GASP is now deprecated and has been removed. It is still
16 # available in the CVS archive or older binutils releases if it is needed.
17-noinst_PROGRAMS = as-new
18+# ...and it is needed for few packages in distribution.
19+noinst_PROGRAMS = as-new gasp-new
20 noinst_SCRIPTS = $(GDBINIT)
21 EXTRA_SCRIPTS = .gdbinit
22
23@@ -515,6 +516,10 @@
24 as.h asintl.h bignum.h bit_fix.h config.h emul.h expr.h flonum.h \
25 frags.h hash.h listing.h obj.h read.h symbols.h tc.h write.h
26
27+gasp_new_SOURCES = gasp.c macro.c sb.c hash.c
28+gasp_new_LDADD = ../libiberty/libiberty.a $(INTLLIBS)
29+gasp_new_DEPENDENCIES = ../libiberty/libiberty.a $(INTLDEPS)
30+
31 EXPECT = `if [ -f $${rootme}/../expect/expect ] ; then \
32 echo $${rootme}/../expect/expect ; \
33 else echo expect ; fi`
34@@ -2416,6 +2421,8 @@
35 $(INCDIR)/obstack.h subsegs.h struc-symbol.h
36 write.o: write.c $(INCDIR)/symcat.h subsegs.h $(INCDIR)/obstack.h \
37 output-file.h dwarf2dbg.h
38+gasp.o: gasp.c $(INCDIR)/getopt.h $(INCDIR)/safe-ctype.h \
39+ sb.h macro.h $(INCDIR)/xregex.h $(INCDIR)/xregex2.h
40 itbl-ops.o: itbl-ops.c itbl-ops.h $(INCDIR)/symcat.h
41 e-crisaout.o: $(srcdir)/config/e-crisaout.c $(INCDIR)/symcat.h \
42 emul-target.h
f8e97439
JB
43--- binutils-2.14.90.0.7/gas/Makefile.in.orig 2003-10-29 18:37:48.000000000 +0100
44+++ binutils-2.14.90.0.7/gas/Makefile.in 2003-11-04 00:08:05.641363288 +0100
45@@ -365,7 +365,7 @@
2859501d
JB
46 write.c
47
48
49-CFILES = $(GAS_CFILES) itbl-ops.c
50+CFILES = $(GAS_CFILES) gasp.c itbl-ops.c
51
52 HFILES = \
53 as.h \
f8e97439 54@@ -631,7 +631,8 @@
2859501d
JB
55
56 # Note: GASP is now deprecated and has been removed. It is still
57 # available in the CVS archive or older binutils releases if it is needed.
58-noinst_PROGRAMS = as-new
59+# ...and it is needed for few packages in distribution.
60+noinst_PROGRAMS = as-new gasp-new
61 noinst_SCRIPTS = $(GDBINIT)
62 EXTRA_SCRIPTS = .gdbinit
63
f8e97439 64@@ -678,6 +679,10 @@
2859501d
JB
65 $(extra_objects) $(GASLIBS) $(INTLDEPS)
66
67
68+gasp_new_SOURCES = gasp.c macro.c sb.c hash.c
69+gasp_new_LDADD = ../libiberty/libiberty.a $(INTLLIBS)
70+gasp_new_DEPENDENCIES = ../libiberty/libiberty.a $(INTLDEPS)
71+
72 EXPECT = `if [ -f $${rootme}/../expect/expect ] ; then \
73 echo $${rootme}/../expect/expect ; \
74 else echo expect ; fi`
f8e97439 75@@ -2515,7 +2520,7 @@
2859501d 76 CONFIG_HEADER = config.h
f8e97439
JB
77 CONFIG_CLEAN_FILES = gdb.ini .gdbinit po/Makefile.in
78 EXTRA_PROGRAMS = itbl-test$(EXEEXT)
79-noinst_PROGRAMS = as-new$(EXEEXT)
80+noinst_PROGRAMS = as-new$(EXEEXT) gasp-new$(EXEEXT)
81 PROGRAMS = $(noinst_PROGRAMS)
82
83 am__objects_1 = app.$(OBJEXT) as.$(OBJEXT) atof-generic.$(OBJEXT) \
84@@ -2531,6 +2536,10 @@
85 am_as_new_OBJECTS = $(am__objects_1)
86 as_new_OBJECTS = $(am_as_new_OBJECTS)
87 as_new_LDFLAGS =
88+am_gasp_new_OBJECTS = gasp.$(OBJEXT) macro.$(OBJEXT) sb.$(OBJEXT) \
89+ hash.$(OBJEXT)
90+gasp_new_OBJECTS = $(am_gasp_new_OBJECTS)
2859501d 91+gasp_new_LDFLAGS =
f8e97439
JB
92 am_itbl_test_OBJECTS = itbl-parse.$(OBJEXT) itbl-lex.$(OBJEXT)
93 itbl_test_OBJECTS = $(am_itbl_test_OBJECTS)
94 itbl_test_DEPENDENCIES = itbl-tops.o itbl-test.o \
95@@ -2562,7 +2571,7 @@
96 install-data-recursive install-exec-recursive \
97 installdirs-recursive install-recursive uninstall-recursive \
98 check-recursive installcheck-recursive
99-SOURCES = $(as_new_SOURCES) $(EXTRA_as_new_SOURCES) $(itbl_test_SOURCES)
100+SOURCES = $(as_new_SOURCES) $(EXTRA_as_new_SOURCES) $(itbl_test_SOURCES) $(gasp_new_SOURCES)
101
102 all: config.h
103 $(MAKE) $(AM_MAKEFLAGS) all-recursive
104@@ -2616,6 +2625,9 @@
105 as-new$(EXEEXT): $(as_new_OBJECTS) $(as_new_DEPENDENCIES)
106 @rm -f as-new$(EXEEXT)
107 $(LINK) $(as_new_LDFLAGS) $(as_new_OBJECTS) $(as_new_LDADD) $(LIBS)
2859501d
JB
108+gasp-new$(EXEEXT): $(gasp_new_OBJECTS) $(gasp_new_DEPENDENCIES)
109+ @rm -f gasp-new$(EXEEXT)
110+ $(LINK) $(gasp_new_LDFLAGS) $(gasp_new_OBJECTS) $(gasp_new_LDADD) $(LIBS)
f8e97439 111 itbl-test$(EXEEXT): $(itbl_test_OBJECTS) $(itbl_test_DEPENDENCIES)
2859501d
JB
112 @rm -f itbl-test$(EXEEXT)
113 $(LINK) $(itbl_test_LDFLAGS) $(itbl_test_OBJECTS) $(itbl_test_LDADD) $(LIBS)
f8e97439 114@@ -3387,6 +3399,8 @@
2859501d
JB
115 $(INCDIR)/obstack.h subsegs.h struc-symbol.h
116 write.o: write.c $(INCDIR)/symcat.h subsegs.h $(INCDIR)/obstack.h \
117 output-file.h dwarf2dbg.h
118+gasp.o: gasp.c $(INCDIR)/getopt.h $(INCDIR)/safe-ctype.h \
119+ sb.h macro.h $(INCDIR)/xregex.h $(INCDIR)/xregex2.h
120 itbl-ops.o: itbl-ops.c itbl-ops.h $(INCDIR)/symcat.h
121 e-crisaout.o: $(srcdir)/config/e-crisaout.c $(INCDIR)/symcat.h \
122 emul-target.h
123diff -Nur binutils-2.13.90.0.18.orig/gas/doc/Makefile.am binutils-2.13.90.0.18/gas/doc/Makefile.am
124--- binutils-2.13.90.0.18.orig/gas/doc/Makefile.am Sun Feb 2 03:21:17 2003
125+++ binutils-2.13.90.0.18/gas/doc/Makefile.am Sun Feb 2 12:35:43 2003
126@@ -15,7 +15,7 @@
127
128 man_MANS = as.1
129
130-info_TEXINFOS = as.texinfo
f8e97439 131+info_TEXINFOS = as.texinfo gasp.texinfo
2859501d
JB
132
133 asconfig.texi: $(CONFIG).texi
134 rm -f asconfig.texi
f8e97439
JB
135--- binutils-2.14.90.0.7/gas/doc/Makefile.in.orig 2003-10-29 18:37:48.000000000 +0100
136+++ binutils-2.14.90.0.7/gas/doc/Makefile.in 2003-11-04 00:08:38.143422224 +0100
137@@ -181,7 +181,7 @@
2859501d
JB
138
139 man_MANS = as.1
140
141-info_TEXINFOS = as.texinfo
f8e97439 142+info_TEXINFOS = as.texinfo gasp.texinfo
2859501d
JB
143
144 CPU_DOCS = \
145 c-a29k.texi \
f8e97439
JB
146@@ -236,11 +236,11 @@
147 DIST_SOURCES =
2859501d 148 TEXINFO_TEX = $(top_srcdir)/../texinfo/texinfo.tex
f8e97439 149 am__TEXINFO_TEX_DIR = $(top_srcdir)/../texinfo
2859501d
JB
150-INFO_DEPS = as.info
151+INFO_DEPS = as.info gasp.info
152 DVIS = as.dvi
f8e97439
JB
153 PDFS = as.pdf
154 PSS = as.ps
155-TEXINFOS = as.texinfo
156+TEXINFOS = as.texinfo gasp.texinfo
2859501d 157
f8e97439
JB
158 NROFF = nroff
159 MANS = $(man_MANS)
160diff -Nur binutils-2.14.90.0.7.orig/gas/doc/gasp.texinfo binutils-2.14.90.0.7/gas/doc/gasp.texinfo
161--- binutils-2.14.90.0.7.orig/gas/doc/gasp.texinfo Thu Jan 1 01:00:00 1970
162+++ binutils-2.14.90.0.7/gas/doc/gasp.texinfo Wed Oct 30 05:09:13 2002
2859501d
JB
163@@ -0,0 +1,1456 @@
164+\input texinfo @c -*- Texinfo -*-
165+@setfilename gasp.info
166+@c
167+@c This file documents the assembly preprocessor "GASP"
168+@c
169+@c Copyright 1994, 1995, 2000, 2002 Free Software Foundation, Inc.
170+@c
171+@c Permission is granted to copy, distribute and/or modify this document
172+@c under the terms of the GNU Free Documentation License, Version 1.1
173+@c or any later version published by the Free Software Foundation;
174+@c with no Invariant Sections, with no Front-Cover Texts, and with no
175+@c Back-Cover Texts. A copy of the license is included in the
176+@c section entitled "GNU Free Documentation License".
177+
178+@ifinfo
179+@format
180+START-INFO-DIR-ENTRY
181+* gasp: (gasp). The GNU Assembler Preprocessor
182+END-INFO-DIR-ENTRY
183+@end format
184+@end ifinfo
185+
186+@syncodeindex ky cp
187+@syncodeindex fn cp
188+
189+@finalout
190+@setchapternewpage odd
191+@settitle GASP
192+@titlepage
193+@c FIXME boring title
194+@title GASP, an assembly preprocessor
195+@subtitle for GASP version 1
196+@sp 1
197+@subtitle March 1994
198+@author Roland Pesch
199+@page
200+
201+@tex
202+{\parskip=0pt \hfill Cygnus Support\par
203+}
204+@end tex
205+
206+@vskip 0pt plus 1filll
207+Copyright @copyright{} 1994, 1995, 2000, 2002 Free Software Foundation, Inc.
208+
209+ Permission is granted to copy, distribute and/or modify this document
210+ under the terms of the GNU Free Documentation License, Version 1.1
211+ or any later version published by the Free Software Foundation;
212+ with no Invariant Sections, with no Front-Cover Texts, and with no
213+ Back-Cover Texts. A copy of the license is included in the
214+ section entitled "GNU Free Documentation License".
215+
216+@end titlepage
217+
218+@ifinfo
219+Copyright @copyright{} 1994, 1995, 2000, 2002 Free Software Foundation, Inc.
220+
221+@ignore
222+Permission is granted to process this file through TeX and print the
223+results, provided the printed document carries a copying permission
224+notice identical to this one except for the removal of this paragraph
225+(this paragraph not being relevant to the printed manual).
226+@end ignore
227+
228+ Permission is granted to copy, distribute and/or modify this document
229+ under the terms of the GNU Free Documentation License, Version 1.1
230+ or any later version published by the Free Software Foundation;
231+ with no Invariant Sections, with no Front-Cover Texts, and with no
232+ Back-Cover Texts. A copy of the license is included in the
233+ section entitled "GNU Free Documentation License".
234+
235+
236+@node Top
237+@top GASP
238+
239+GASP is a preprocessor for assembly programs.
240+
241+This file describes version 1 of GASP.
242+
243+Steve Chamberlain wrote GASP; Roland Pesch wrote this manual.
244+
245+@menu
246+* Overview:: What is GASP?
247+* Invoking GASP:: Command line options.
248+* Commands:: Preprocessor commands.
249+* GNU Free Documentation License:: GNU Free Documentation License
250+* Index:: Index.
251+@end menu
252+@end ifinfo
253+
254+@node Overview
255+@chapter What is GASP?
256+
257+The primary purpose of the @sc{gnu} assembler is to assemble the output of
258+other programs---notably compilers. When you have to hand-code
259+specialized routines in assembly, that means the @sc{gnu} assembler is
260+an unfriendly processor: it has no directives for macros, conditionals,
261+or many other conveniences that you might expect.
262+
263+In some cases you can simply use the C preprocessor, or a generalized
264+preprocessor like @sc{m4}; but this can be awkward, since none of these
265+things are designed with assembly in mind.
266+
267+@sc{gasp} fills this need. It is expressly designed to provide the
268+facilities you need with hand-coded assembly code. Implementing it as a
269+preprocessor, rather than part of the assembler, allows the maximum
270+flexibility: you can use it with hand-coded assembly, without paying a
271+penalty of added complexity in the assembler you use for compiler
272+output.
273+
274+@emph{Note} The use of @sc{gasp} has now been deprecated. Anything
275+that it could do can now be done by the macro facilities built into
276+@sc{gas} itself. At some point in the future the @sc{gasp} sources will
277+be removed entirely from the binutils distribution.
278+
279+Here is a small example to give the flavor of @sc{gasp}. This input to
280+@sc{gasp}
281+
282+@cartouche
283+@example
284+ .MACRO saveregs from=8 to=14
285+count .ASSIGNA \from
286+ ! save r\from..r\to
287+ .AWHILE \&count LE \to
288+ mov r\&count,@@-sp
289+count .ASSIGNA \&count + 1
290+ .AENDW
291+ .ENDM
292+
293+ saveregs from=12
294+
295+bar: mov #H'dead+10,r0
296+foo .SDATAC "hello"<10>
297+ .END
298+@end example
299+@end cartouche
300+
301+@noindent
302+generates this assembly program:
303+
304+@cartouche
305+@example
306+ ! save r12..r14
307+ mov r12,@@-sp
308+ mov r13,@@-sp
309+ mov r14,@@-sp
310+
311+bar: mov #57005+10,r0
312+foo: .byte 6,104,101,108,108,111,10
313+@end example
314+@end cartouche
315+
316+@node Invoking GASP
317+@chapter Command Line Options
318+
319+@c FIXME! Or is there a simpler way, calling from GAS option?
320+The simplest way to use @sc{gasp} is to run it as a filter and assemble
321+its output. In Unix and its ilk, you can do this, for example:
322+
323+@c FIXME! GASP filename suffix convention?
324+@example
325+$ gasp prog.asm | as -o prog.o
326+@end example
327+
328+Naturally, there are also a few command-line options to allow you to
329+request variations on this basic theme. Here is the full set of
330+possibilities for the @sc{gasp} command line.
331+
332+@example
333+gasp [ -a | --alternate ]
334+ [ -c @var{char} | --commentchar @var{char} ]
335+ [ -d | --debug ] [ -h | --help ] [ -M | --mri ]
336+ [ -o @var{outfile} | --output @var{outfile} ]
337+ [ -p | --print ] [ -s | --copysource ]
338+ [ -u | --unreasonable ] [ -v | --version ]
339+ @var{infile} @dots{}
340+@end example
341+
342+@ftable @code
343+@item @var{infile} @dots{}
344+@c FIXME! Why not stdin as default infile?
345+The input file names. You must specify at least one input file; if you
346+specify more, @sc{gasp} preprocesses them all, concatenating the output
347+in the order you list the @var{infile} arguments.
348+
349+Mark the end of each input file with the preprocessor command
350+@code{.END}. @xref{Other Commands,, Miscellaneous commands}.
351+
352+@item -a
353+@itemx --alternate
354+Use alternative macro syntax. @xref{Alternate,, Alternate macro
355+syntax}, for a discussion of how this syntax differs from the default
356+@sc{gasp} syntax.
357+
358+@cindex comment character, changing
359+@cindex semicolon, as comment
360+@cindex exclamation mark, as comment
361+@cindex shriek, as comment
362+@cindex bang, as comment
363+@cindex @code{!} default comment char
364+@cindex @code{;} as comment char
365+@item -c '@var{char}'
366+@itemx --commentchar '@var{char}'
367+Use @var{char} as the comment character. The default comment character
368+is @samp{!}. For example, to use a semicolon as the comment character,
369+specify @w{@samp{-c ';'}} on the @sc{gasp} command line. Since
370+assembler command characters often have special significance to command
371+shells, it is a good idea to quote or escape @var{char} when you specify
372+a comment character.
373+
374+For the sake of simplicity, all examples in this manual use the default
375+comment character @samp{!}.
376+
377+@item -d
378+@itemx --debug
379+Show debugging statistics. In this version of @sc{gasp}, this option
380+produces statistics about the string buffers that @sc{gasp} allocates
381+internally. For each defined buffersize @var{s}, @sc{gasp} shows the
382+number of strings @var{n} that it allocated, with a line like this:
383+
384+@example
385+strings size @var{s} : @var{n}
386+@end example
387+
388+@noindent
389+@sc{gasp} displays these statistics on the standard error stream, when
390+done preprocessing.
391+
392+@item -h
393+@itemx --help
394+Display a summary of the @sc{gasp} command line options.
395+
396+@item -M
397+@itemx --mri
398+Use MRI compatibility mode. Using this option causes @sc{gasp} to
399+accept the syntax and pseudo-ops used by the Microtec Research
400+@code{ASM68K} assembler.
401+
402+@item -o @var{outfile}
403+@itemx --output @var{outfile}
404+Write the output in a file called @var{outfile}. If you do not use the
405+@samp{-o} option, @sc{gasp} writes its output on the standard output
406+stream.
407+
408+@item -p
409+@itemx --print
410+Print line numbers. @sc{gasp} obeys this option @emph{only} if you also
411+specify @samp{-s} to copy source lines to its output. With @samp{-s
412+-p}, @sc{gasp} displays the line number of each source line copied
413+(immediately after the comment character at the beginning of the line).
414+
415+@item -s
416+@itemx --copysource
417+Copy the source lines to the output file. Use this option
418+to see the effect of each preprocessor line on the @sc{gasp} output.
419+@sc{gasp} places a comment character (@samp{!} by default) at
420+the beginning of each source line it copies, so that you can use this
421+option and still assemble the result.
422+
423+@item -u
424+@itemx --unreasonable
425+Bypass ``unreasonable expansion'' limit. Since you can define @sc{gasp}
426+macros inside other macro definitions, the preprocessor normally
427+includes a sanity check. If your program requires more than 1,000
428+nested expansions, @sc{gasp} normally exits with an error message. Use
429+this option to turn off this check, allowing unlimited nested
430+expansions.
431+
432+@item -v
433+@itemx --version
434+Display the @sc{gasp} version number.
435+@end ftable
436+
437+@node Commands
438+@chapter Preprocessor Commands
439+
440+@sc{gasp} commands have a straightforward syntax that fits in well with
441+assembly conventions. In general, a command extends for a line, and may
442+have up to three fields: an optional label, the command itself, and
443+optional arguments to the command. You can write commands in upper or
444+lower case, though this manual shows them in upper case. @xref{Syntax
445+Details,, Details of the GASP syntax}, for more information.
446+
447+@menu
448+* Conditionals::
449+* Loops::
450+* Variables::
451+* Macros::
452+* Data::
453+* Listings::
454+* Other Commands::
455+* Syntax Details::
456+* Alternate::
457+@end menu
458+
459+@node Conditionals
460+@section Conditional assembly
461+
462+The conditional-assembly directives allow you to include or exclude
463+portions of an assembly depending on how a pair of expressions, or a
464+pair of strings, compare.
465+
466+The overall structure of conditionals is familiar from many other
467+contexts. @code{.AIF} marks the start of a conditional, and precedes
468+assembly for the case when the condition is true. An optional
469+@code{.AELSE} precedes assembly for the converse case, and an
470+@code{.AENDI} marks the end of the condition.
471+
472+@c FIXME! Why doesn't -u turn off this check?
473+You may nest conditionals up to a depth of 100; @sc{gasp} rejects
474+nesting beyond that, because it may indicate a bug in your macro
475+structure.
476+
477+@c FIXME! Why isn't there something like cpp's -D option? Conditionals
478+@c would be much more useful if there were.
479+Conditionals are primarily useful inside macro definitions, where you
480+often need different effects depending on argument values.
481+@xref{Macros,, Defining your own directives}, for details about defining
482+macros.
483+
484+@ftable @code
485+@item .AIF @var{expra} @var{cmp} @var{exprb}
486+@itemx .AIF "@var{stra}" @var{cmp} "@var{strb}"
487+
488+The governing condition goes on the same line as the @code{.AIF}
489+preprocessor command. You may compare either two strings, or two
490+expressions.
491+
492+When you compare strings, only two conditional @var{cmp} comparison
493+operators are available: @samp{EQ} (true if @var{stra} and @var{strb}
494+are identical), and @samp{NE} (the opposite).
495+
496+When you compare two expressions, @emph{both expressions must be
497+absolute} (@pxref{Expressions,, Arithmetic expressions in GASP}). You
498+can use these @var{cmp} comparison operators with expressions:
499+
500+@ftable @code
501+@item EQ
502+Are @var{expra} and @var{exprb} equal? (For strings, are @var{stra} and
503+@var{strb} identical?)
504+
505+@item NE
506+Are @var{expra} and @var{exprb} different? (For strings, are @var{stra}
507+and @var{strb} different?
508+
509+@item LT
510+Is @var{expra} less than @var{exprb}? (Not allowed for strings.)
511+
512+@item LE
513+Is @var{expra} less than or equal to @var{exprb}? (Not allowed for strings.)
514+
515+@item GT
516+Is @var{expra} greater than @var{exprb}? (Not allowed for strings.)
517+
518+@item GE
519+Is @var{expra} greater than or equal to @var{exprb}? (Not allowed for
520+strings.)
521+@end ftable
522+
523+@item .AELSE
524+Marks the start of assembly code to be included if the condition fails.
525+Optional, and only allowed within a conditional (between @code{.AIF} and
526+@code{.AENDI}).
527+
528+@item .AENDI
529+Marks the end of a conditional assembly.
530+@end ftable
531+
532+@node Loops
533+@section Repetitive sections of assembly
534+
535+Two preprocessor directives allow you to repeatedly issue copies of the
536+same block of assembly code.
537+
538+@ftable @code
539+@item .AREPEAT @var{aexp}
540+@itemx .AENDR
541+If you simply need to repeat the same block of assembly over and over a
542+fixed number of times, sandwich one instance of the repeated block
543+between @code{.AREPEAT} and @code{.AENDR}. Specify the number of
544+copies as @var{aexp} (which must be an absolute expression). For
545+example, this repeats two assembly statements three times in succession:
546+
547+@cartouche
548+@example
549+ .AREPEAT 3
550+ rotcl r2
551+ div1 r0,r1
552+ .AENDR
553+@end example
554+@end cartouche
555+
556+@item .AWHILE @var{expra} @var{cmp} @var{exprb}
557+@itemx .AENDW
558+@itemx .AWHILE @var{stra} @var{cmp} @var{strb}
559+@itemx .AENDW
560+To repeat a block of assembly depending on a conditional test, rather
561+than repeating it for a specific number of times, use @code{.AWHILE}.
562+@code{.AENDW} marks the end of the repeated block. The conditional
563+comparison works exactly the same way as for @code{.AIF}, with the same
564+comparison operators (@pxref{Conditionals,, Conditional assembly}).
565+
566+Since the terms of the comparison must be absolute expression,
567+@code{.AWHILE} is primarily useful within macros. @xref{Macros,,
568+Defining your own directives}.
569+@end ftable
570+
571+@cindex loops, breaking out of
572+@cindex breaking out of loops
573+You can use the @code{.EXITM} preprocessor directive to break out of
574+loops early (as well as to break out of macros). @xref{Macros,,
575+Defining your own directives}.
576+
577+@node Variables
578+@section Preprocessor variables
579+
580+You can use variables in @sc{gasp} to represent strings, registers, or
581+the results of expressions.
582+
583+You must distinguish two kinds of variables:
584+@enumerate
585+@item
586+Variables defined with @code{.EQU} or @code{.ASSIGN}. To evaluate this
587+kind of variable in your assembly output, simply mention its name. For
588+example, these two lines define and use a variable @samp{eg}:
589+
590+@cartouche
591+@example
592+eg .EQU FLIP-64
593+ @dots{}
594+ mov.l eg,r0
595+@end example
596+@end cartouche
597+
598+@emph{Do not use} this kind of variable in conditional expressions or
599+while loops; @sc{gasp} only evaluates these variables when writing
600+assembly output.
601+
602+@item
603+Variables for use during preprocessing. You can define these
604+with @code{.ASSIGNC} or @code{.ASSIGNA}. To evaluate this
605+kind of variable, write @samp{\&} before the variable name; for example,
606+
607+@cartouche
608+@example
609+opcit .ASSIGNA 47
610+ @dots{}
611+ .AWHILE \&opcit GT 0
612+ @dots{}
613+ .AENDW
614+@end example
615+@end cartouche
616+
617+@sc{gasp} treats macro arguments almost the same way, but to evaluate
618+them you use the prefix @samp{\} rather than @samp{\&}.
619+@xref{Macros,, Defining your own directives}.
620+@end enumerate
621+
622+@ftable @code
623+@item @var{pvar} .EQU @var{expr}
624+@c FIXME! Anything to beware of re GAS directive of same name?
625+Assign preprocessor variable @var{pvar} the value of the expression
626+@var{expr}. There are no restrictions on redefinition; use @samp{.EQU}
627+with the same @var{pvar} as often as you find it convenient.
628+
629+@item @var{pvar} .ASSIGN @var{expr}
630+Almost the same as @code{.EQU}, save that you may not redefine
631+@var{pvar} using @code{.ASSIGN} once it has a value.
632+@c FIXME!! Supposed to work this way, apparently, but on 9feb94 works
633+@c just like .EQU
634+
635+@item @var{pvar} .ASSIGNA @var{aexpr}
636+Define a variable with a numeric value, for use during preprocessing.
637+@var{aexpr} must be an absolute expression. You can redefine variables
638+with @code{.ASSIGNA} at any time.
639+
640+@item @var{pvar} .ASSIGNC "@var{str}"
641+Define a variable with a string value, for use during preprocessing.
642+You can redefine variables with @code{.ASSIGNC} at any time.
643+
644+@item @var{pvar} .REG (@var{register})
645+Use @code{.REG} to define a variable that represents a register. In
646+particular, @var{register} is @emph{not evaluated} as an expression.
647+You may use @code{.REG} at will to redefine register variables.
648+@end ftable
649+
650+All these directives accept the variable name in the ``label'' position,
651+that is at the left margin. You may specify a colon after the variable
652+name if you wish; the first example above could have started @samp{eg:}
653+with the same effect.
654+
655+@c pagebreak makes for better aesthetics---ensures macro and expansion together
656+@page
657+@node Macros
658+@section Defining your own directives
659+
660+The commands @code{.MACRO} and @code{.ENDM} allow you to define macros
661+that generate assembly output. You can use these macros with a syntax
662+similar to built-in @sc{gasp} or assembler directives. For example,
663+this definition specifies a macro @code{SUM} that adds together a range of
664+consecutive registers:
665+
666+@cartouche
667+@example
668+ .MACRO SUM FROM=0, TO=9
669+ ! \FROM \TO
670+ mov r\FROM,r10
671+COUNT .ASSIGNA \FROM+1
672+ .AWHILE \&COUNT LE \TO
673+ add r\&COUNT,r10
674+COUNT .ASSIGNA \&COUNT+1
675+ .AENDW
676+ .ENDM
677+@end example
678+@end cartouche
679+
680+@noindent
681+With that definition, @samp{SUM 0,5} generates this assembly output:
682+
683+@cartouche
684+@example
685+ ! 0 5
686+ mov r0,r10
687+ add r1,r10
688+ add r2,r10
689+ add r3,r10
690+ add r4,r10
691+ add r5,r10
692+@end example
693+@end cartouche
694+
695+@ftable @code
696+@item .MACRO @var{macname}
697+@itemx .MACRO @var{macname} @var{macargs} @dots{}
698+Begin the definition of a macro called @var{macname}. If your macro
699+definition requires arguments, specify their names after the macro name,
700+separated by commas or spaces. You can supply a default value for any
701+macro argument by following the name with @samp{=@var{deflt}}. For
702+example, these are all valid @code{.MACRO} statements:
703+
704+@table @code
705+@item .MACRO COMM
706+Begin the definition of a macro called @code{COMM}, which takes no
707+arguments.
708+
709+@item .MACRO PLUS1 P, P1
710+@itemx .MACRO PLUS1 P P1
711+Either statement begins the definition of a macro called @code{PLUS1},
712+which takes two arguments; within the macro definition, write
713+@samp{\P} or @samp{\P1} to evaluate the arguments.
714+
715+@item .MACRO RESERVE_STR P1=0 P2
716+Begin the definition of a macro called @code{RESERVE_STR}, with two
717+arguments. The first argument has a default value, but not the second.
718+After the definition is complete, you can call the macro either as
719+@samp{RESERVE_STR @var{a},@var{b}} (with @samp{\P1} evaluating to
720+@var{a} and @samp{\P2} evaluating to @var{b}), or as @samp{RESERVE_STR
721+,@var{b}} (with @samp{\P1} evaluating as the default, in this case
722+@samp{0}, and @samp{\P2} evaluating to @var{b}).
723+@end table
724+
725+When you call a macro, you can specify the argument values either by
726+position, or by keyword. For example, @samp{SUM 9,17} is equivalent to
727+@samp{SUM TO=17, FROM=9}. Macro arguments are preprocessor variables
728+similar to the variables you define with @samp{.ASSIGNA} or
729+@samp{.ASSIGNC}; in particular, you can use them in conditionals or for
730+loop control. (The only difference is the prefix you write to evaluate
731+the variable: for a macro argument, write @samp{\@var{argname}}, but for
732+a preprocessor variable, write @samp{\&@var{varname}}.)
733+
734+@item @var{name} .MACRO
735+@itemx @var{name} .MACRO ( @var{macargs} @dots{} )
736+@c FIXME check: I think no error _and_ no args recognized if I use form
737+@c NAME .MACRO ARG ARG
738+An alternative form of introducing a macro definition: specify the macro
739+name in the label position, and the arguments (if any) between
740+parentheses after the name. Defaulting rules and usage work the same
741+way as for the other macro definition syntax.
742+
743+@item .ENDM
744+Mark the end of a macro definition.
745+
746+@item .EXITM
747+Exit early from the current macro definition, @code{.AREPEAT} loop, or
748+@code{.AWHILE} loop.
749+
750+@cindex number of macros executed
751+@cindex macros, count executed
752+@item \@@
753+@sc{gasp} maintains a counter of how many macros it has
754+executed in this pseudo-variable; you can copy that number to your
755+output with @samp{\@@}, but @emph{only within a macro definition}.
756+
757+@item LOCAL @var{name} [ , @dots{} ]
758+@emph{Warning: @code{LOCAL} is only available if you select ``alternate
759+macro syntax'' with @samp{-a} or @samp{--alternate}.} @xref{Alternate,,
760+Alternate macro syntax}.
761+
762+Generate a string replacement for each of the @var{name} arguments, and
763+replace any instances of @var{name} in each macro expansion. The
764+replacement string is unique in the assembly, and different for each
765+separate macro expansion. @code{LOCAL} allows you to write macros that
766+define symbols, without fear of conflict between separate macro expansions.
767+@end ftable
768+
769+@node Data
770+@section Data output
771+
772+In assembly code, you often need to specify working areas of memory;
773+depending on the application, you may want to initialize such memory or
774+not. @sc{gasp} provides preprocessor directives to help you avoid
775+repetitive coding for both purposes.
776+
777+You can use labels as usual to mark the data areas.
778+
779+@menu
780+* Initialized::
781+* Uninitialized::
782+@end menu
783+
784+@node Initialized
785+@subsection Initialized data
786+
787+These are the @sc{gasp} directives for initialized data, and the standard
788+@sc{gnu} assembler directives they expand to:
789+
790+@ftable @code
791+@item .DATA @var{expr}, @var{expr}, @dots{}
792+@itemx .DATA.B @var{expr}, @var{expr}, @dots{}
793+@itemx .DATA.W @var{expr}, @var{expr}, @dots{}
794+@itemx .DATA.L @var{expr}, @var{expr}, @dots{}
795+Evaluate arithmetic expressions @var{expr}, and emit the corresponding
796+@code{as} directive (labelled with @var{lab}). The unqualified
797+@code{.DATA} emits @samp{.long}; @code{.DATA.B} emits @samp{.byte};
798+@code{.DATA.W} emits @samp{.short}; and @code{.DATA.L} emits
799+@samp{.long}.
800+
801+For example, @samp{foo .DATA 1,2,3} emits @samp{foo: .long 1,2,3}.
802+
803+@item .DATAB @var{repeat}, @var{expr}
804+@itemx .DATAB.B @var{repeat}, @var{expr}
805+@itemx .DATAB.W @var{repeat}, @var{expr}
806+@itemx .DATAB.L @var{repeat}, @var{expr}
807+@c FIXME! Looks like gasp accepts and ignores args after 2nd.
808+Make @code{as} emit @var{repeat} copies of the value of the expression
809+@var{expr} (using the @code{as} directive @code{.fill}).
810+@samp{.DATAB.B} repeats one-byte values; @samp{.DATAB.W} repeats
811+two-byte values; and @samp{.DATAB.L} repeats four-byte values.
812+@samp{.DATAB} without a suffix repeats four-byte values, just like
813+@samp{.DATAB.L}.
814+
815+@c FIXME! Allowing zero might be useful for edge conditions in macros.
816+@var{repeat} must be an absolute expression with a positive value.
817+
818+@item .SDATA "@var{str}" @dots{}
819+String data. Emits a concatenation of bytes, precisely as you specify
820+them (in particular, @emph{nothing is added to mark the end} of the
821+string). @xref{Constants,, String and numeric constants}, for details
822+about how to write strings. @code{.SDATA} concatenates multiple
823+arguments, making it easy to switch between string representations. You
824+can use commas to separate the individual arguments for clarity, if you
825+choose.
826+
827+@item .SDATAB @var{repeat}, "@var{str}" @dots{}
828+Repeated string data. The first argument specifies how many copies of
829+the string to emit; the remaining arguments specify the string, in the
830+same way as the arguments to @code{.SDATA}.
831+
832+@item .SDATAZ "@var{str}" @dots{}
833+Zero-terminated string data. Just like @code{.SDATA}, except that
834+@code{.SDATAZ} writes a zero byte at the end of the string.
835+
836+@item .SDATAC "@var{str}" @dots{}
837+Count-prefixed string data. Just like @code{.SDATA}, except that
838+@sc{gasp} precedes the string with a leading one-byte count. For
839+example, @samp{.SDATAC "HI"} generates @samp{.byte 2,72,73}. Since the
840+count field is only one byte, you can only use @code{.SDATAC} for
841+strings less than 256 bytes in length.
842+@end ftable
843+
844+@node Uninitialized
845+@subsection Uninitialized data
846+
847+@c FIXME! .space different on some platforms, notably HPPA. Config?
848+Use the @code{.RES}, @code{.SRES}, @code{.SRESC}, and @code{.SRESZ}
849+directives to reserve memory and leave it uninitialized. @sc{gasp}
850+resolves these directives to appropriate calls of the @sc{gnu}
851+@code{as} @code{.space} directive.
852+
853+@ftable @code
854+@item .RES @var{count}
855+@itemx .RES.B @var{count}
856+@itemx .RES.W @var{count}
857+@itemx .RES.L @var{count}
858+Reserve room for @var{count} uninitialized elements of data. The
859+suffix specifies the size of each element: @code{.RES.B} reserves
860+@var{count} bytes, @code{.RES.W} reserves @var{count} pairs of bytes,
861+and @code{.RES.L} reserves @var{count} quartets. @code{.RES} without a
862+suffix is equivalent to @code{.RES.L}.
863+
864+@item .SRES @var{count}
865+@itemx .SRES.B @var{count}
866+@itemx .SRES.W @var{count}
867+@itemx .SRES.L @var{count}
868+@c FIXME! This is boring. Shouldn't it at least have a different
869+@c default size? (e.g. the "S" suggests "string", for which .B
870+@c would be more appropriate)
871+@code{.SRES} is a synonym for @samp{.RES}.
872+
873+@item .SRESC @var{count}
874+@itemx .SRESC.B @var{count}
875+@itemx .SRESC.W @var{count}
876+@itemx .SRESC.L @var{count}
877+Like @code{.SRES}, but reserves space for @code{@var{count}+1} elements.
878+
879+@item .SRESZ @var{count}
880+@itemx .SRESZ.B @var{count}
881+@itemx .SRESZ.W @var{count}
882+@itemx .SRESZ.L @var{count}
883+Like @code{.SRES}, but reserves space for @code{@var{count}+1} elements.
884+@end ftable
885+
886+@node Listings
887+@section Assembly listing control
888+
889+The @sc{gasp} listing-control directives correspond to
890+related @sc{gnu} @code{as} directives.
891+
892+@ftable @code
893+@item .PRINT LIST
894+@itemx .PRINT NOLIST
895+Print control. This directive emits the @sc{gnu} @code{as} directive
896+@code{.list} or @code{.nolist}, according to its argument. @xref{List,,
897+@code{.list}, as.info, Using as}, for details on how these directives
898+interact.
899+
900+@item .FORM LIN=@var{ln}
901+@itemx .FORM COL=@var{cols}
902+@itemx .FORM LIN=@var{ln} COL=@var{cols}
903+Specify the page size for assembly listings: @var{ln} represents the
904+number of lines, and @var{cols} the number of columns. You may specify
905+either page dimension independently, or both together. If you do not
906+specify the number of lines, @sc{gasp} assumes 60 lines; if you do not
907+specify the number of columns, @sc{gasp} assumes 132 columns.
908+(Any values you may have specified in previous instances of @code{.FORM}
909+do @emph{not} carry over as defaults.) Emits the @code{.psize}
910+assembler directive.
911+
912+@item .HEADING @var{string}
913+Specify @var{string} as the title of your assembly listings. Emits
914+@samp{.title "@var{string}"}.
915+
916+@item .PAGE
917+Force a new page in assembly listings. Emits @samp{.eject}.
918+@end ftable
919+
920+@node Other Commands
921+@section Miscellaneous commands
922+
923+@ftable @code
924+@item .ALTERNATE
925+Use the alternate macro syntax henceforth in the assembly.
926+@xref{Alternate,, Alternate macro syntax}.
927+
928+@item .ORG
929+@c FIXME! This is very strange, since _GAS_ understands .org
930+This command is recognized, but not yet implemented. @sc{gasp}
931+generates an error message for programs that use @code{.ORG}.
932+
933+@item .RADIX @var{s}
934+@c FIXME no test cases in testsuite/gasp
935+@sc{gasp} understands numbers in any of base two, eight, ten, or
936+sixteen. You can encode the base explicitly in any numeric constant
937+(@pxref{Constants,, String and numeric constants}). If you write
938+numbers without an explicit indication of the base, the most recent
939+@samp{.RADIX @var{s}} command determines how they are interpreted.
940+@var{s} is a single letter, one of the following:
941+
942+@table @code
943+@item .RADIX B
944+Base 2.
945+
946+@item .RADIX Q
947+Base 8.
948+
949+@item .RADIX D
950+Base 10. This is the original default radix.
951+
952+@item .RADIX H
953+Base 16.
954+@end table
955+
956+You may specify the argument @var{s} in lower case (any of @samp{bqdh})
957+with the same effects.
958+
959+@item .EXPORT @var{name}
960+@itemx .GLOBAL @var{name}
961+@c FIXME! No test cases in testsuite/gasp
962+Declare @var{name} global (emits @samp{.global @var{name}}). The two
963+directives are synonymous.
964+
965+@item .PROGRAM
966+No effect: @sc{gasp} accepts this directive, and silently ignores it.
967+
968+@item .END
969+Mark end of each preprocessor file. @sc{gasp} issues a warning if it
970+reaches end of file without seeing this command.
971+
972+@item .INCLUDE "@var{str}"
973+Preprocess the file named by @var{str}, as if its contents appeared
974+where the @code{.INCLUDE} directive does. @sc{gasp} imposes a maximum
975+limit of 30 stacked include files, as a sanity check.
976+@c FIXME! Why is include depth not affected by -u?
977+
978+@item .ALIGN @var{size}
979+@c FIXME! Why is this not utterly pointless?
980+Evaluate the absolute expression @var{size}, and emit the assembly
981+instruction @samp{.align @var{size}} using the result.
982+@end ftable
983+
984+@node Syntax Details
985+@section Details of the GASP syntax
986+
987+Since @sc{gasp} is meant to work with assembly code, its statement
988+syntax has no surprises for the assembly programmer.
989+
990+@cindex whitespace
991+@emph{Whitespace} (blanks or tabs; @emph{not} newline) is partially
992+significant, in that it delimits up to three fields in a line. The
993+amount of whitespace does not matter; you may line up fields in separate
994+lines if you wish, but @sc{gasp} does not require that.
995+
996+@cindex fields of @sc{gasp} source line
997+@cindex label field
998+The @emph{first field}, an optional @dfn{label}, must be flush left in a
999+line (with no leading whitespace) if it appears at all. You may use a
1000+colon after the label if you wish; @sc{gasp} neither requires the colon
1001+nor objects to it (but will not include it as part of the label name).
1002+
1003+@cindex directive field
1004+The @emph{second field}, which must appear after some whitespace,
1005+contains a @sc{gasp} or assembly @dfn{directive}.
1006+
1007+@cindex argument fields
1008+Any @emph{further fields} on a line are @dfn{arguments} to the
1009+directive; you can separate them from one another using either commas or
1010+whitespace.
1011+
1012+@menu
1013+* Markers::
1014+* Constants::
1015+* Symbols::
1016+* Expressions::
1017+* String Builtins::
1018+@end menu
1019+
1020+@node Markers
1021+@subsection Special syntactic markers
1022+
1023+@sc{gasp} recognizes a few special markers: to delimit comments, to
1024+continue a statement on the next line, to separate symbols from other
1025+characters, and to copy text to the output literally. (One other
1026+special marker, @samp{\@@}, works only within macro definitions;
1027+@pxref{Macros,, Defining your own directives}.)
1028+
1029+@cindex comments
1030+The trailing part of any @sc{gasp} source line may be a @dfn{comment}.
1031+A comment begins with the first unquoted comment character (@samp{!} by
1032+default), or an escaped or doubled comment character (@samp{\!} or
1033+@samp{!!} by default), and extends to the end of a line. You can
1034+specify what comment character to use with the @samp{-c} option
1035+(@pxref{Invoking GASP,, Command Line Options}). The two kinds of
1036+comment markers lead to slightly different treatment:
1037+
1038+@table @code
1039+@item !
1040+A single, un-escaped comment character generates an assembly comment in
1041+the @sc{gasp} output. @sc{gasp} evaluates any preprocessor variables
1042+(macro arguments, or variables defined with @code{.ASSIGNA} or
1043+@code{.ASSIGNC}) present. For example, a macro that begins like this
1044+
1045+@example
1046+ .MACRO SUM FROM=0, TO=9
1047+ ! \FROM \TO
1048+@end example
1049+
1050+@noindent
1051+issues as the first line of output a comment that records the
1052+values you used to call the macro.
1053+
1054+@c comments, preprocessor-only
1055+@c preprocessor-only comments
1056+@c GASP-only comments
1057+@item \!
1058+@itemx !!
1059+Either an escaped comment character, or a double comment character,
1060+marks a @sc{gasp} source comment. @sc{gasp} does not copy such comments
1061+to the assembly output.
1062+@end table
1063+
1064+@cindex continuation character
1065+@kindex +
1066+To @emph{continue a statement} on the next line of the file, begin the
1067+second line with the character @samp{+}.
1068+
1069+@cindex literal copy to output
1070+@cindex copying literally to output
1071+@cindex preprocessing, avoiding
1072+@cindex avoiding preprocessing
1073+Occasionally you may want to prevent @sc{gasp} from preprocessing some
1074+particular bit of text. To @emph{copy literally} from the @sc{gasp}
1075+source to its output, place @samp{\(} before the string to copy, and
1076+@samp{)} at the end. For example, write @samp{\(\!)} if you need the
1077+characters @samp{\!} in your assembly output.
1078+
1079+@cindex symbol separator
1080+@cindex text, separating from symbols
1081+@cindex symbols, separating from text
1082+To @emph{separate a preprocessor variable} from text to appear
1083+immediately after its value, write a single quote (@code{'}). For
1084+example, @samp{.SDATA "\P'1"} writes a string built by concatenating the
1085+value of @code{P} and the digit @samp{1}. (You cannot achieve this by
1086+writing just @samp{\P1}, since @samp{P1} is itself a valid name for a
1087+preprocessor variable.)
1088+
1089+@node Constants
1090+@subsection String and numeric constants
1091+
1092+There are two ways of writing @dfn{string constants} in @sc{gasp}: as
1093+literal text, and by numeric byte value. Specify a string literal
1094+between double quotes (@code{"@var{str}"}). Specify an individual
1095+numeric byte value as an absolute expression between angle brackets
1096+(@code{<@var{expr}>}. Directives that output strings allow you to
1097+specify any number of either kind of value, in whatever order is
1098+convenient, and concatenate the result. (Alternate syntax mode
1099+introduces a number of alternative string notations; @pxref{Alternate,,
1100+Alternate macro syntax}.)
1101+
1102+@c Details of numeric notation, e.g. base prefixes
1103+You can write @dfn{numeric constants} either in a specific base, or in
1104+whatever base is currently selected (either 10, or selected by the most
1105+recent @code{.RADIX}).
1106+
1107+To write a number in a @emph{specific base}, use the pattern
1108+@code{@var{s}'@var{ddd}}: a base specifier character @var{s}, followed
1109+by a single quote followed by digits @var{ddd}. The base specifier
1110+character matches those you can specify with @code{.RADIX}: @samp{B} for
1111+base 2, @samp{Q} for base 8, @samp{D} for base 10, and @samp{H} for base
1112+16. (You can write this character in lower case if you prefer.)
1113+
1114+You can write floating point constants using the same syntax recognised
1115+by GAS @ref{Flonums,,Flonums,as,The GNU Assembler.}. A constraint is
1116+that these constants will be interpreted as decimal values irrespective
1117+of the currently selected base.
1118+
1119+@c FIXME! What are rules for recognizing number in deflt base? Whatever
1120+@c is left over after parsing other things??
1121+
1122+@node Symbols
1123+@subsection Symbols
1124+
1125+@sc{gasp} recognizes symbol names that start with any alphabetic character,
1126+@samp{_}, or @samp{$}, and continue with any of the same characters or
1127+with digits. Label names follow the same rules.
1128+
1129+@node Expressions
1130+@subsection Arithmetic expressions in GASP
1131+
1132+@cindex absolute expressions
1133+@cindex relocatable expressions
1134+There are two kinds of expressions, depending on their result:
1135+@dfn{absolute} expressions, which resolve to a constant (that is, they
1136+do not involve any values unknown to @sc{gasp}), and @dfn{relocatable}
1137+expressions, which must reduce to the form
1138+
1139+@example
1140+@var{addsym}+@var{const}-@var{subsym}
1141+@end example
1142+
1143+@noindent
1144+where @var{addsym} and @var{subsym} are assembly symbols of unknown
1145+value, and @var{const} is a constant.
1146+
1147+Arithmetic for @sc{gasp} expressions follows very similar rules to C.
1148+You can use parentheses to change precedence; otherwise, arithmetic
1149+primitives have decreasing precedence in the order of the following
1150+list.
1151+
1152+@enumerate
1153+@item
1154+Single-argument @code{+} (identity), @code{-} (arithmetic opposite), or
1155+@code{~} (bitwise negation). @emph{The argument must be an absolute
1156+expression.}
1157+
1158+@item
1159+@code{*} (multiplication) and @code{/} (division). @emph{Both arguments
1160+must be absolute expressions.}
1161+
1162+@item
1163+@code{+} (addition) and @code{-} (subtraction). @emph{At least one argument
1164+must be absolute.}
1165+@c FIXME! Actually, subtraction doesn't check for this.
1166+
1167+@item
1168+@code{&} (bitwise and). @emph{Both arguments must be absolute.}
1169+
1170+@item
1171+@c FIXME! I agree ~ is a better notation than ^ for xor, but is the
1172+@c improvement worth differing from C?
1173+@code{|} (bitwise or) and @code{~} (bitwise exclusive or; @code{^} in
1174+C). @emph{Both arguments must be absolute.}
1175+@end enumerate
1176+
1177+@node String Builtins
1178+@subsection String primitives
1179+
1180+You can use these primitives to manipulate strings (in the argument
1181+field of @sc{gasp} statements):
1182+
1183+@ftable @code
1184+@item .LEN("@var{str}")
1185+Calculate the length of string @code{"@var{str}"}, as an absolute
1186+expression. For example, @samp{.RES.B .LEN("sample")} reserves six
1187+bytes of memory.
1188+
1189+@item .INSTR("@var{string}", "@var{seg}", @var{ix})
1190+Search for the first occurrence of @var{seg} after position @var{ix} of
1191+@var{string}. For example, @samp{.INSTR("ABCDEFG", "CDE", 0)} evaluates
1192+to the absolute result @code{2}.
1193+
1194+The result is @code{-1} if @var{seg} does not occur in @var{string}
1195+after position @var{ix}.
1196+
1197+@item .SUBSTR("@var{string}",@var{start},@var{len})
1198+The substring of @var{string} beginning at byte number @var{start} and
1199+extending for @var{len} bytes.
1200+@end ftable
1201+
1202+@node Alternate
1203+@section Alternate macro syntax
1204+
1205+If you specify @samp{-a} or @samp{--alternate} on the @sc{gasp} command
1206+line, the preprocessor uses somewhat different syntax. This syntax is
1207+reminiscent of the syntax of Phar Lap macro assembler, but it
1208+is @emph{not} meant to be a full emulation of Phar Lap or similar
1209+assemblers. In particular, @sc{gasp} does not support directives such
1210+as @code{DB} and @code{IRP}, even in alternate syntax mode.
1211+
1212+In particular, @samp{-a} (or @samp{--alternate}) elicits these
1213+differences:
1214+
1215+@table @emph
1216+@item Preprocessor directives
1217+You can use @sc{gasp} preprocessor directives without a leading @samp{.}
1218+dot. For example, you can write @samp{SDATA} with the same effect as
1219+@samp{.SDATA}.
1220+
1221+@item LOCAL
1222+One additional directive, @code{LOCAL}, is available. @xref{Macros,,
1223+Defining your own directives}, for an explanation of how to use
1224+@code{LOCAL}.
1225+
1226+@need 2000
1227+@item String delimiters
1228+You can write strings delimited in these other ways besides
1229+@code{"@var{string}"}:
1230+
1231+@table @code
1232+@item '@var{string}'
1233+You can delimit strings with single-quote charaters.
1234+
1235+@item <@var{string}>
1236+You can delimit strings with matching angle brackets.
1237+@end table
1238+
1239+@item single-character string escape
1240+To include any single character literally in a string (even if the
1241+character would otherwise have some special meaning), you can prefix the
1242+character with @samp{!} (an exclamation mark). For example, you can
1243+write @samp{<4.3 !> 5.4!!>} to get the literal text @samp{4.3 > 5.4!}.
1244+
1245+@item Expression results as strings
1246+You can write @samp{%@var{expr}} to evaluate the expression @var{expr}
1247+and use the result as a string.
1248+@end table
1249+
1250+@node GNU Free Documentation License
1251+@chapter GNU Free Documentation License
1252+
1253+ GNU Free Documentation License
1254+
1255+ Version 1.1, March 2000
1256+
1257+ Copyright (C) 2000 Free Software Foundation, Inc.
1258+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1259+
1260+ Everyone is permitted to copy and distribute verbatim copies
1261+ of this license document, but changing it is not allowed.
1262+
1263+
1264+0. PREAMBLE
1265+
1266+The purpose of this License is to make a manual, textbook, or other
1267+written document "free" in the sense of freedom: to assure everyone
1268+the effective freedom to copy and redistribute it, with or without
1269+modifying it, either commercially or noncommercially. Secondarily,
1270+this License preserves for the author and publisher a way to get
1271+credit for their work, while not being considered responsible for
1272+modifications made by others.
1273+
1274+This License is a kind of "copyleft", which means that derivative
1275+works of the document must themselves be free in the same sense. It
1276+complements the GNU General Public License, which is a copyleft
1277+license designed for free software.
1278+
1279+We have designed this License in order to use it for manuals for free
1280+software, because free software needs free documentation: a free
1281+program should come with manuals providing the same freedoms that the
1282+software does. But this License is not limited to software manuals;
1283+it can be used for any textual work, regardless of subject matter or
1284+whether it is published as a printed book. We recommend this License
1285+principally for works whose purpose is instruction or reference.
1286+
1287+
1288+1. APPLICABILITY AND DEFINITIONS
1289+
1290+This License applies to any manual or other work that contains a
1291+notice placed by the copyright holder saying it can be distributed
1292+under the terms of this License. The "Document", below, refers to any
1293+such manual or work. Any member of the public is a licensee, and is
1294+addressed as "you".
1295+
1296+A "Modified Version" of the Document means any work containing the
1297+Document or a portion of it, either copied verbatim, or with
1298+modifications and/or translated into another language.
1299+
1300+A "Secondary Section" is a named appendix or a front-matter section of
1301+the Document that deals exclusively with the relationship of the
1302+publishers or authors of the Document to the Document's overall subject
1303+(or to related matters) and contains nothing that could fall directly
1304+within that overall subject. (For example, if the Document is in part a
1305+textbook of mathematics, a Secondary Section may not explain any
1306+mathematics.) The relationship could be a matter of historical
1307+connection with the subject or with related matters, or of legal,
1308+commercial, philosophical, ethical or political position regarding
1309+them.
1310+
1311+The "Invariant Sections" are certain Secondary Sections whose titles
1312+are designated, as being those of Invariant Sections, in the notice
1313+that says that the Document is released under this License.
1314+
1315+The "Cover Texts" are certain short passages of text that are listed,
1316+as Front-Cover Texts or Back-Cover Texts, in the notice that says that
1317+the Document is released under this License.
1318+
1319+A "Transparent" copy of the Document means a machine-readable copy,
1320+represented in a format whose specification is available to the
1321+general public, whose contents can be viewed and edited directly and
1322+straightforwardly with generic text editors or (for images composed of
1323+pixels) generic paint programs or (for drawings) some widely available
1324+drawing editor, and that is suitable for input to text formatters or
1325+for automatic translation to a variety of formats suitable for input
1326+to text formatters. A copy made in an otherwise Transparent file
1327+format whose markup has been designed to thwart or discourage
1328+subsequent modification by readers is not Transparent. A copy that is
1329+not "Transparent" is called "Opaque".
1330+
1331+Examples of suitable formats for Transparent copies include plain
1332+ASCII without markup, Texinfo input format, LaTeX input format, SGML
1333+or XML using a publicly available DTD, and standard-conforming simple
1334+HTML designed for human modification. Opaque formats include
1335+PostScript, PDF, proprietary formats that can be read and edited only
1336+by proprietary word processors, SGML or XML for which the DTD and/or
1337+processing tools are not generally available, and the
1338+machine-generated HTML produced by some word processors for output
1339+purposes only.
1340+
1341+The "Title Page" means, for a printed book, the title page itself,
1342+plus such following pages as are needed to hold, legibly, the material
1343+this License requires to appear in the title page. For works in
1344+formats which do not have any title page as such, "Title Page" means
1345+the text near the most prominent appearance of the work's title,
1346+preceding the beginning of the body of the text.
1347+
1348+
1349+2. VERBATIM COPYING
1350+
1351+You may copy and distribute the Document in any medium, either
1352+commercially or noncommercially, provided that this License, the
1353+copyright notices, and the license notice saying this License applies
1354+to the Document are reproduced in all copies, and that you add no other
1355+conditions whatsoever to those of this License. You may not use
1356+technical measures to obstruct or control the reading or further
1357+copying of the copies you make or distribute. However, you may accept
1358+compensation in exchange for copies. If you distribute a large enough
1359+number of copies you must also follow the conditions in section 3.
1360+
1361+You may also lend copies, under the same conditions stated above, and
1362+you may publicly display copies.
1363+
1364+
1365+3. COPYING IN QUANTITY
1366+
1367+If you publish printed copies of the Document numbering more than 100,
1368+and the Document's license notice requires Cover Texts, you must enclose
1369+the copies in covers that carry, clearly and legibly, all these Cover
1370+Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
1371+the back cover. Both covers must also clearly and legibly identify
1372+you as the publisher of these copies. The front cover must present
1373+the full title with all words of the title equally prominent and
1374+visible. You may add other material on the covers in addition.
1375+Copying with changes limited to the covers, as long as they preserve
1376+the title of the Document and satisfy these conditions, can be treated
1377+as verbatim copying in other respects.
1378+
1379+If the required texts for either cover are too voluminous to fit
1380+legibly, you should put the first ones listed (as many as fit
1381+reasonably) on the actual cover, and continue the rest onto adjacent
1382+pages.
1383+
1384+If you publish or distribute Opaque copies of the Document numbering
1385+more than 100, you must either include a machine-readable Transparent
1386+copy along with each Opaque copy, or state in or with each Opaque copy
1387+a publicly-accessible computer-network location containing a complete
1388+Transparent copy of the Document, free of added material, which the
1389+general network-using public has access to download anonymously at no
1390+charge using public-standard network protocols. If you use the latter
1391+option, you must take reasonably prudent steps, when you begin
1392+distribution of Opaque copies in quantity, to ensure that this
1393+Transparent copy will remain thus accessible at the stated location
1394+until at least one year after the last time you distribute an Opaque
1395+copy (directly or through your agents or retailers) of that edition to
1396+the public.
1397+
1398+It is requested, but not required, that you contact the authors of the
1399+Document well before redistributing any large number of copies, to give
1400+them a chance to provide you with an updated version of the Document.
1401+
1402+
1403+4. MODIFICATIONS
1404+
1405+You may copy and distribute a Modified Version of the Document under
1406+the conditions of sections 2 and 3 above, provided that you release
1407+the Modified Version under precisely this License, with the Modified
1408+Version filling the role of the Document, thus licensing distribution
1409+and modification of the Modified Version to whoever possesses a copy
1410+of it. In addition, you must do these things in the Modified Version:
1411+
1412+A. Use in the Title Page (and on the covers, if any) a title distinct
1413+ from that of the Document, and from those of previous versions
1414+ (which should, if there were any, be listed in the History section
1415+ of the Document). You may use the same title as a previous version
1416+ if the original publisher of that version gives permission.
1417+B. List on the Title Page, as authors, one or more persons or entities
1418+ responsible for authorship of the modifications in the Modified
1419+ Version, together with at least five of the principal authors of the
1420+ Document (all of its principal authors, if it has less than five).
1421+C. State on the Title page the name of the publisher of the
1422+ Modified Version, as the publisher.
1423+D. Preserve all the copyright notices of the Document.
1424+E. Add an appropriate copyright notice for your modifications
1425+ adjacent to the other copyright notices.
1426+F. Include, immediately after the copyright notices, a license notice
1427+ giving the public permission to use the Modified Version under the
1428+ terms of this License, in the form shown in the Addendum below.
1429+G. Preserve in that license notice the full lists of Invariant Sections
1430+ and required Cover Texts given in the Document's license notice.
1431+H. Include an unaltered copy of this License.
1432+I. Preserve the section entitled "History", and its title, and add to
1433+ it an item stating at least the title, year, new authors, and
1434+ publisher of the Modified Version as given on the Title Page. If
1435+ there is no section entitled "History" in the Document, create one
1436+ stating the title, year, authors, and publisher of the Document as
1437+ given on its Title Page, then add an item describing the Modified
1438+ Version as stated in the previous sentence.
1439+J. Preserve the network location, if any, given in the Document for
1440+ public access to a Transparent copy of the Document, and likewise
1441+ the network locations given in the Document for previous versions
1442+ it was based on. These may be placed in the "History" section.
1443+ You may omit a network location for a work that was published at
1444+ least four years before the Document itself, or if the original
1445+ publisher of the version it refers to gives permission.
1446+K. In any section entitled "Acknowledgements" or "Dedications",
1447+ preserve the section's title, and preserve in the section all the
1448+ substance and tone of each of the contributor acknowledgements
1449+ and/or dedications given therein.
1450+L. Preserve all the Invariant Sections of the Document,
1451+ unaltered in their text and in their titles. Section numbers
1452+ or the equivalent are not considered part of the section titles.
1453+M. Delete any section entitled "Endorsements". Such a section
1454+ may not be included in the Modified Version.
1455+N. Do not retitle any existing section as "Endorsements"
1456+ or to conflict in title with any Invariant Section.
1457+
1458+If the Modified Version includes new front-matter sections or
1459+appendices that qualify as Secondary Sections and contain no material
1460+copied from the Document, you may at your option designate some or all
1461+of these sections as invariant. To do this, add their titles to the
1462+list of Invariant Sections in the Modified Version's license notice.
1463+These titles must be distinct from any other section titles.
1464+
1465+You may add a section entitled "Endorsements", provided it contains
1466+nothing but endorsements of your Modified Version by various
1467+parties--for example, statements of peer review or that the text has
1468+been approved by an organization as the authoritative definition of a
1469+standard.
1470+
1471+You may add a passage of up to five words as a Front-Cover Text, and a
1472+passage of up to 25 words as a Back-Cover Text, to the end of the list
1473+of Cover Texts in the Modified Version. Only one passage of
1474+Front-Cover Text and one of Back-Cover Text may be added by (or
1475+through arrangements made by) any one entity. If the Document already
1476+includes a cover text for the same cover, previously added by you or
1477+by arrangement made by the same entity you are acting on behalf of,
1478+you may not add another; but you may replace the old one, on explicit
1479+permission from the previous publisher that added the old one.
1480+
1481+The author(s) and publisher(s) of the Document do not by this License
1482+give permission to use their names for publicity for or to assert or
1483+imply endorsement of any Modified Version.
1484+
1485+
1486+5. COMBINING DOCUMENTS
1487+
1488+You may combine the Document with other documents released under this
1489+License, under the terms defined in section 4 above for modified
1490+versions, provided that you include in the combination all of the
1491+Invariant Sections of all of the original documents, unmodified, and
1492+list them all as Invariant Sections of your combined work in its
1493+license notice.
1494+
1495+The combined work need only contain one copy of this License, and
1496+multiple identical Invariant Sections may be replaced with a single
1497+copy. If there are multiple Invariant Sections with the same name but
1498+different contents, make the title of each such section unique by
1499+adding at the end of it, in parentheses, the name of the original
1500+author or publisher of that section if known, or else a unique number.
1501+Make the same adjustment to the section titles in the list of
1502+Invariant Sections in the license notice of the combined work.
1503+
1504+In the combination, you must combine any sections entitled "History"
1505+in the various original documents, forming one section entitled
1506+"History"; likewise combine any sections entitled "Acknowledgements",
1507+and any sections entitled "Dedications". You must delete all sections
1508+entitled "Endorsements."
1509+
1510+
1511+6. COLLECTIONS OF DOCUMENTS
1512+
1513+You may make a collection consisting of the Document and other documents
1514+released under this License, and replace the individual copies of this
1515+License in the various documents with a single copy that is included in
1516+the collection, provided that you follow the rules of this License for
1517+verbatim copying of each of the documents in all other respects.
1518+
1519+You may extract a single document from such a collection, and distribute
1520+it individually under this License, provided you insert a copy of this
1521+License into the extracted document, and follow this License in all
1522+other respects regarding verbatim copying of that document.
1523+
1524+
1525+7. AGGREGATION WITH INDEPENDENT WORKS
1526+
1527+A compilation of the Document or its derivatives with other separate
1528+and independent documents or works, in or on a volume of a storage or
1529+distribution medium, does not as a whole count as a Modified Version
1530+of the Document, provided no compilation copyright is claimed for the
1531+compilation. Such a compilation is called an "aggregate", and this
1532+License does not apply to the other self-contained works thus compiled
1533+with the Document, on account of their being thus compiled, if they
1534+are not themselves derivative works of the Document.
1535+
1536+If the Cover Text requirement of section 3 is applicable to these
1537+copies of the Document, then if the Document is less than one quarter
1538+of the entire aggregate, the Document's Cover Texts may be placed on
1539+covers that surround only the Document within the aggregate.
1540+Otherwise they must appear on covers around the whole aggregate.
1541+
1542+
1543+8. TRANSLATION
1544+
1545+Translation is considered a kind of modification, so you may
1546+distribute translations of the Document under the terms of section 4.
1547+Replacing Invariant Sections with translations requires special
1548+permission from their copyright holders, but you may include
1549+translations of some or all Invariant Sections in addition to the
1550+original versions of these Invariant Sections. You may include a
1551+translation of this License provided that you also include the
1552+original English version of this License. In case of a disagreement
1553+between the translation and the original English version of this
1554+License, the original English version will prevail.
1555+
1556+
1557+9. TERMINATION
1558+
1559+You may not copy, modify, sublicense, or distribute the Document except
1560+as expressly provided for under this License. Any other attempt to
1561+copy, modify, sublicense or distribute the Document is void, and will
1562+automatically terminate your rights under this License. However,
1563+parties who have received copies, or rights, from you under this
1564+License will not have their licenses terminated so long as such
1565+parties remain in full compliance.
1566+
1567+
1568+10. FUTURE REVISIONS OF THIS LICENSE
1569+
1570+The Free Software Foundation may publish new, revised versions
1571+of the GNU Free Documentation License from time to time. Such new
1572+versions will be similar in spirit to the present version, but may
1573+differ in detail to address new problems or concerns. See
1574+http://www.gnu.org/copyleft/.
1575+
1576+Each version of the License is given a distinguishing version number.
1577+If the Document specifies that a particular numbered version of this
1578+License "or any later version" applies to it, you have the option of
1579+following the terms and conditions either of that specified version or
1580+of any later version that has been published (not as a draft) by the
1581+Free Software Foundation. If the Document does not specify a version
1582+number of this License, you may choose any version ever published (not
1583+as a draft) by the Free Software Foundation.
1584+
1585+
1586+ADDENDUM: How to use this License for your documents
1587+
1588+To use this License in a document you have written, include a copy of
1589+the License in the document and put the following copyright and
1590+license notices just after the title page:
1591+
1592+@smallexample
1593+ Copyright (c) YEAR YOUR NAME.
1594+ Permission is granted to copy, distribute and/or modify this document
1595+ under the terms of the GNU Free Documentation License, Version 1.1
1596+ or any later version published by the Free Software Foundation;
1597+ with the Invariant Sections being LIST THEIR TITLES, with the
1598+ Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
1599+ A copy of the license is included in the section entitled "GNU
1600+ Free Documentation License".
1601+@end smallexample
1602+
1603+If you have no Invariant Sections, write "with no Invariant Sections"
1604+instead of saying which ones are invariant. If you have no
1605+Front-Cover Texts, write "no Front-Cover Texts" instead of
1606+"Front-Cover Texts being LIST"; likewise for Back-Cover Texts.
1607+
1608+If your document contains nontrivial examples of program code, we
1609+recommend releasing these examples in parallel under your choice of
1610+free software license, such as the GNU General Public License,
1611+to permit their use in free software.
1612+
1613+@node Index
1614+@unnumbered Index
1615+
1616+@printindex cp
1617+
1618+@contents
1619+@bye
1620diff -Nur binutils-2.13.90.0.18.orig/gas/gasp.c binutils-2.13.90.0.18/gas/gasp.c
1621--- binutils-2.13.90.0.18.orig/gas/gasp.c Thu Jan 1 01:00:00 1970
1622+++ binutils-2.13.90.0.18/gas/gasp.c Sun May 26 18:57:12 2002
1623@@ -0,0 +1,3761 @@
1624+/* gasp.c - Gnu assembler preprocessor main program.
1625+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
1626+ Free Software Foundation, Inc.
1627+
1628+ Written by Steve and Judy Chamberlain of Cygnus Support,
1629+ sac@cygnus.com
1630+
1631+ This file is part of GASP, the GNU Assembler Preprocessor.
1632+
1633+ GASP is free software; you can redistribute it and/or modify
1634+ it under the terms of the GNU General Public License as published by
1635+ the Free Software Foundation; either version 2, or (at your option)
1636+ any later version.
1637+
1638+ GASP is distributed in the hope that it will be useful,
1639+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1640+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1641+ GNU General Public License for more details.
1642+
1643+ You should have received a copy of the GNU General Public License
1644+ along with GASP; see the file COPYING. If not, write to the Free
1645+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
1646+ 02111-1307, USA. */
1647+
1648+/*
1649+This program translates the input macros and stuff into a form
1650+suitable for gas to consume.
1651+
1652+ gasp [-sdhau] [-c char] [-o <outfile>] <infile>*
1653+
1654+ -s copy source to output
1655+ -c <char> comments are started with <char> instead of !
1656+ -u allow unreasonable stuff
1657+ -p print line numbers
1658+ -d print debugging stats
1659+ -s semi colons start comments
1660+ -a use alternate syntax
1661+ Pseudo ops can start with or without a .
1662+ Labels have to be in first column.
1663+ -I specify include dir
1664+ Macro arg parameters subsituted by name, don't need the &.
1665+ String can start with ' too.
1666+ Strings can be surrounded by <..>
1667+ A %<exp> in a string evaluates the expression
1668+ Literal char in a string with !
1669+*/
1670+
1671+#include "config.h"
1672+#include "bin-bugs.h"
1673+
1674+#include <assert.h>
1675+#include <stdio.h>
1676+#include <string.h>
1677+#include "getopt.h"
1678+
1679+#ifdef HAVE_STDLIB_H
1680+#include <stdlib.h>
1681+#endif
1682+
1683+#ifdef NEED_MALLOC_DECLARATION
1684+extern char *malloc ();
1685+#endif
1686+
1687+#include "ansidecl.h"
1688+#include "libiberty.h"
1689+#include "safe-ctype.h"
1690+#include "sb.h"
1691+#include "macro.h"
1692+#include "asintl.h"
1693+#include "xregex.h"
1694+
1695+char *program_version = "1.2";
1696+
1697+/* This is normally declared in as.h, but we don't include that. We
1698+ need the function because other files linked with gasp.c might call
1699+ it. */
1700+extern void as_abort PARAMS ((const char *, int, const char *));
1701+
1702+/* The default obstack chunk size. If we set this to zero, the
1703+ obstack code will use whatever will fit in a 4096 byte block. This
1704+ is used by the hash table code used by macro.c. */
1705+int chunksize = 0;
1706+
1707+#define MAX_INCLUDES 30 /* Maximum include depth. */
1708+#define MAX_REASONABLE 1000 /* Maximum number of expansions. */
1709+
1710+int unreasonable; /* -u on command line. */
1711+int stats; /* -d on command line. */
1712+int print_line_number; /* -p flag on command line. */
1713+int copysource; /* -c flag on command line. */
1714+int warnings; /* Number of WARNINGs generated so far. */
1715+int errors; /* Number of ERRORs generated so far. */
1716+int fatals; /* Number of fatal ERRORs generated so far (either 0 or 1). */
1717+int alternate = 0; /* -a on command line. */
1718+int mri = 0; /* -M on command line. */
1719+char comment_char = '!';
1720+int radix = 10; /* Default radix. */
1721+
1722+int had_end; /* Seen .END. */
1723+
1724+/* The output stream. */
1725+FILE *outfile;
1726+
1727+/* The attributes of each character are stored as a bit pattern
1728+ chartype, which gives us quick tests. */
1729+
1730+#define FIRSTBIT 1
1731+#define NEXTBIT 2
1732+#define SEPBIT 4
1733+#define WHITEBIT 8
1734+#define COMMENTBIT 16
1735+#define BASEBIT 32
1736+#define ISCOMMENTCHAR(x) (chartype[(unsigned char)(x)] & COMMENTBIT)
1737+#define ISFIRSTCHAR(x) (chartype[(unsigned char)(x)] & FIRSTBIT)
1738+#define ISNEXTCHAR(x) (chartype[(unsigned char)(x)] & NEXTBIT)
1739+#define ISSEP(x) (chartype[(unsigned char)(x)] & SEPBIT)
1740+#define ISWHITE(x) (chartype[(unsigned char)(x)] & WHITEBIT)
1741+#define ISBASE(x) (chartype[(unsigned char)(x)] & BASEBIT)
1742+static char chartype[256];
1743+
1744+/* Conditional assembly uses the `ifstack'. Each aif pushes another
1745+ entry onto the stack, and sets the on flag if it should. The aelse
1746+ sets hadelse, and toggles on. An aend pops a level. We limit to
1747+ 100 levels of nesting, not because we're facists pigs with read
1748+ only minds, but because more than 100 levels of nesting is probably
1749+ a bug in the user's macro structure. */
1750+
1751+#define IFNESTING 100
1752+struct {
1753+ int on; /* Is the level being output. */
1754+ int hadelse; /* Has an aelse been seen. */
1755+} ifstack[IFNESTING];
1756+
1757+int ifi;
1758+
1759+/* The final and intermediate results of expression evaluation are kept in
1760+ exp_t's. Note that a symbol is not an sb, but a pointer into the input
1761+ line. It must be coped somewhere safe before the next line is read in. */
1762+
1763+typedef struct {
1764+ char *name;
1765+ int len;
1766+} symbol;
1767+
1768+typedef struct {
1769+ int value; /* Constant part. */
1770+ symbol add_symbol; /* Name part. */
1771+ symbol sub_symbol; /* Name part. */
1772+} exp_t;
1773+
1774+/* Hashing is done in a pretty standard way. A hash_table has a
1775+ pointer to a vector of pointers to hash_entrys, and the size of the
1776+ vector. A hash_entry contains a union of all the info we like to
1777+ store in hash table. If there is a hash collision, hash_entries
1778+ with the same hash are kept in a chain. */
1779+
1780+/* What the data in a hash_entry means. */
1781+typedef enum {
1782+ hash_integer, /* Name->integer mapping. */
1783+ hash_string, /* Name->string mapping. */
1784+ hash_macro, /* Name is a macro. */
1785+ hash_formal /* Name is a formal argument. */
1786+} hash_type;
1787+
1788+typedef struct hs {
1789+ sb key; /* Symbol name. */
1790+ hash_type type; /* Symbol meaning. */
1791+ union {
1792+ sb s;
1793+ int i;
1794+ struct macro_struct *m;
1795+ struct formal_struct *f;
1796+ } value;
1797+ struct hs *next; /* Next hash_entry with same hash key. */
1798+} hash_entry;
1799+
1800+typedef struct {
1801+ hash_entry **table;
1802+ int size;
1803+} hash_table;
1804+
1805+/* How we nest files and expand macros etc.
1806+
1807+ We keep a stack of of include_stack structs. Each include file
1808+ pushes a new level onto the stack. We keep an sb with a pushback
1809+ too. unget chars are pushed onto the pushback sb, getchars first
1810+ checks the pushback sb before reading from the input stream.
1811+
1812+ Small things are expanded by adding the text of the item onto the
1813+ pushback sb. Larger items are grown by pushing a new level and
1814+ allocating the entire pushback buf for the item. Each time
1815+ something like a macro is expanded, the stack index is changed. We
1816+ can then perform an exitm by popping all entries off the stack with
1817+ the same stack index. If we're being reasonable, we can detect
1818+ recusive expansion by checking the index is reasonably small. */
1819+
1820+typedef enum {
1821+ include_file, include_repeat, include_while, include_macro
1822+} include_type;
1823+
1824+struct include_stack {
1825+ sb pushback; /* Current pushback stream. */
1826+ int pushback_index; /* Next char to read from stream. */
1827+ FILE *handle; /* Open file. */
1828+ sb name; /* Name of file. */
1829+ int linecount; /* Number of lines read so far. */
1830+ include_type type;
1831+ int index; /* Index of this layer. */
1832+} include_stack[MAX_INCLUDES];
1833+
1834+struct include_stack *sp;
1835+#define isp (sp - include_stack)
1836+
1837+/* Include file list. */
1838+
1839+typedef struct include_path {
1840+ struct include_path *next;
1841+ sb path;
1842+} include_path;
1843+
1844+include_path *paths_head;
1845+include_path *paths_tail;
1846+
1847+static void quit PARAMS ((void));
1848+static void hash_new_table PARAMS ((int, hash_table *));
1849+static int hash PARAMS ((sb *));
1850+static hash_entry *hash_create PARAMS ((hash_table *, sb *));
1851+static void hash_add_to_string_table PARAMS ((hash_table *, sb *, sb *, int));
1852+static void hash_add_to_int_table PARAMS ((hash_table *, sb *, int));
1853+static hash_entry *hash_lookup PARAMS ((hash_table *, sb *));
1854+static void checkconst PARAMS ((int, exp_t *));
1855+static int is_flonum PARAMS ((int, sb *));
1856+static int chew_flonum PARAMS ((int, sb *, sb *));
1857+static int sb_strtol PARAMS ((int, sb *, int, int *));
1858+static int level_0 PARAMS ((int, sb *, exp_t *));
1859+static int level_1 PARAMS ((int, sb *, exp_t *));
1860+static int level_2 PARAMS ((int, sb *, exp_t *));
1861+static int level_3 PARAMS ((int, sb *, exp_t *));
1862+static int level_4 PARAMS ((int, sb *, exp_t *));
1863+static int level_5 PARAMS ((int, sb *, exp_t *));
1864+static int exp_parse PARAMS ((int, sb *, exp_t *));
1865+static void exp_string PARAMS ((exp_t *, sb *));
1866+static int exp_get_abs PARAMS ((const char *, int, sb *, int *));
1867+#if 0
1868+static void strip_comments PARAMS ((sb *));
1869+#endif
1870+static void unget PARAMS ((int));
1871+static void include_buf PARAMS ((sb *, sb *, include_type, int));
1872+static void include_print_where_line PARAMS ((FILE *));
1873+static void include_print_line PARAMS ((FILE *));
1874+static int get_line PARAMS ((sb *));
1875+static int grab_label PARAMS ((sb *, sb *));
1876+static void change_base PARAMS ((int, sb *, sb *));
1877+static void do_end PARAMS ((sb *));
1878+static void do_assign PARAMS ((int, int, sb *));
1879+static void do_radix PARAMS ((sb *));
1880+static int get_opsize PARAMS ((int, sb *, int *));
1881+static int eol PARAMS ((int, sb *));
1882+static void do_data PARAMS ((int, sb *, int));
1883+static void do_datab PARAMS ((int, sb *));
1884+static void do_align PARAMS ((int, sb *));
1885+static void do_res PARAMS ((int, sb *, int));
1886+static void do_export PARAMS ((sb *));
1887+static void do_print PARAMS ((int, sb *));
1888+static void do_heading PARAMS ((int, sb *));
1889+static void do_page PARAMS ((void));
1890+static void do_form PARAMS ((int, sb *));
1891+static int get_any_string PARAMS ((int, sb *, sb *, int, int));
1892+static int skip_openp PARAMS ((int, sb *));
1893+static int skip_closep PARAMS ((int, sb *));
1894+static int dolen PARAMS ((int, sb *, sb *));
1895+static int doinstr PARAMS ((int, sb *, sb *));
1896+static int dosubstr PARAMS ((int, sb *, sb *));
1897+static void process_assigns PARAMS ((int, sb *, sb *));
1898+static int get_and_process PARAMS ((int, sb *, sb *));
1899+static void process_file PARAMS ((void));
1900+static void free_old_entry PARAMS ((hash_entry *));
1901+static void do_assigna PARAMS ((int, sb *));
1902+static void do_assignc PARAMS ((int, sb *));
1903+static void do_reg PARAMS ((int, sb *));
1904+static int condass_lookup_name PARAMS ((sb *, int, sb *, int));
1905+static int whatcond PARAMS ((int, sb *, int *));
1906+static int istrue PARAMS ((int, sb *));
1907+static void do_aif PARAMS ((int, sb *));
1908+static void do_aelse PARAMS ((void));
1909+static void do_aendi PARAMS ((void));
1910+static int condass_on PARAMS ((void));
1911+static void do_if PARAMS ((int, sb *, int));
1912+static int get_mri_string PARAMS ((int, sb *, sb *, int));
1913+static void do_ifc PARAMS ((int, sb *, int));
1914+static void do_aendr PARAMS ((void));
1915+static void do_awhile PARAMS ((int, sb *));
1916+static void do_aendw PARAMS ((void));
1917+static void do_exitm PARAMS ((void));
1918+static void do_arepeat PARAMS ((int, sb *));
1919+static void do_endm PARAMS ((void));
1920+static void do_irp PARAMS ((int, sb *, int));
1921+static void do_local PARAMS ((int, sb *));
1922+static void do_macro PARAMS ((int, sb *));
1923+static int macro_op PARAMS ((int, sb *));
1924+static int getstring PARAMS ((int, sb *, sb *));
1925+static void do_sdata PARAMS ((int, sb *, int));
1926+static void do_sdatab PARAMS ((int, sb *));
1927+static int new_file PARAMS ((const char *));
1928+static void do_include PARAMS ((int, sb *));
1929+static void include_pop PARAMS ((void));
1930+static int get PARAMS ((void));
1931+static int linecount PARAMS ((void));
1932+static int include_next_index PARAMS ((void));
1933+static void chartype_init PARAMS ((void));
1934+static int process_pseudo_op PARAMS ((int, sb *, sb *));
1935+static void add_keyword PARAMS ((const char *, int));
1936+static void process_init PARAMS ((void));
1937+static void do_define PARAMS ((const char *));
1938+static void show_usage PARAMS ((FILE *, int));
1939+static void show_help PARAMS ((void));
1940+
1941+#define FATAL(x) \
1942+ do \
1943+ { \
1944+ include_print_where_line (stderr); \
1945+ fprintf x; \
1946+ fatals++; \
1947+ quit (); \
1948+ } \
1949+ while (0)
1950+
1951+#define ERROR(x) \
1952+ do \
1953+ { \
1954+ include_print_where_line (stderr); \
1955+ fprintf x; \
1956+ errors++; \
1957+ } \
1958+ while (0)
1959+
1960+#define WARNING(x) \
1961+ do \
1962+ { \
1963+ include_print_where_line (stderr); \
1964+ fprintf x; \
1965+ warnings++; \
1966+ } \
1967+ while (0)
1968+
1969+/* Exit the program and return the right ERROR code. */
1970+
1971+static void
1972+quit ()
1973+{
1974+ int exitcode;
1975+ if (fatals + errors)
1976+ exitcode = 1;
1977+ else
1978+ exitcode = 0;
1979+
1980+ if (stats)
1981+ {
1982+ int i;
1983+ for (i = 0; i < sb_max_power_two; i++)
1984+ {
1985+ fprintf (stderr, "strings size %8d : %d\n",
1986+ 1 << i, string_count[i]);
1987+ }
1988+ }
1989+ exit (exitcode);
1990+}
1991+
1992+/* Hash table maintenance. */
1993+
1994+/* Build a new hash table with size buckets
1995+ and fill in the info at ptr. */
1996+
1997+static void
1998+hash_new_table (size, ptr)
1999+ int size;
2000+ hash_table *ptr;
2001+{
2002+ int i;
2003+ ptr->size = size;
2004+ ptr->table = (hash_entry **) xmalloc (size * (sizeof (hash_entry *)));
2005+ /* Fill with null-pointer, not zero-bit-pattern. */
2006+ for (i = 0; i < size; i++)
2007+ ptr->table[i] = 0;
2008+}
2009+
2010+/* Calculate and return the hash value of the sb at key. */
2011+
2012+static int
2013+hash (key)
2014+ sb *key;
2015+{
2016+ int k = 0x1234;
2017+ int i;
2018+ char *p = key->ptr;
2019+ for (i = 0; i < key->len; i++)
2020+ {
2021+ k ^= (k << 2) ^ *p;
2022+ p++;
2023+ }
2024+ return k & 0xf0fff;
2025+}
2026+
2027+/* Look up key in hash_table tab. If present, then return it,
2028+ otherwise build a new one and fill it with hash_integer. */
2029+
2030+static hash_entry *
2031+hash_create (tab, key)
2032+ hash_table *tab;
2033+ sb *key;
2034+{
2035+ int k = hash (key) % tab->size;
2036+ hash_entry *p;
2037+ hash_entry **table = tab->table;
2038+
2039+ p = table[k];
2040+
2041+ while (1)
2042+ {
2043+ if (!p)
2044+ {
2045+ hash_entry *n = (hash_entry *) xmalloc (sizeof (hash_entry));
2046+ n->next = table[k];
2047+ sb_new (&n->key);
2048+ sb_add_sb (&n->key, key);
2049+ table[k] = n;
2050+ n->type = hash_integer;
2051+ return n;
2052+ }
2053+ if (strncmp (table[k]->key.ptr, key->ptr, key->len) == 0)
2054+ {
2055+ return p;
2056+ }
2057+ p = p->next;
2058+ }
2059+}
2060+
2061+/* Add sb name with key into hash_table tab.
2062+ If replacing old value and again, then ERROR. */
2063+
2064+static void
2065+hash_add_to_string_table (tab, key, name, again)
2066+ hash_table *tab;
2067+ sb *key;
2068+ sb *name;
2069+ int again;
2070+{
2071+ hash_entry *ptr = hash_create (tab, key);
2072+ if (ptr->type == hash_integer)
2073+ {
2074+ sb_new (&ptr->value.s);
2075+ }
2076+ if (ptr->value.s.len)
2077+ {
2078+ if (!again)
2079+ ERROR ((stderr, _("redefinition not allowed\n")));
2080+ }
2081+
2082+ ptr->type = hash_string;
2083+ sb_reset (&ptr->value.s);
2084+
2085+ sb_add_sb (&ptr->value.s, name);
2086+}
2087+
2088+/* Add integer name to hash_table tab with sb key. */
2089+
2090+static void
2091+hash_add_to_int_table (tab, key, name)
2092+ hash_table *tab;
2093+ sb *key;
2094+ int name;
2095+{
2096+ hash_entry *ptr = hash_create (tab, key);
2097+ ptr->value.i = name;
2098+}
2099+
2100+/* Look up sb key in hash_table tab.
2101+ If found, return hash_entry result, else 0. */
2102+
2103+static hash_entry *
2104+hash_lookup (tab, key)
2105+ hash_table *tab;
2106+ sb *key;
2107+{
2108+ int k = hash (key) % tab->size;
2109+ hash_entry **table = tab->table;
2110+ hash_entry *p = table[k];
2111+ while (p)
2112+ {
2113+ if (p->key.len == key->len
2114+ && strncmp (p->key.ptr, key->ptr, key->len) == 0)
2115+ return p;
2116+ p = p->next;
2117+ }
2118+ return 0;
2119+}
2120+
2121+/* expressions
2122+
2123+ are handled in a really simple recursive decent way. each bit of
2124+ the machine takes an index into an sb and a pointer to an exp_t,
2125+ modifies the *exp_t and returns the index of the first character
2126+ past the part of the expression parsed.
2127+
2128+ expression precedence:
2129+ ( )
2130+ unary + - ~
2131+ * /
2132+ + -
2133+ &
2134+ | ~
2135+*/
2136+
2137+/* Make sure that the exp_t at term is constant.
2138+ If not the give the op ERROR. */
2139+
2140+static void
2141+checkconst (op, term)
2142+ int op;
2143+ exp_t *term;
2144+{
2145+ if (term->add_symbol.len
2146+ || term->sub_symbol.len)
2147+ {
2148+ ERROR ((stderr, _("the %c operator cannot take non-absolute arguments.\n"), op));
2149+ }
2150+}
2151+
2152+/* Chew the flonum from the string starting at idx. Adjust idx to
2153+ point to the next character after the flonum. */
2154+
2155+static int
2156+chew_flonum (idx, string, out)
2157+ int idx;
2158+ sb *string;
2159+ sb *out;
2160+{
2161+ sb buf;
2162+ regex_t reg;
2163+ regmatch_t match;
2164+
2165+ /* Duplicate and null terminate `string'. */
2166+ sb_new (&buf);
2167+ sb_add_sb (&buf, string);
2168+ sb_add_char (&buf, '\0');
2169+
2170+ if (regcomp (&reg, "([0-9]*\\.[0-9]+([eE][+-]?[0-9]+)?)", REG_EXTENDED) != 0)
2171+ return idx;
2172+ if (regexec (&reg, &buf.ptr[idx], 1, &match, 0) != 0)
2173+ return idx;
2174+
2175+ /* Copy the match to the output. */
2176+ assert (match.rm_eo >= match.rm_so);
2177+ sb_add_buffer (out, &buf.ptr[idx], match.rm_eo - match.rm_so);
2178+
2179+ sb_kill (&buf);
2180+ regfree (&reg);
2181+ idx += match.rm_eo;
2182+ return idx;
2183+}
2184+
2185+static int
2186+is_flonum (idx, string)
2187+ int idx;
2188+ sb *string;
2189+{
2190+ sb buf;
2191+ regex_t reg;
2192+ int rc;
2193+
2194+ /* Duplicate and null terminate `string'. */
2195+ sb_new (&buf);
2196+ sb_add_sb (&buf, string);
2197+ sb_add_char (&buf, '\0');
2198+
2199+ if (regcomp (&reg, "^[0-9]*\\.[0-9]+([eE][+-]?[0-9]+)?", REG_EXTENDED) != 0)
2200+ return 0;
2201+
2202+ rc = regexec (&reg, &buf.ptr[idx], 0, NULL, 0);
2203+ sb_kill (&buf);
2204+ regfree (&reg);
2205+ return (rc == 0);
2206+}
2207+
2208+/* Turn the number in string at idx into a number of base, fill in
2209+ ptr, and return the index of the first character not in the number. */
2210+
2211+static int
2212+sb_strtol (idx, string, base, ptr)
2213+ int idx;
2214+ sb *string;
2215+ int base;
2216+ int *ptr;
2217+{
2218+ int value = 0;
2219+ idx = sb_skip_white (idx, string);
2220+
2221+ while (idx < string->len)
2222+ {
2223+ int ch = string->ptr[idx];
2224+ int dig = 0;
2225+ if (ISDIGIT (ch))
2226+ dig = ch - '0';
2227+ else if (ch >= 'a' && ch <= 'f')
2228+ dig = ch - 'a' + 10;
2229+ else if (ch >= 'A' && ch <= 'F')
2230+ dig = ch - 'A' + 10;
2231+ else
2232+ break;
2233+
2234+ if (dig >= base)
2235+ break;
2236+
2237+ value = value * base + dig;
2238+ idx++;
2239+ }
2240+ *ptr = value;
2241+ return idx;
2242+}
2243+
2244+static int
2245+level_0 (idx, string, lhs)
2246+ int idx;
2247+ sb *string;
2248+ exp_t *lhs;
2249+{
2250+ lhs->add_symbol.len = 0;
2251+ lhs->add_symbol.name = 0;
2252+
2253+ lhs->sub_symbol.len = 0;
2254+ lhs->sub_symbol.name = 0;
2255+
2256+ idx = sb_skip_white (idx, string);
2257+
2258+ lhs->value = 0;
2259+
2260+ if (ISDIGIT (string->ptr[idx]))
2261+ {
2262+ idx = sb_strtol (idx, string, 10, &lhs->value);
2263+ }
2264+ else if (ISFIRSTCHAR (string->ptr[idx]))
2265+ {
2266+ int len = 0;
2267+ lhs->add_symbol.name = string->ptr + idx;
2268+ while (idx < string->len && ISNEXTCHAR (string->ptr[idx]))
2269+ {
2270+ idx++;
2271+ len++;
2272+ }
2273+ lhs->add_symbol.len = len;
2274+ }
2275+ else if (string->ptr[idx] == '"')
2276+ {
2277+ sb acc;
2278+ sb_new (&acc);
2279+ ERROR ((stderr, _("string where expression expected.\n")));
2280+ idx = getstring (idx, string, &acc);
2281+ sb_kill (&acc);
2282+ }
2283+ else
2284+ {
2285+ ERROR ((stderr, _("can't find primary in expression.\n")));
2286+ idx++;
2287+ }
2288+ return sb_skip_white (idx, string);
2289+}
2290+
2291+static int
2292+level_1 (idx, string, lhs)
2293+ int idx;
2294+ sb *string;
2295+ exp_t *lhs;
2296+{
2297+ idx = sb_skip_white (idx, string);
2298+
2299+ switch (string->ptr[idx])
2300+ {
2301+ case '+':
2302+ idx = level_1 (idx + 1, string, lhs);
2303+ break;
2304+ case '~':
2305+ idx = level_1 (idx + 1, string, lhs);
2306+ checkconst ('~', lhs);
2307+ lhs->value = ~lhs->value;
2308+ break;
2309+ case '-':
2310+ {
2311+ symbol t;
2312+ idx = level_1 (idx + 1, string, lhs);
2313+ lhs->value = -lhs->value;
2314+ t = lhs->add_symbol;
2315+ lhs->add_symbol = lhs->sub_symbol;
2316+ lhs->sub_symbol = t;
2317+ break;
2318+ }
2319+ case '(':
2320+ idx++;
2321+ idx = level_5 (sb_skip_white (idx, string), string, lhs);
2322+ if (string->ptr[idx] != ')')
2323+ ERROR ((stderr, _("misplaced closing parens.\n")));
2324+ else
2325+ idx++;
2326+ break;
2327+ default:
2328+ idx = level_0 (idx, string, lhs);
2329+ break;
2330+ }
2331+ return sb_skip_white (idx, string);
2332+}
2333+
2334+static int
2335+level_2 (idx, string, lhs)
2336+ int idx;
2337+ sb *string;
2338+ exp_t *lhs;
2339+{
2340+ exp_t rhs;
2341+
2342+ idx = level_1 (idx, string, lhs);
2343+
2344+ while (idx < string->len && (string->ptr[idx] == '*'
2345+ || string->ptr[idx] == '/'))
2346+ {
2347+ char op = string->ptr[idx++];
2348+ idx = level_1 (idx, string, &rhs);
2349+ switch (op)
2350+ {
2351+ case '*':
2352+ checkconst ('*', lhs);
2353+ checkconst ('*', &rhs);
2354+ lhs->value *= rhs.value;
2355+ break;
2356+ case '/':
2357+ checkconst ('/', lhs);
2358+ checkconst ('/', &rhs);
2359+ if (rhs.value == 0)
2360+ ERROR ((stderr, _("attempt to divide by zero.\n")));
2361+ else
2362+ lhs->value /= rhs.value;
2363+ break;
2364+ }
2365+ }
2366+ return sb_skip_white (idx, string);
2367+}
2368+
2369+static int
2370+level_3 (idx, string, lhs)
2371+ int idx;
2372+ sb *string;
2373+ exp_t *lhs;
2374+{
2375+ exp_t rhs;
2376+
2377+ idx = level_2 (idx, string, lhs);
2378+
2379+ while (idx < string->len
2380+ && (string->ptr[idx] == '+'
2381+ || string->ptr[idx] == '-'))
2382+ {
2383+ char op = string->ptr[idx++];
2384+ idx = level_2 (idx, string, &rhs);
2385+ switch (op)
2386+ {
2387+ case '+':
2388+ lhs->value += rhs.value;
2389+ if (lhs->add_symbol.name && rhs.add_symbol.name)
2390+ {
2391+ ERROR ((stderr, _("can't add two relocatable expressions\n")));
2392+ }
2393+ /* Change nn+symbol to symbol + nn. */
2394+ if (rhs.add_symbol.name)
2395+ {
2396+ lhs->add_symbol = rhs.add_symbol;
2397+ }
2398+ break;
2399+ case '-':
2400+ lhs->value -= rhs.value;
2401+ lhs->sub_symbol = rhs.add_symbol;
2402+ break;
2403+ }
2404+ }
2405+ return sb_skip_white (idx, string);
2406+}
2407+
2408+static int
2409+level_4 (idx, string, lhs)
2410+ int idx;
2411+ sb *string;
2412+ exp_t *lhs;
2413+{
2414+ exp_t rhs;
2415+
2416+ idx = level_3 (idx, string, lhs);
2417+
2418+ while (idx < string->len &&
2419+ string->ptr[idx] == '&')
2420+ {
2421+ char op = string->ptr[idx++];
2422+ idx = level_3 (idx, string, &rhs);
2423+ switch (op)
2424+ {
2425+ case '&':
2426+ checkconst ('&', lhs);
2427+ checkconst ('&', &rhs);
2428+ lhs->value &= rhs.value;
2429+ break;
2430+ }
2431+ }
2432+ return sb_skip_white (idx, string);
2433+}
2434+
2435+static int
2436+level_5 (idx, string, lhs)
2437+ int idx;
2438+ sb *string;
2439+ exp_t *lhs;
2440+{
2441+ exp_t rhs;
2442+
2443+ idx = level_4 (idx, string, lhs);
2444+
2445+ while (idx < string->len
2446+ && (string->ptr[idx] == '|' || string->ptr[idx] == '~'))
2447+ {
2448+ char op = string->ptr[idx++];
2449+ idx = level_4 (idx, string, &rhs);
2450+ switch (op)
2451+ {
2452+ case '|':
2453+ checkconst ('|', lhs);
2454+ checkconst ('|', &rhs);
2455+ lhs->value |= rhs.value;
2456+ break;
2457+ case '~':
2458+ checkconst ('~', lhs);
2459+ checkconst ('~', &rhs);
2460+ lhs->value ^= rhs.value;
2461+ break;
2462+ }
2463+ }
2464+ return sb_skip_white (idx, string);
2465+}
2466+
2467+/* Parse the expression at offset idx into string, fill up res with
2468+ the result. Return the index of the first char past the
2469+ expression. */
2470+
2471+static int
2472+exp_parse (idx, string, res)
2473+ int idx;
2474+ sb *string;
2475+ exp_t *res;
2476+{
2477+ return level_5 (sb_skip_white (idx, string), string, res);
2478+}
2479+
2480+/* Turn the expression at exp into text and glue it onto the end of
2481+ string. */
2482+
2483+static void
2484+exp_string (exp, string)
2485+ exp_t *exp;
2486+ sb *string;
2487+{
2488+ int np = 0;
2489+ int ad = 0;
2490+ sb_reset (string);
2491+
2492+ if (exp->add_symbol.len)
2493+ {
2494+ sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
2495+ np = 1;
2496+ ad = 1;
2497+ }
2498+ if (exp->value)
2499+ {
2500+ char buf[20];
2501+ if (np)
2502+ sb_add_char (string, '+');
2503+ sprintf (buf, "%d", exp->value);
2504+ sb_add_string (string, buf);
2505+ np = 1;
2506+ ad = 1;
2507+ }
2508+ if (exp->sub_symbol.len)
2509+ {
2510+ sb_add_char (string, '-');
2511+ sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
2512+ np = 0;
2513+ ad = 1;
2514+ }
2515+
2516+ if (!ad)
2517+ sb_add_char (string, '0');
2518+}
2519+
2520+/* Parse the expression at offset idx into sb in. Return the value in
2521+ val. If the expression is not constant, give ERROR emsg. Return
2522+ the index of the first character past the end of the expression. */
2523+
2524+static int
2525+exp_get_abs (emsg, idx, in, val)
2526+ const char *emsg;
2527+ int idx;
2528+ sb *in;
2529+ int *val;
2530+{
2531+ exp_t res;
2532+ idx = exp_parse (idx, in, &res);
2533+ if (res.add_symbol.len || res.sub_symbol.len)
2534+ ERROR ((stderr, "%s", emsg));
2535+ *val = res.value;
2536+ return idx;
2537+}
2538+
2539+/* Current label parsed from line. */
2540+sb label;
2541+
2542+/* Hash table for all assigned variables. */
2543+hash_table assign_hash_table;
2544+
2545+/* Hash table for keyword. */
2546+hash_table keyword_hash_table;
2547+
2548+/* Hash table for eq variables. */
2549+hash_table vars;
2550+
2551+#define in_comment ';'
2552+
2553+#if 0
2554+static void
2555+strip_comments (out)
2556+ sb *out;
2557+{
2558+ char *s = out->ptr;
2559+ int i = 0;
2560+ for (i = 0; i < out->len; i++)
2561+ {
2562+ if (ISCOMMENTCHAR (s[i]))
2563+ {
2564+ out->len = i;
2565+ return;
2566+ }
2567+ }
2568+}
2569+#endif
2570+
2571+/* Push back character ch so that it can be read again. */
2572+
2573+static void
2574+unget (ch)
2575+ int ch;
2576+{
2577+ if (ch == '\n')
2578+ {
2579+ sp->linecount--;
2580+ }
2581+ if (sp->pushback_index)
2582+ sp->pushback_index--;
2583+ else
2584+ sb_add_char (&sp->pushback, ch);
2585+}
2586+
2587+/* Push the sb ptr onto the include stack, with the given name, type
2588+ and index. */
2589+
2590+static void
2591+include_buf (name, ptr, type, index)
2592+ sb *name;
2593+ sb *ptr;
2594+ include_type type;
2595+ int index;
2596+{
2597+ sp++;
2598+ if (sp - include_stack >= MAX_INCLUDES)
2599+ FATAL ((stderr, _("unreasonable nesting.\n")));
2600+ sb_new (&sp->name);
2601+ sb_add_sb (&sp->name, name);
2602+ sp->handle = 0;
2603+ sp->linecount = 1;
2604+ sp->pushback_index = 0;
2605+ sp->type = type;
2606+ sp->index = index;
2607+ sb_new (&sp->pushback);
2608+ sb_add_sb (&sp->pushback, ptr);
2609+}
2610+
2611+/* Used in ERROR messages, print info on where the include stack is
2612+ onto file. */
2613+
2614+static void
2615+include_print_where_line (file)
2616+ FILE *file;
2617+{
2618+ struct include_stack *p = include_stack + 1;
2619+
2620+ while (p <= sp)
2621+ {
2622+ fprintf (file, "%s:%d ", sb_name (&p->name), p->linecount - 1);
2623+ p++;
2624+ }
2625+}
2626+
2627+/* Used in listings, print the line number onto file. */
2628+
2629+static void
2630+include_print_line (file)
2631+ FILE *file;
2632+{
2633+ int n;
2634+ struct include_stack *p = include_stack + 1;
2635+
2636+ n = fprintf (file, "%4d", p->linecount);
2637+ p++;
2638+ while (p <= sp)
2639+ {
2640+ n += fprintf (file, ".%d", p->linecount);
2641+ p++;
2642+ }
2643+ while (n < 8 * 3)
2644+ {
2645+ fprintf (file, " ");
2646+ n++;
2647+ }
2648+}
2649+
2650+/* Read a line from the top of the include stack into sb in. */
2651+
2652+static int
2653+get_line (in)
2654+ sb *in;
2655+{
2656+ int online = 0;
2eacf7fd 2657+ int more = 1, ch = 0;
2859501d
JB
2658+
2659+ if (copysource)
2660+ {
2661+ putc (comment_char, outfile);
2662+ if (print_line_number)
2663+ include_print_line (outfile);
2664+ }
2665+
2666+ while (1)
2667+ {
2eacf7fd 2668+ ch = get ();
2859501d
JB
2669+
2670+ while (ch == '\r')
2671+ ch = get ();
2672+
2673+ if (ch == EOF)
2674+ {
2675+ if (online)
2676+ {
2677+ WARNING ((stderr, _("End of file not at start of line.\n")));
2678+ if (copysource)
2679+ putc ('\n', outfile);
2680+ ch = '\n';
2681+ }
2682+ else
2683+ more = 0;
2684+ break;
2685+ }
2686+
2687+ if (copysource)
2688+ {
2689+ putc (ch, outfile);
2690+ }
2691+
2692+ if (ch == '\n')
2693+ {
2694+ ch = get ();
2695+ online = 0;
2696+ if (ch == '+')
2697+ {
2698+ /* Continued line. */
2699+ if (copysource)
2700+ {
2701+ putc (comment_char, outfile);
2702+ putc ('+', outfile);
2703+ }
2704+ ch = get ();
2705+ }
2706+ else
2707+ {
2708+ if (ch != EOF)
2709+ unget (ch);
2eacf7fd 2710+ ch = '\n'; break;
2859501d
JB
2711+ }
2712+ }
2713+ else
2714+ {
2715+ sb_add_char (in, ch);
2716+ }
2717+ online++;
2718+ }
2719+
2eacf7fd 2720+ return more ? ch : 0;
2859501d
JB
2721+}
2722+
2723+/* Find a label from sb in and put it in out. */
2724+
2725+static int
2726+grab_label (in, out)
2727+ sb *in;
2728+ sb *out;
2729+{
2730+ int i = 0;
2731+ sb_reset (out);
2732+ if (ISFIRSTCHAR (in->ptr[i]) || in->ptr[i] == '\\')
2733+ {
2734+ sb_add_char (out, in->ptr[i]);
2735+ i++;
2736+ while ((ISNEXTCHAR (in->ptr[i])
2737+ || in->ptr[i] == '\\'
2738+ || in->ptr[i] == '&')
2739+ && i < in->len)
2740+ {
2741+ sb_add_char (out, in->ptr[i]);
2742+ i++;
2743+ }
2744+ }
2745+ return i;
2746+}
2747+
2748+/* Find all strange base stuff and turn into decimal. Also
2749+ find all the other numbers and convert them from the default radix. */
2750+
2751+static void
2752+change_base (idx, in, out)
2753+ int idx;
2754+ sb *in;
2755+ sb *out;
2756+{
2757+ char buffer[20];
2758+
2759+ while (idx < in->len)
2760+ {
2761+ if (in->ptr[idx] == '\\'
2762+ && idx + 1 < in->len
2763+ && in->ptr[idx + 1] == '(')
2764+ {
2765+ idx += 2;
2766+ while (idx < in->len
2767+ && in->ptr[idx] != ')')
2768+ {
2769+ sb_add_char (out, in->ptr[idx]);
2770+ idx++;
2771+ }
2772+ if (idx < in->len)
2773+ idx++;
2774+ }
2775+ else if (idx < in->len - 1 && in->ptr[idx + 1] == '\'' && ! mri)
2776+ {
2777+ int base;
2778+ int value;
2779+ switch (in->ptr[idx])
2780+ {
2781+ case 'b':
2782+ case 'B':
2783+ base = 2;
2784+ break;
2785+ case 'q':
2786+ case 'Q':
2787+ base = 8;
2788+ break;
2789+ case 'h':
2790+ case 'H':
2791+ base = 16;
2792+ break;
2793+ case 'd':
2794+ case 'D':
2795+ base = 10;
2796+ break;
2797+ default:
2798+ ERROR ((stderr, _("Illegal base character %c.\n"), in->ptr[idx]));
2799+ base = 10;
2800+ break;
2801+ }
2802+
2803+ idx = sb_strtol (idx + 2, in, base, &value);
2804+ sprintf (buffer, "%d", value);
2805+ sb_add_string (out, buffer);
2806+ }
2807+ else if (ISFIRSTCHAR (in->ptr[idx]))
2808+ {
2809+ /* Copy entire names through quickly. */
2810+ sb_add_char (out, in->ptr[idx]);
2811+ idx++;
2812+ while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
2813+ {
2814+ sb_add_char (out, in->ptr[idx]);
2815+ idx++;
2816+ }
2817+ }
2818+ else if (is_flonum (idx, in))
2819+ {
2820+ idx = chew_flonum (idx, in, out);
2821+ }
2822+ else if (ISDIGIT (in->ptr[idx]))
2823+ {
2824+ int value;
2825+ /* All numbers must start with a digit, let's chew it and
2826+ spit out decimal. */
2827+ idx = sb_strtol (idx, in, radix, &value);
2828+ sprintf (buffer, "%d", value);
2829+ sb_add_string (out, buffer);
2830+
2831+ /* Skip all undigsested letters. */
2832+ while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
2833+ {
2834+ sb_add_char (out, in->ptr[idx]);
2835+ idx++;
2836+ }
2837+ }
2838+ else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
2839+ {
2840+ char tchar = in->ptr[idx];
2841+ /* Copy entire names through quickly. */
2842+ sb_add_char (out, in->ptr[idx]);
2843+ idx++;
2844+ while (idx < in->len && in->ptr[idx] != tchar)
2845+ {
2846+ sb_add_char (out, in->ptr[idx]);
2847+ idx++;
2848+ }
2849+ }
2850+ else
2851+ {
2852+ /* Nothing special, just pass it through. */
2853+ sb_add_char (out, in->ptr[idx]);
2854+ idx++;
2855+ }
2856+ }
2857+
2858+}
2859+
2860+/* .end */
2861+
2862+static void
2863+do_end (in)
2864+ sb *in;
2865+{
2866+ had_end = 1;
2867+ if (mri)
2868+ fprintf (outfile, "%s\n", sb_name (in));
2869+}
2870+
2871+/* .assign */
2872+
2873+static void
2874+do_assign (again, idx, in)
2875+ int again;
2876+ int idx;
2877+ sb *in;
2878+{
2879+ /* Stick label in symbol table with following value. */
2880+ exp_t e;
2881+ sb acc;
2882+
2883+ sb_new (&acc);
2884+ idx = exp_parse (idx, in, &e);
2885+ exp_string (&e, &acc);
2886+ hash_add_to_string_table (&assign_hash_table, &label, &acc, again);
2887+ sb_kill (&acc);
2888+}
2889+
2890+/* .radix [b|q|d|h] */
2891+
2892+static void
2893+do_radix (ptr)
2894+ sb *ptr;
2895+{
2896+ int idx = sb_skip_white (0, ptr);
2897+ switch (ptr->ptr[idx])
2898+ {
2899+ case 'B':
2900+ case 'b':
2901+ radix = 2;
2902+ break;
2903+ case 'q':
2904+ case 'Q':
2905+ radix = 8;
2906+ break;
2907+ case 'd':
2908+ case 'D':
2909+ radix = 10;
2910+ break;
2911+ case 'h':
2912+ case 'H':
2913+ radix = 16;
2914+ break;
2915+ default:
2916+ ERROR ((stderr, _("radix is %c must be one of b, q, d or h"), radix));
2917+ }
2918+}
2919+
2920+/* Parse off a .b, .w or .l. */
2921+
2922+static int
2923+get_opsize (idx, in, size)
2924+ int idx;
2925+ sb *in;
2926+ int *size;
2927+{
2928+ *size = 4;
2929+ if (in->ptr[idx] == '.')
2930+ {
2931+ idx++;
2932+ }
2933+ switch (in->ptr[idx])
2934+ {
2935+ case 'b':
2936+ case 'B':
2937+ *size = 1;
2938+ break;
2939+ case 'w':
2940+ case 'W':
2941+ *size = 2;
2942+ break;
2943+ case 'l':
2944+ case 'L':
2945+ *size = 4;
2946+ break;
2947+ case ' ':
2948+ case '\t':
2949+ break;
2950+ default:
2951+ ERROR ((stderr, _("size must be one of b, w or l, is %c.\n"), in->ptr[idx]));
2952+ break;
2953+ }
2954+ idx++;
2955+
2956+ return idx;
2957+}
2958+
2959+static int
2960+eol (idx, line)
2961+ int idx;
2962+ sb *line;
2963+{
2964+ idx = sb_skip_white (idx, line);
2965+ if (idx < line->len
2966+ && ISCOMMENTCHAR(line->ptr[idx]))
2967+ return 1;
2968+ if (idx >= line->len)
2969+ return 1;
2970+ return 0;
2971+}
2972+
2973+/* .data [.b|.w|.l] <data>*
2974+ or d[bwl] <data>* */
2975+
2976+static void
2977+do_data (idx, in, size)
2978+ int idx;
2979+ sb *in;
2980+ int size;
2981+{
2982+ int opsize = 4;
2983+ char *opname = ".yikes!";
2984+ sb acc;
2985+ sb_new (&acc);
2986+
2987+ if (!size)
2988+ {
2989+ idx = get_opsize (idx, in, &opsize);
2990+ }
2991+ else
2992+ {
2993+ opsize = size;
2994+ }
2995+ switch (opsize)
2996+ {
2997+ case 4:
2998+ opname = ".long";
2999+ break;
3000+ case 2:
3001+ opname = ".short";
3002+ break;
3003+ case 1:
3004+ opname = ".byte";
3005+ break;
3006+ }
3007+
3008+ fprintf (outfile, "%s\t", opname);
3009+
3010+ idx = sb_skip_white (idx, in);
3011+
3012+ if (alternate
3013+ && idx < in->len
3014+ && in->ptr[idx] == '"')
3015+ {
3016+ int i;
3017+ idx = getstring (idx, in, &acc);
3018+ for (i = 0; i < acc.len; i++)
3019+ {
3020+ if (i)
3021+ fprintf (outfile, ",");
3022+ fprintf (outfile, "%d", acc.ptr[i]);
3023+ }
3024+ }
3025+ else
3026+ {
3027+ while (!eol (idx, in))
3028+ {
3029+ exp_t e;
3030+ idx = exp_parse (idx, in, &e);
3031+ exp_string (&e, &acc);
3032+ sb_add_char (&acc, 0);
3033+ fprintf (outfile, "%s", acc.ptr);
3034+ if (idx < in->len && in->ptr[idx] == ',')
3035+ {
3036+ fprintf (outfile, ",");
3037+ idx++;
3038+ }
3039+ }
3040+ }
3041+ sb_kill (&acc);
3042+ sb_print_at (outfile, idx, in);
3043+ fprintf (outfile, "\n");
3044+}
3045+
3046+/* .datab [.b|.w|.l] <repeat>,<fill> */
3047+
3048+static void
3049+do_datab (idx, in)
3050+ int idx;
3051+ sb *in;
3052+{
3053+ int opsize;
3054+ int repeat;
3055+ int fill;
3056+
3057+ idx = get_opsize (idx, in, &opsize);
3058+
3059+ idx = exp_get_abs (_("datab repeat must be constant.\n"), idx, in, &repeat);
3060+ idx = sb_skip_comma (idx, in);
3061+ idx = exp_get_abs (_("datab data must be absolute.\n"), idx, in, &fill);
3062+
3063+ fprintf (outfile, ".fill\t%d,%d,%d\n", repeat, opsize, fill);
3064+}
3065+
3066+/* .align <size> */
3067+
3068+static void
3069+do_align (idx, in)
3070+ int idx;
3071+ sb *in;
3072+{
3073+ int al, have_fill, fill;
3074+
3075+ idx = exp_get_abs (_("align needs absolute expression.\n"), idx, in, &al);
3076+ idx = sb_skip_white (idx, in);
3077+ have_fill = 0;
3078+ fill = 0;
3079+ if (! eol (idx, in))
3080+ {
3081+ idx = sb_skip_comma (idx, in);
3082+ idx = exp_get_abs (_(".align needs absolute fill value.\n"), idx, in,
3083+ &fill);
3084+ have_fill = 1;
3085+ }
3086+
3087+ fprintf (outfile, ".align %d", al);
3088+ if (have_fill)
3089+ fprintf (outfile, ",%d", fill);
3090+ fprintf (outfile, "\n");
3091+}
3092+
3093+/* .res[.b|.w|.l] <size> */
3094+
3095+static void
3096+do_res (idx, in, type)
3097+ int idx;
3098+ sb *in;
3099+ int type;
3100+{
3101+ int size = 4;
3102+ int count = 0;
3103+
3104+ idx = get_opsize (idx, in, &size);
3105+ while (!eol (idx, in))
3106+ {
3107+ idx = sb_skip_white (idx, in);
3108+ if (in->ptr[idx] == ',')
3109+ idx++;
3110+ idx = exp_get_abs (_("res needs absolute expression for fill count.\n"), idx, in, &count);
3111+
3112+ if (type == 'c' || type == 'z')
3113+ count++;
3114+
3115+ fprintf (outfile, ".space %d\n", count * size);
3116+ }
3117+}
3118+
3119+/* .export */
3120+
3121+static void
3122+do_export (in)
3123+ sb *in;
3124+{
3125+ fprintf (outfile, ".global %s\n", sb_name (in));
3126+}
3127+
3128+/* .print [list] [nolist] */
3129+
3130+static void
3131+do_print (idx, in)
3132+ int idx;
3133+ sb *in;
3134+{
3135+ idx = sb_skip_white (idx, in);
3136+ while (idx < in->len)
3137+ {
3138+ if (strncasecmp (in->ptr + idx, "LIST", 4) == 0)
3139+ {
3140+ fprintf (outfile, ".list\n");
3141+ idx += 4;
3142+ }
3143+ else if (strncasecmp (in->ptr + idx, "NOLIST", 6) == 0)
3144+ {
3145+ fprintf (outfile, ".nolist\n");
3146+ idx += 6;
3147+ }
3148+ idx++;
3149+ }
3150+}
3151+
3152+/* .head */
3153+
3154+static void
3155+do_heading (idx, in)
3156+ int idx;
3157+ sb *in;
3158+{
3159+ sb head;
3160+ sb_new (&head);
3161+ idx = getstring (idx, in, &head);
3162+ fprintf (outfile, ".title \"%s\"\n", sb_name (&head));
3163+ sb_kill (&head);
3164+}
3165+
3166+/* .page */
3167+
3168+static void
3169+do_page ()
3170+{
3171+ fprintf (outfile, ".eject\n");
3172+}
3173+
3174+/* .form [lin=<value>] [col=<value>] */
3175+
3176+static void
3177+do_form (idx, in)
3178+ int idx;
3179+ sb *in;
3180+{
3181+ int lines = 60;
3182+ int columns = 132;
3183+ idx = sb_skip_white (idx, in);
3184+
3185+ while (idx < in->len)
3186+ {
3187+
3188+ if (strncasecmp (in->ptr + idx, "LIN=", 4) == 0)
3189+ {
3190+ idx += 4;
3191+ idx = exp_get_abs (_("form LIN= needs absolute expresssion.\n"), idx, in, &lines);
3192+ }
3193+
3194+ if (strncasecmp (in->ptr + idx, _("COL="), 4) == 0)
3195+ {
3196+ idx += 4;
3197+ idx = exp_get_abs (_("form COL= needs absolute expresssion.\n"), idx, in, &columns);
3198+ }
3199+
3200+ idx++;
3201+ }
3202+ fprintf (outfile, ".psize %d,%d\n", lines, columns);
3203+
3204+}
3205+
3206+/* Fetch string from the input stream,
3207+ rules:
3208+ 'Bxyx<whitespace> -> return 'Bxyza
3209+ %<char> -> return string of decimal value of x
3210+ "<string>" -> return string
3211+ xyx<whitespace> -> return xyz
3212+*/
3213+
3214+static int
3215+get_any_string (idx, in, out, expand, pretend_quoted)
3216+ int idx;
3217+ sb *in;
3218+ sb *out;
3219+ int expand;
3220+ int pretend_quoted;
3221+{
3222+ sb_reset (out);
3223+ idx = sb_skip_white (idx, in);
3224+
3225+ if (idx < in->len)
3226+ {
3227+ if (in->len > 2 && in->ptr[idx + 1] == '\'' && ISBASE (in->ptr[idx]))
3228+ {
3229+ while (!ISSEP (in->ptr[idx]))
3230+ sb_add_char (out, in->ptr[idx++]);
3231+ }
3232+ else if (in->ptr[idx] == '%'
3233+ && alternate
3234+ && expand)
3235+ {
3236+ int val;
3237+ char buf[20];
3238+ /* Turns the next expression into a string. */
3239+ /* xgettext: no-c-format */
3240+ idx = exp_get_abs (_("% operator needs absolute expression"),
3241+ idx + 1,
3242+ in,
3243+ &val);
3244+ sprintf (buf, "%d", val);
3245+ sb_add_string (out, buf);
3246+ }
3247+ else if (in->ptr[idx] == '"'
3248+ || in->ptr[idx] == '<'
3249+ || (alternate && in->ptr[idx] == '\''))
3250+ {
3251+ if (alternate && expand)
3252+ {
3253+ /* Keep the quotes. */
3254+ sb_add_char (out, '\"');
3255+
3256+ idx = getstring (idx, in, out);
3257+ sb_add_char (out, '\"');
3258+
3259+ }
3260+ else
3261+ {
3262+ idx = getstring (idx, in, out);
3263+ }
3264+ }
3265+ else
3266+ {
3267+ while (idx < in->len
3268+ && (in->ptr[idx] == '"'
3269+ || in->ptr[idx] == '\''
3270+ || pretend_quoted
3271+ || !ISSEP (in->ptr[idx])))
3272+ {
3273+ if (in->ptr[idx] == '"'
3274+ || in->ptr[idx] == '\'')
3275+ {
3276+ char tchar = in->ptr[idx];
3277+ sb_add_char (out, in->ptr[idx++]);
3278+ while (idx < in->len
3279+ && in->ptr[idx] != tchar)
3280+ sb_add_char (out, in->ptr[idx++]);
3281+ if (idx == in->len)
3282+ return idx;
3283+ }
3284+ sb_add_char (out, in->ptr[idx++]);
3285+ }
3286+ }
3287+ }
3288+
3289+ return idx;
3290+}
3291+
3292+/* Skip along sb in starting at idx, suck off whitespace a ( and more
3293+ whitespace. Return the idx of the next char. */
3294+
3295+static int
3296+skip_openp (idx, in)
3297+ int idx;
3298+ sb *in;
3299+{
3300+ idx = sb_skip_white (idx, in);
3301+ if (in->ptr[idx] != '(')
3302+ ERROR ((stderr, _("misplaced ( .\n")));
3303+ idx = sb_skip_white (idx + 1, in);
3304+ return idx;
3305+}
3306+
3307+/* Skip along sb in starting at idx, suck off whitespace a ) and more
3308+ whitespace. Return the idx of the next char. */
3309+
3310+static int
3311+skip_closep (idx, in)
3312+ int idx;
3313+ sb *in;
3314+{
3315+ idx = sb_skip_white (idx, in);
3316+ if (in->ptr[idx] != ')')
3317+ ERROR ((stderr, _("misplaced ).\n")));
3318+ idx = sb_skip_white (idx + 1, in);
3319+ return idx;
3320+}
3321+
3322+/* .len */
3323+
3324+static int
3325+dolen (idx, in, out)
3326+ int idx;
3327+ sb *in;
3328+ sb *out;
3329+{
3330+
3331+ sb stringout;
3332+ char buffer[10];
3333+
3334+ sb_new (&stringout);
3335+ idx = skip_openp (idx, in);
3336+ idx = get_and_process (idx, in, &stringout);
3337+ idx = skip_closep (idx, in);
3338+ sprintf (buffer, "%d", stringout.len);
3339+ sb_add_string (out, buffer);
3340+
3341+ sb_kill (&stringout);
3342+ return idx;
3343+}
3344+
3345+/* .instr */
3346+
3347+static int
3348+doinstr (idx, in, out)
3349+ int idx;
3350+ sb *in;
3351+ sb *out;
3352+{
3353+ sb string;
3354+ sb search;
3355+ int i;
3356+ int start;
3357+ int res;
3358+ char buffer[10];
3359+
3360+ sb_new (&string);
3361+ sb_new (&search);
3362+ idx = skip_openp (idx, in);
3363+ idx = get_and_process (idx, in, &string);
3364+ idx = sb_skip_comma (idx, in);
3365+ idx = get_and_process (idx, in, &search);
3366+ idx = sb_skip_comma (idx, in);
3367+ if (ISDIGIT (in->ptr[idx]))
3368+ {
3369+ idx = exp_get_abs (_(".instr needs absolute expresson.\n"), idx, in, &start);
3370+ }
3371+ else
3372+ {
3373+ start = 0;
3374+ }
3375+ idx = skip_closep (idx, in);
3376+ res = -1;
3377+ for (i = start; i < string.len; i++)
3378+ {
3379+ if (strncmp (string.ptr + i, search.ptr, search.len) == 0)
3380+ {
3381+ res = i;
3382+ break;
3383+ }
3384+ }
3385+ sprintf (buffer, "%d", res);
3386+ sb_add_string (out, buffer);
3387+ sb_kill (&string);
3388+ sb_kill (&search);
3389+ return idx;
3390+}
3391+
3392+static int
3393+dosubstr (idx, in, out)
3394+ int idx;
3395+ sb *in;
3396+ sb *out;
3397+{
3398+ sb string;
3399+ int pos;
3400+ int len;
3401+ sb_new (&string);
3402+
3403+ idx = skip_openp (idx, in);
3404+ idx = get_and_process (idx, in, &string);
3405+ idx = sb_skip_comma (idx, in);
3406+ idx = exp_get_abs (_("need absolute position.\n"), idx, in, &pos);
3407+ idx = sb_skip_comma (idx, in);
3408+ idx = exp_get_abs (_("need absolute length.\n"), idx, in, &len);
3409+ idx = skip_closep (idx, in);
3410+
3411+ if (len < 0 || pos < 0 ||
3412+ pos > string.len
3413+ || pos + len > string.len)
3414+ {
3415+ sb_add_string (out, " ");
3416+ }
3417+ else
3418+ {
3419+ sb_add_char (out, '"');
3420+ while (len > 0)
3421+ {
3422+ sb_add_char (out, string.ptr[pos++]);
3423+ len--;
3424+ }
3425+ sb_add_char (out, '"');
3426+ }
3427+ sb_kill (&string);
3428+ return idx;
3429+}
3430+
3431+/* Scan line, change tokens in the hash table to their replacements. */
3432+
3433+static void
3434+process_assigns (idx, in, buf)
3435+ int idx;
3436+ sb *in;
3437+ sb *buf;
3438+{
3439+ while (idx < in->len)
3440+ {
3441+ hash_entry *ptr;
3442+ if (in->ptr[idx] == '\\'
3443+ && idx + 1 < in->len
3444+ && in->ptr[idx + 1] == '(')
3445+ {
3446+ do
3447+ {
3448+ sb_add_char (buf, in->ptr[idx]);
3449+ idx++;
3450+ }
3451+ while (idx < in->len && in->ptr[idx - 1] != ')');
3452+ }
3453+ else if (in->ptr[idx] == '\\'
3454+ && idx + 1 < in->len
3455+ && in->ptr[idx + 1] == '&')
3456+ {
3457+ idx = condass_lookup_name (in, idx + 2, buf, 1);
3458+ }
3459+ else if (in->ptr[idx] == '\\'
3460+ && idx + 1 < in->len
3461+ && in->ptr[idx + 1] == '$')
3462+ {
3463+ idx = condass_lookup_name (in, idx + 2, buf, 0);
3464+ }
3465+ else if (idx + 3 < in->len
3466+ && in->ptr[idx] == '.'
3467+ && TOUPPER (in->ptr[idx + 1]) == 'L'
3468+ && TOUPPER (in->ptr[idx + 2]) == 'E'
3469+ && TOUPPER (in->ptr[idx + 3]) == 'N')
3470+ idx = dolen (idx + 4, in, buf);
3471+ else if (idx + 6 < in->len
3472+ && in->ptr[idx] == '.'
3473+ && TOUPPER (in->ptr[idx + 1]) == 'I'
3474+ && TOUPPER (in->ptr[idx + 2]) == 'N'
3475+ && TOUPPER (in->ptr[idx + 3]) == 'S'
3476+ && TOUPPER (in->ptr[idx + 4]) == 'T'
3477+ && TOUPPER (in->ptr[idx + 5]) == 'R')
3478+ idx = doinstr (idx + 6, in, buf);
3479+ else if (idx + 7 < in->len
3480+ && in->ptr[idx] == '.'
3481+ && TOUPPER (in->ptr[idx + 1]) == 'S'
3482+ && TOUPPER (in->ptr[idx + 2]) == 'U'
3483+ && TOUPPER (in->ptr[idx + 3]) == 'B'
3484+ && TOUPPER (in->ptr[idx + 4]) == 'S'
3485+ && TOUPPER (in->ptr[idx + 5]) == 'T'
3486+ && TOUPPER (in->ptr[idx + 6]) == 'R')
3487+ idx = dosubstr (idx + 7, in, buf);
3488+ else if (ISFIRSTCHAR (in->ptr[idx]))
3489+ {
3490+ /* May be a simple name subsitution, see if we have a word. */
3491+ sb acc;
3492+ int cur = idx + 1;
3493+ while (cur < in->len
3494+ && (ISNEXTCHAR (in->ptr[cur])))
3495+ cur++;
3496+
3497+ sb_new (&acc);
3498+ sb_add_buffer (&acc, in->ptr + idx, cur - idx);
3499+ ptr = hash_lookup (&assign_hash_table, &acc);
3500+ if (ptr)
3501+ {
3502+ /* Found a definition for it. */
3503+ sb_add_sb (buf, &ptr->value.s);
3504+ }
3505+ else
3506+ {
3507+ /* No definition, just copy the word. */
3508+ sb_add_sb (buf, &acc);
3509+ }
3510+ sb_kill (&acc);
3511+ idx = cur;
3512+ }
3513+ else
3514+ {
3515+ sb_add_char (buf, in->ptr[idx++]);
3516+ }
3517+ }
3518+}
3519+
3520+static int
3521+get_and_process (idx, in, out)
3522+ int idx;
3523+ sb *in;
3524+ sb *out;
3525+{
3526+ sb t;
3527+ sb_new (&t);
3528+ idx = get_any_string (idx, in, &t, 1, 0);
3529+ process_assigns (0, &t, out);
3530+ sb_kill (&t);
3531+ return idx;
3532+}
3533+
3534+static void
3535+process_file ()
3536+{
3537+ sb line;
3538+ sb t1, t2;
3539+ sb acc;
3540+ sb label_in;
3541+ int more;
3542+
3543+ sb_new (&line);
3544+ sb_new (&t1);
3545+ sb_new (&t2);
3546+ sb_new (&acc);
3547+ sb_new (&label_in);
3548+ sb_reset (&line);
3549+ more = get_line (&line);
3550+ while (more)
3551+ {
3552+ /* Find any label and pseudo op that we're intested in. */
3553+ int l;
3554+ if (line.len == 0)
3555+ {
3556+ if (condass_on ())
3557+ fprintf (outfile, "\n");
3558+ }
3559+ else if (mri
3560+ && (line.ptr[0] == '*'
3561+ || line.ptr[0] == '!'))
3562+ {
3563+ /* MRI line comment. */
3564+ fprintf (outfile, "%s", sb_name (&line));
3565+ }
3566+ else
3567+ {
3568+ l = grab_label (&line, &label_in);
3569+ sb_reset (&label);
3570+
3571+ if (line.ptr[l] == ':')
3572+ l++;
3573+ while (ISWHITE (line.ptr[l]) && l < line.len)
3574+ l++;
3575+
3576+ if (label_in.len)
3577+ {
3578+ int do_assigns;
3579+
3580+ /* Munge the label, unless this is EQU or ASSIGN. */
3581+ do_assigns = 1;
3582+ if (l < line.len
3583+ && (line.ptr[l] == '.' || alternate || mri))
3584+ {
3585+ int lx = l;
3586+
3587+ if (line.ptr[lx] == '.')
3588+ ++lx;
3589+ if (lx + 3 <= line.len
3590+ && strncasecmp ("EQU", line.ptr + lx, 3) == 0
3591+ && (lx + 3 == line.len
3592+ || ! ISFIRSTCHAR (line.ptr[lx + 3])))
3593+ do_assigns = 0;
3594+ else if (lx + 6 <= line.len
3595+ && strncasecmp ("ASSIGN", line.ptr + lx, 6) == 0
3596+ && (lx + 6 == line.len
3597+ || ! ISFIRSTCHAR (line.ptr[lx + 6])))
3598+ do_assigns = 0;
3599+ }
3600+
3601+ if (do_assigns)
3602+ process_assigns (0, &label_in, &label);
3603+ else
3604+ sb_add_sb (&label, &label_in);
3605+ }
3606+
3607+ if (l < line.len)
3608+ {
3609+ if (process_pseudo_op (l, &line, &acc))
3610+ {
3611+
3612+ }
3613+ else if (condass_on ())
3614+ {
3615+ if (macro_op (l, &line))
3616+ {
3617+
3618+ }
3619+ else
3620+ {
3621+ {
3622+ if (label.len)
3623+ {
3624+ fprintf (outfile, "%s:\t", sb_name (&label));
3625+ }
3626+ else
3627+ fprintf (outfile, "\t");
3628+ sb_reset (&t1);
3629+ process_assigns (l, &line, &t1);
3630+ sb_reset (&t2);
3631+ change_base (0, &t1, &t2);
3632+ fprintf (outfile, "%s\n", sb_name (&t2));
3633+ }
3634+ }
3635+ }
3636+ }
3637+ else
3638+ {
3639+ /* Only a label on this line. */
3640+ if (label.len && condass_on ())
3641+ {
3642+ fprintf (outfile, "%s:\n", sb_name (&label));
3643+ }
3644+ }
3645+ }
3646+
3647+ if (had_end)
3648+ break;
3649+ sb_reset (&line);
3650+ more = get_line (&line);
3651+ }
3652+
3653+ if (!had_end && !mri)
3654+ WARNING ((stderr, _("END missing from end of file.\n")));
3655+}
3656+
3657+static void
3658+free_old_entry (ptr)
3659+ hash_entry *ptr;
3660+{
3661+ if (ptr)
3662+ {
3663+ if (ptr->type == hash_string)
3664+ sb_kill (&ptr->value.s);
3665+ }
3666+}
3667+
3668+/* name: .ASSIGNA <value> */
3669+
3670+static void
3671+do_assigna (idx, in)
3672+ int idx;
3673+ sb *in;
3674+{
3675+ sb tmp;
3676+ int val;
3677+ sb_new (&tmp);
3678+
3679+ process_assigns (idx, in, &tmp);
3680+ idx = exp_get_abs (_(".ASSIGNA needs constant expression argument.\n"), 0, &tmp, &val);
3681+
3682+ if (!label.len)
3683+ {
3684+ ERROR ((stderr, _(".ASSIGNA without label.\n")));
3685+ }
3686+ else
3687+ {
3688+ hash_entry *ptr = hash_create (&vars, &label);
3689+ free_old_entry (ptr);
3690+ ptr->type = hash_integer;
3691+ ptr->value.i = val;
3692+ }
3693+ sb_kill (&tmp);
3694+}
3695+
3696+/* name: .ASSIGNC <string> */
3697+
3698+static void
3699+do_assignc (idx, in)
3700+ int idx;
3701+ sb *in;
3702+{
3703+ sb acc;
3704+ sb_new (&acc);
3705+ idx = getstring (idx, in, &acc);
3706+
3707+ if (!label.len)
3708+ {
3709+ ERROR ((stderr, _(".ASSIGNS without label.\n")));
3710+ }
3711+ else
3712+ {
3713+ hash_entry *ptr = hash_create (&vars, &label);
3714+ free_old_entry (ptr);
3715+ ptr->type = hash_string;
3716+ sb_new (&ptr->value.s);
3717+ sb_add_sb (&ptr->value.s, &acc);
3718+ }
3719+ sb_kill (&acc);
3720+}
3721+
3722+/* name: .REG (reg) */
3723+
3724+static void
3725+do_reg (idx, in)
3726+ int idx;
3727+ sb *in;
3728+{
3729+ /* Remove reg stuff from inside parens. */
3730+ sb what;
3731+ if (!mri)
3732+ idx = skip_openp (idx, in);
3733+ else
3734+ idx = sb_skip_white (idx, in);
3735+ sb_new (&what);
3736+ while (idx < in->len
3737+ && (mri
3738+ ? ! eol (idx, in)
3739+ : in->ptr[idx] != ')'))
3740+ {
3741+ sb_add_char (&what, in->ptr[idx]);
3742+ idx++;
3743+ }
3744+ hash_add_to_string_table (&assign_hash_table, &label, &what, 1);
3745+ sb_kill (&what);
3746+}
3747+
3748+static int
3749+condass_lookup_name (inbuf, idx, out, warn)
3750+ sb *inbuf;
3751+ int idx;
3752+ sb *out;
3753+ int warn;
3754+{
3755+ hash_entry *ptr;
3756+ sb condass_acc;
3757+ sb_new (&condass_acc);
3758+
3759+ while (idx < inbuf->len
3760+ && ISNEXTCHAR (inbuf->ptr[idx]))
3761+ {
3762+ sb_add_char (&condass_acc, inbuf->ptr[idx++]);
3763+ }
3764+
3765+ if (inbuf->ptr[idx] == '\'')
3766+ idx++;
3767+ ptr = hash_lookup (&vars, &condass_acc);
3768+
3769+ if (!ptr)
3770+ {
3771+ if (warn)
3772+ {
3773+ WARNING ((stderr, _("Can't find preprocessor variable %s.\n"), sb_name (&condass_acc)));
3774+ }
3775+ else
3776+ {
3777+ sb_add_string (out, "0");
3778+ }
3779+ }
3780+ else
3781+ {
3782+ if (ptr->type == hash_integer)
3783+ {
3784+ char buffer[30];
3785+ sprintf (buffer, "%d", ptr->value.i);
3786+ sb_add_string (out, buffer);
3787+ }
3788+ else
3789+ {
3790+ sb_add_sb (out, &ptr->value.s);
3791+ }
3792+ }
3793+ sb_kill (&condass_acc);
3794+ return idx;
3795+}
3796+
3797+#define EQ 1
3798+#define NE 2
3799+#define GE 3
3800+#define LT 4
3801+#define LE 5
3802+#define GT 6
3803+#define NEVER 7
3804+
3805+static int
3806+whatcond (idx, in, val)
3807+ int idx;
3808+ sb *in;
3809+ int *val;
3810+{
3811+ int cond;
3812+
3813+ idx = sb_skip_white (idx, in);
3814+ cond = NEVER;
3815+ if (idx + 1 < in->len)
3816+ {
3817+ char *p;
3818+ char a, b;
3819+
3820+ p = in->ptr + idx;
3821+ a = TOUPPER (p[0]);
3822+ b = TOUPPER (p[1]);
3823+ if (a == 'E' && b == 'Q')
3824+ cond = EQ;
3825+ else if (a == 'N' && b == 'E')
3826+ cond = NE;
3827+ else if (a == 'L' && b == 'T')
3828+ cond = LT;
3829+ else if (a == 'L' && b == 'E')
3830+ cond = LE;
3831+ else if (a == 'G' && b == 'T')
3832+ cond = GT;
3833+ else if (a == 'G' && b == 'E')
3834+ cond = GE;
3835+ }
3836+ if (cond == NEVER)
3837+ {
3838+ ERROR ((stderr, _("Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n")));
3839+ cond = NEVER;
3840+ }
3841+ idx = sb_skip_white (idx + 2, in);
3842+ *val = cond;
3843+ return idx;
3844+}
3845+
3846+static int
3847+istrue (idx, in)
3848+ int idx;
3849+ sb *in;
3850+{
3851+ int res;
3852+ sb acc_a;
3853+ sb cond;
3854+ sb acc_b;
3855+ sb_new (&acc_a);
3856+ sb_new (&cond);
3857+ sb_new (&acc_b);
3858+ idx = sb_skip_white (idx, in);
3859+
3860+ if (in->ptr[idx] == '"')
3861+ {
3862+ int cond;
3863+ int same;
3864+ /* This is a string comparision. */
3865+ idx = getstring (idx, in, &acc_a);
3866+ idx = whatcond (idx, in, &cond);
3867+ idx = getstring (idx, in, &acc_b);
3868+ same = acc_a.len == acc_b.len
3869+ && (strncmp (acc_a.ptr, acc_b.ptr, acc_a.len) == 0);
3870+
3871+ if (cond != EQ && cond != NE)
3872+ {
3873+ ERROR ((stderr, _("Comparison operator for strings must be EQ or NE\n")));
3874+ res = 0;
3875+ }
3876+ else
3877+ res = (cond != EQ) ^ same;
3878+ }
3879+ else
3880+ /* This is a numeric expression. */
3881+ {
3882+ int vala;
3883+ int valb;
3884+ int cond;
3885+ idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"), idx, in, &vala);
3886+ idx = whatcond (idx, in, &cond);
3887+ idx = sb_skip_white (idx, in);
3888+ if (in->ptr[idx] == '"')
3889+ {
3890+ WARNING ((stderr, _("String compared against expression.\n")));
3891+ res = 0;
3892+ }
3893+ else
3894+ {
3895+ idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"), idx, in, &valb);
3896+ switch (cond)
3897+ {
3898+ default:
3899+ res = 42;
3900+ break;
3901+ case EQ:
3902+ res = vala == valb;
3903+ break;
3904+ case NE:
3905+ res = vala != valb;
3906+ break;
3907+ case LT:
3908+ res = vala < valb;
3909+ break;
3910+ case LE:
3911+ res = vala <= valb;
3912+ break;
3913+ case GT:
3914+ res = vala > valb;
3915+ break;
3916+ case GE:
3917+ res = vala >= valb;
3918+ break;
3919+ case NEVER:
3920+ res = 0;
3921+ break;
3922+ }
3923+ }
3924+ }
3925+
3926+ sb_kill (&acc_a);
3927+ sb_kill (&cond);
3928+ sb_kill (&acc_b);
3929+ return res;
3930+}
3931+
3932+/* .AIF */
3933+
3934+static void
3935+do_aif (idx, in)
3936+ int idx;
3937+ sb *in;
3938+{
3939+ if (ifi >= IFNESTING)
3940+ {
3941+ FATAL ((stderr, _("AIF nesting unreasonable.\n")));
3942+ }
3943+ ifi++;
3944+ ifstack[ifi].on = ifstack[ifi - 1].on ? istrue (idx, in) : 0;
3945+ ifstack[ifi].hadelse = 0;
3946+}
3947+
3948+/* .AELSE */
3949+
3950+static void
3951+do_aelse ()
3952+{
3953+ ifstack[ifi].on = ifstack[ifi - 1].on ? !ifstack[ifi].on : 0;
3954+ if (ifstack[ifi].hadelse)
3955+ {
3956+ ERROR ((stderr, _("Multiple AELSEs in AIF.\n")));
3957+ }
3958+ ifstack[ifi].hadelse = 1;
3959+}
3960+
3961+/* .AENDI */
3962+
3963+static void
3964+do_aendi ()
3965+{
3966+ if (ifi != 0)
3967+ {
3968+ ifi--;
3969+ }
3970+ else
3971+ {
3972+ ERROR ((stderr, _("AENDI without AIF.\n")));
3973+ }
3974+}
3975+
3976+static int
3977+condass_on ()
3978+{
3979+ return ifstack[ifi].on;
3980+}
3981+
3982+/* MRI IFEQ, IFNE, IFLT, IFLE, IFGE, IFGT. */
3983+
3984+static void
3985+do_if (idx, in, cond)
3986+ int idx;
3987+ sb *in;
3988+ int cond;
3989+{
3990+ int val;
3991+ int res;
3992+
3993+ if (ifi >= IFNESTING)
3994+ {
3995+ FATAL ((stderr, _("IF nesting unreasonable.\n")));
3996+ }
3997+
3998+ idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"),
3999+ idx, in, &val);
4000+ switch (cond)
4001+ {
4002+ default:
4003+ case EQ: res = val == 0; break;
4004+ case NE: res = val != 0; break;
4005+ case LT: res = val < 0; break;
4006+ case LE: res = val <= 0; break;
4007+ case GE: res = val >= 0; break;
4008+ case GT: res = val > 0; break;
4009+ }
4010+
4011+ ifi++;
4012+ ifstack[ifi].on = ifstack[ifi - 1].on ? res : 0;
4013+ ifstack[ifi].hadelse = 0;
4014+}
4015+
4016+/* Get a string for the MRI IFC or IFNC pseudo-ops. */
4017+
4018+static int
4019+get_mri_string (idx, in, val, terminator)
4020+ int idx;
4021+ sb *in;
4022+ sb *val;
4023+ int terminator;
4024+{
4025+ idx = sb_skip_white (idx, in);
4026+
4027+ if (idx < in->len
4028+ && in->ptr[idx] == '\'')
4029+ {
4030+ sb_add_char (val, '\'');
4031+ for (++idx; idx < in->len; ++idx)
4032+ {
4033+ sb_add_char (val, in->ptr[idx]);
4034+ if (in->ptr[idx] == '\'')
4035+ {
4036+ ++idx;
4037+ if (idx >= in->len
4038+ || in->ptr[idx] != '\'')
4039+ break;
4040+ }
4041+ }
4042+ idx = sb_skip_white (idx, in);
4043+ }
4044+ else
4045+ {
4046+ int i;
4047+
4048+ while (idx < in->len
4049+ && in->ptr[idx] != terminator)
4050+ {
4051+ sb_add_char (val, in->ptr[idx]);
4052+ ++idx;
4053+ }
4054+ i = val->len - 1;
4055+ while (i >= 0 && ISWHITE (val->ptr[i]))
4056+ --i;
4057+ val->len = i + 1;
4058+ }
4059+
4060+ return idx;
4061+}
4062+
4063+/* MRI IFC, IFNC */
4064+
4065+static void
4066+do_ifc (idx, in, ifnc)
4067+ int idx;
4068+ sb *in;
4069+ int ifnc;
4070+{
4071+ sb first;
4072+ sb second;
4073+ int res;
4074+
4075+ if (ifi >= IFNESTING)
4076+ {
4077+ FATAL ((stderr, _("IF nesting unreasonable.\n")));
4078+ }
4079+
4080+ sb_new (&first);
4081+ sb_new (&second);
4082+
4083+ idx = get_mri_string (idx, in, &first, ',');
4084+
4085+ if (idx >= in->len || in->ptr[idx] != ',')
4086+ {
4087+ ERROR ((stderr, _("Bad format for IF or IFNC.\n")));
4088+ return;
4089+ }
4090+
4091+ idx = get_mri_string (idx + 1, in, &second, ';');
4092+
4093+ res = (first.len == second.len
4094+ && strncmp (first.ptr, second.ptr, first.len) == 0);
4095+ res ^= ifnc;
4096+
4097+ ifi++;
4098+ ifstack[ifi].on = ifstack[ifi - 1].on ? res : 0;
4099+ ifstack[ifi].hadelse = 0;
4100+}
4101+
4102+/* .ENDR */
4103+
4104+static void
4105+do_aendr ()
4106+{
4107+ if (!mri)
4108+ ERROR ((stderr, _("AENDR without a AREPEAT.\n")));
4109+ else
4110+ ERROR ((stderr, _("ENDR without a REPT.\n")));
4111+}
4112+
4113+/* .AWHILE */
4114+
4115+static void
4116+do_awhile (idx, in)
4117+ int idx;
4118+ sb *in;
4119+{
4120+ int line = linecount ();
4121+ sb exp;
4122+ sb sub;
4123+ int doit;
4124+
4125+ sb_new (&sub);
4126+ sb_new (&exp);
4127+
4128+ process_assigns (idx, in, &exp);
4129+ doit = istrue (0, &exp);
4130+
4131+ if (! buffer_and_nest ("AWHILE", "AENDW", &sub, get_line))
4132+ FATAL ((stderr, _("AWHILE without a AENDW at %d.\n"), line - 1));
4133+
4134+ /* Turn
4135+ .AWHILE exp
4136+ foo
4137+ .AENDW
4138+ into
4139+ foo
4140+ .AWHILE exp
4141+ foo
4142+ .ENDW
4143+ */
4144+
4145+ if (doit)
4146+ {
4147+ int index = include_next_index ();
4148+
4149+ sb copy;
4150+ sb_new (&copy);
4151+ sb_add_sb (&copy, &sub);
4152+ sb_add_sb (&copy, in);
4153+ sb_add_string (&copy, "\n");
4154+ sb_add_sb (&copy, &sub);
4155+ sb_add_string (&copy, "\t.AENDW\n");
4156+ /* Push another WHILE. */
4157+ include_buf (&exp, &copy, include_while, index);
4158+ sb_kill (&copy);
4159+ }
4160+ sb_kill (&exp);
4161+ sb_kill (&sub);
4162+}
4163+
4164+/* .AENDW */
4165+
4166+static void
4167+do_aendw ()
4168+{
4169+ ERROR ((stderr, _("AENDW without a AENDW.\n")));
4170+}
4171+
4172+/* .EXITM
4173+
4174+ Pop things off the include stack until the type and index changes. */
4175+
4176+static void
4177+do_exitm ()
4178+{
4179+ include_type type = sp->type;
4180+ if (type == include_repeat
4181+ || type == include_while
4182+ || type == include_macro)
4183+ {
4184+ int index = sp->index;
4185+ include_pop ();
4186+ while (sp->index == index
4187+ && sp->type == type)
4188+ {
4189+ include_pop ();
4190+ }
4191+ }
4192+}
4193+
4194+/* .AREPEAT */
4195+
4196+static void
4197+do_arepeat (idx, in)
4198+ int idx;
4199+ sb *in;
4200+{
4201+ int line = linecount ();
4202+ sb exp; /* Buffer with expression in it. */
4203+ sb copy; /* Expanded repeat block. */
4204+ sb sub; /* Contents of AREPEAT. */
4205+ int rc;
4206+ int ret;
4207+ char buffer[30];
4208+
4209+ sb_new (&exp);
4210+ sb_new (&copy);
4211+ sb_new (&sub);
4212+ process_assigns (idx, in, &exp);
4213+ idx = exp_get_abs (_("AREPEAT must have absolute operand.\n"), 0, &exp, &rc);
4214+ if (!mri)
4215+ ret = buffer_and_nest ("AREPEAT", "AENDR", &sub, get_line);
4216+ else
4217+ ret = buffer_and_nest ("REPT", "ENDR", &sub, get_line);
4218+ if (! ret)
4219+ FATAL ((stderr, _("AREPEAT without a AENDR at %d.\n"), line - 1));
4220+ if (rc > 0)
4221+ {
4222+ /* Push back the text following the repeat, and another repeat block
4223+ so
4224+ .AREPEAT 20
4225+ foo
4226+ .AENDR
4227+ gets turned into
4228+ foo
4229+ .AREPEAT 19
4230+ foo
4231+ .AENDR
4232+ */
4233+ int index = include_next_index ();
4234+ sb_add_sb (&copy, &sub);
4235+ if (rc > 1)
4236+ {
4237+ if (!mri)
4238+ sprintf (buffer, "\t.AREPEAT %d\n", rc - 1);
4239+ else
4240+ sprintf (buffer, "\tREPT %d\n", rc - 1);
4241+ sb_add_string (&copy, buffer);
4242+ sb_add_sb (&copy, &sub);
4243+ if (!mri)
4244+ sb_add_string (&copy, " .AENDR\n");
4245+ else
4246+ sb_add_string (&copy, " ENDR\n");
4247+ }
4248+
4249+ include_buf (&exp, &copy, include_repeat, index);
4250+ }
4251+ sb_kill (&exp);
4252+ sb_kill (&sub);
4253+ sb_kill (&copy);
4254+}
4255+
4256+/* .ENDM */
4257+
4258+static void
4259+do_endm ()
4260+{
4261+ ERROR ((stderr, _(".ENDM without a matching .MACRO.\n")));
4262+}
4263+
4264+/* MRI IRP pseudo-op. */
4265+
4266+static void
4267+do_irp (idx, in, irpc)
4268+ int idx;
4269+ sb *in;
4270+ int irpc;
4271+{
4272+ const char *err;
4273+ sb out;
4274+
4275+ sb_new (&out);
4276+
4277+ err = expand_irp (irpc, idx, in, &out, get_line, comment_char);
4278+ if (err != NULL)
4279+ ERROR ((stderr, "%s\n", err));
4280+
4281+ fprintf (outfile, "%s", sb_terminate (&out));
4282+
4283+ sb_kill (&out);
4284+}
4285+
4286+/* Macro processing. */
4287+
4288+/* Parse off LOCAL n1, n2,... Invent a label name for it. */
4289+
4290+static void
4291+do_local (idx, line)
4292+ int idx ATTRIBUTE_UNUSED;
4293+ sb *line ATTRIBUTE_UNUSED;
4294+{
4295+ ERROR ((stderr, _("LOCAL outside of MACRO")));
4296+}
4297+
4298+static void
4299+do_macro (idx, in)
4300+ int idx;
4301+ sb *in;
4302+{
4303+ const char *err;
4304+ int line = linecount ();
4305+
4306+ err = define_macro (idx, in, &label, get_line, (const char **) NULL);
4307+ if (err != NULL)
4308+ ERROR ((stderr, _("macro at line %d: %s\n"), line - 1, err));
4309+}
4310+
4311+static int
4312+macro_op (idx, in)
4313+ int idx;
4314+ sb *in;
4315+{
4316+ const char *err;
4317+ sb out;
4318+ sb name;
4319+
4320+ if (! macro_defined)
4321+ return 0;
4322+
4323+ sb_terminate (in);
4324+ if (! check_macro (in->ptr + idx, &out, comment_char, &err, NULL))
4325+ return 0;
4326+
4327+ if (err != NULL)
4328+ ERROR ((stderr, "%s\n", err));
4329+
4330+ sb_new (&name);
4331+ sb_add_string (&name, _("macro expansion"));
4332+
4333+ include_buf (&name, &out, include_macro, include_next_index ());
4334+
4335+ sb_kill (&name);
4336+ sb_kill (&out);
4337+
4338+ return 1;
4339+}
4340+
4341+/* String handling. */
4342+
4343+static int
4344+getstring (idx, in, acc)
4345+ int idx;
4346+ sb *in;
4347+ sb *acc;
4348+{
4349+ idx = sb_skip_white (idx, in);
4350+
4351+ while (idx < in->len
4352+ && (in->ptr[idx] == '"'
4353+ || in->ptr[idx] == '<'
4354+ || (in->ptr[idx] == '\'' && alternate)))
4355+ {
4356+ if (in->ptr[idx] == '<')
4357+ {
4358+ if (alternate || mri)
4359+ {
4360+ int nest = 0;
4361+ idx++;
4362+ while ((in->ptr[idx] != '>' || nest)
4363+ && idx < in->len)
4364+ {
4365+ if (in->ptr[idx] == '!')
4366+ {
4367+ idx++;
4368+ sb_add_char (acc, in->ptr[idx++]);
4369+ }
4370+ else
4371+ {
4372+ if (in->ptr[idx] == '>')
4373+ nest--;
4374+ if (in->ptr[idx] == '<')
4375+ nest++;
4376+ sb_add_char (acc, in->ptr[idx++]);
4377+ }
4378+ }
4379+ idx++;
4380+ }
4381+ else
4382+ {
4383+ int code;
4384+ idx++;
4385+ idx = exp_get_abs (_("Character code in string must be absolute expression.\n"),
4386+ idx, in, &code);
4387+ sb_add_char (acc, code);
4388+
4389+ if (in->ptr[idx] != '>')
4390+ ERROR ((stderr, _("Missing > for character code.\n")));
4391+ idx++;
4392+ }
4393+ }
4394+ else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
4395+ {
4396+ char tchar = in->ptr[idx];
4397+ idx++;
4398+ while (idx < in->len)
4399+ {
4400+ if (alternate && in->ptr[idx] == '!')
4401+ {
4402+ idx++;
4403+ sb_add_char (acc, in->ptr[idx++]);
4404+ }
4405+ else
4406+ {
4407+ if (in->ptr[idx] == tchar)
4408+ {
4409+ idx++;
4410+ if (idx >= in->len || in->ptr[idx] != tchar)
4411+ break;
4412+ }
4413+ sb_add_char (acc, in->ptr[idx]);
4414+ idx++;
4415+ }
4416+ }
4417+ }
4418+ }
4419+
4420+ return idx;
4421+}
4422+
4423+/* .SDATA[C|Z] <string> */
4424+
4425+static void
4426+do_sdata (idx, in, type)
4427+ int idx;
4428+ sb *in;
4429+ int type;
4430+{
4431+ int nc = 0;
4432+ int pidx = -1;
4433+ sb acc;
4434+ sb_new (&acc);
4435+ fprintf (outfile, ".byte\t");
4436+
4437+ while (!eol (idx, in))
4438+ {
4439+ int i;
4440+ sb_reset (&acc);
4441+ idx = sb_skip_white (idx, in);
4442+ while (!eol (idx, in))
4443+ {
4444+ pidx = idx = get_any_string (idx, in, &acc, 0, 1);
4445+ if (type == 'c')
4446+ {
4447+ if (acc.len > 255)
4448+ {
4449+ ERROR ((stderr, _("string for SDATAC longer than 255 characters (%d).\n"), acc.len));
4450+ }
4451+ fprintf (outfile, "%d", acc.len);
4452+ nc = 1;
4453+ }
4454+
4455+ for (i = 0; i < acc.len; i++)
4456+ {
4457+ if (nc)
4458+ {
4459+ fprintf (outfile, ",");
4460+ }
4461+ fprintf (outfile, "%d", acc.ptr[i]);
4462+ nc = 1;
4463+ }
4464+
4465+ if (type == 'z')
4466+ {
4467+ if (nc)
4468+ fprintf (outfile, ",");
4469+ fprintf (outfile, "0");
4470+ }
4471+ idx = sb_skip_comma (idx, in);
4472+ if (idx == pidx)
4473+ break;
4474+ }
4475+ if (!alternate && in->ptr[idx] != ',' && idx != in->len)
4476+ {
4477+ fprintf (outfile, "\n");
4478+ ERROR ((stderr, _("illegal character in SDATA line (0x%x).\n"),
4479+ in->ptr[idx]));
4480+ break;
4481+ }
4482+ idx++;
4483+ }
4484+ sb_kill (&acc);
4485+ fprintf (outfile, "\n");
4486+}
4487+
4488+/* .SDATAB <count> <string> */
4489+
4490+static void
4491+do_sdatab (idx, in)
4492+ int idx;
4493+ sb *in;
4494+{
4495+ int repeat;
4496+ int i;
4497+ sb acc;
4498+ sb_new (&acc);
4499+
4500+ idx = exp_get_abs (_("Must have absolute SDATAB repeat count.\n"), idx, in, &repeat);
4501+ if (repeat <= 0)
4502+ {
4503+ ERROR ((stderr, _("Must have positive SDATAB repeat count (%d).\n"), repeat));
4504+ repeat = 1;
4505+ }
4506+
4507+ idx = sb_skip_comma (idx, in);
4508+ idx = getstring (idx, in, &acc);
4509+
4510+ for (i = 0; i < repeat; i++)
4511+ {
4512+ if (i)
4513+ fprintf (outfile, "\t");
4514+ fprintf (outfile, ".byte\t");
4515+ sb_print (outfile, &acc);
4516+ fprintf (outfile, "\n");
4517+ }
4518+ sb_kill (&acc);
4519+
4520+}
4521+
4522+static int
4523+new_file (name)
4524+ const char *name;
4525+{
4526+ FILE *newone = fopen (name, "r");
4527+ if (!newone)
4528+ return 0;
4529+
4530+ if (isp == MAX_INCLUDES)
4531+ FATAL ((stderr, _("Unreasonable include depth (%ld).\n"), (long) isp));
4532+
4533+ sp++;
4534+ sp->handle = newone;
4535+
4536+ sb_new (&sp->name);
4537+ sb_add_string (&sp->name, name);
4538+
4539+ sp->linecount = 1;
4540+ sp->pushback_index = 0;
4541+ sp->type = include_file;
4542+ sp->index = 0;
4543+ sb_new (&sp->pushback);
4544+ return 1;
4545+}
4546+
4547+static void
4548+do_include (idx, in)
4549+ int idx;
4550+ sb *in;
4551+{
4552+ sb t;
4553+ sb cat;
4554+ include_path *includes;
4555+
4556+ sb_new (&t);
4557+ sb_new (&cat);
4558+
4559+ if (! mri)
4560+ idx = getstring (idx, in, &t);
4561+ else
4562+ {
4563+ idx = sb_skip_white (idx, in);
4564+ while (idx < in->len && ! ISWHITE (in->ptr[idx]))
4565+ {
4566+ sb_add_char (&t, in->ptr[idx]);
4567+ ++idx;
4568+ }
4569+ }
4570+
4571+ for (includes = paths_head; includes; includes = includes->next)
4572+ {
4573+ sb_reset (&cat);
4574+ sb_add_sb (&cat, &includes->path);
4575+ sb_add_char (&cat, '/');
4576+ sb_add_sb (&cat, &t);
4577+ if (new_file (sb_name (&cat)))
4578+ {
4579+ break;
4580+ }
4581+ }
4582+ if (!includes)
4583+ {
4584+ if (! new_file (sb_name (&t)))
4585+ FATAL ((stderr, _("Can't open include file `%s'.\n"), sb_name (&t)));
4586+ }
4587+ sb_kill (&cat);
4588+ sb_kill (&t);
4589+}
4590+
4591+static void
4592+include_pop ()
4593+{
4594+ if (sp != include_stack)
4595+ {
4596+ if (sp->handle)
4597+ fclose (sp->handle);
4598+ sp--;
4599+ }
4600+}
4601+
4602+/* Get the next character from the include stack. If there's anything
4603+ in the pushback buffer, take that first. If we're at eof, pop from
4604+ the stack and try again. Keep the linecount up to date. */
4605+
4606+static int
4607+get ()
4608+{
4609+ int r;
4610+
4611+ if (sp->pushback.len != sp->pushback_index)
4612+ {
4613+ r = (char) (sp->pushback.ptr[sp->pushback_index++]);
4614+ /* When they've all gone, reset the pointer. */
4615+ if (sp->pushback_index == sp->pushback.len)
4616+ {
4617+ sp->pushback.len = 0;
4618+ sp->pushback_index = 0;
4619+ }
4620+ }
4621+ else if (sp->handle)
4622+ {
4623+ r = getc (sp->handle);
4624+ }
4625+ else
4626+ r = EOF;
4627+
4628+ if (r == EOF && isp)
4629+ {
4630+ include_pop ();
4631+ r = get ();
4632+ while (r == EOF && isp)
4633+ {
4634+ include_pop ();
4635+ r = get ();
4636+ }
4637+ return r;
4638+ }
4639+ if (r == '\n')
4640+ {
4641+ sp->linecount++;
4642+ }
4643+
4644+ return r;
4645+}
4646+
4647+static int
4648+linecount ()
4649+{
4650+ return sp->linecount;
4651+}
4652+
4653+static int
4654+include_next_index ()
4655+{
4656+ static int index;
4657+ if (!unreasonable
4658+ && index > MAX_REASONABLE)
4659+ FATAL ((stderr, _("Unreasonable expansion (-u turns off check).\n")));
4660+ return ++index;
4661+}
4662+
4663+/* Initialize the chartype vector. */
4664+
4665+static void
4666+chartype_init ()
4667+{
4668+ int x;
4669+ for (x = 0; x < 256; x++)
4670+ {
4671+ if (ISALPHA (x) || x == '_' || x == '$')
4672+ chartype[x] |= FIRSTBIT;
4673+
4674+ if (mri && x == '.')
4675+ chartype[x] |= FIRSTBIT;
4676+
4677+ if (ISDIGIT (x) || ISALPHA (x) || x == '_' || x == '$')
4678+ chartype[x] |= NEXTBIT;
4679+
4680+ if (x == ' ' || x == '\t' || x == ',' || x == '"' || x == ';'
4681+ || x == '"' || x == '<' || x == '>' || x == ')' || x == '(')
4682+ chartype[x] |= SEPBIT;
4683+
4684+ if (x == 'b' || x == 'B'
4685+ || x == 'q' || x == 'Q'
4686+ || x == 'h' || x == 'H'
4687+ || x == 'd' || x == 'D')
4688+ chartype [x] |= BASEBIT;
4689+
4690+ if (x == ' ' || x == '\t')
4691+ chartype[x] |= WHITEBIT;
4692+
4693+ if (x == comment_char)
4694+ chartype[x] |= COMMENTBIT;
4695+ }
4696+}
4697+
4698+/* What to do with all the keywords. */
4699+#define PROCESS 0x1000 /* Run substitution over the line. */
4700+#define LAB 0x2000 /* Spit out the label. */
4701+
4702+#define K_EQU (PROCESS|1)
4703+#define K_ASSIGN (PROCESS|2)
4704+#define K_REG (PROCESS|3)
4705+#define K_ORG (PROCESS|4)
4706+#define K_RADIX (PROCESS|5)
4707+#define K_DATA (LAB|PROCESS|6)
4708+#define K_DATAB (LAB|PROCESS|7)
4709+#define K_SDATA (LAB|PROCESS|8)
4710+#define K_SDATAB (LAB|PROCESS|9)
4711+#define K_SDATAC (LAB|PROCESS|10)
4712+#define K_SDATAZ (LAB|PROCESS|11)
4713+#define K_RES (LAB|PROCESS|12)
4714+#define K_SRES (LAB|PROCESS|13)
4715+#define K_SRESC (LAB|PROCESS|14)
4716+#define K_SRESZ (LAB|PROCESS|15)
4717+#define K_EXPORT (LAB|PROCESS|16)
4718+#define K_GLOBAL (LAB|PROCESS|17)
4719+#define K_PRINT (LAB|PROCESS|19)
4720+#define K_FORM (LAB|PROCESS|20)
4721+#define K_HEADING (LAB|PROCESS|21)
4722+#define K_PAGE (LAB|PROCESS|22)
4723+#define K_IMPORT (LAB|PROCESS|23)
4724+#define K_PROGRAM (LAB|PROCESS|24)
4725+#define K_END (PROCESS|25)
4726+#define K_INCLUDE (PROCESS|26)
4727+#define K_IGNORED (PROCESS|27)
4728+#define K_ASSIGNA (PROCESS|28)
4729+#define K_ASSIGNC (29)
4730+#define K_AIF (PROCESS|30)
4731+#define K_AELSE (PROCESS|31)
4732+#define K_AENDI (PROCESS|32)
4733+#define K_AREPEAT (PROCESS|33)
4734+#define K_AENDR (PROCESS|34)
4735+#define K_AWHILE (35)
4736+#define K_AENDW (PROCESS|36)
4737+#define K_EXITM (37)
4738+#define K_MACRO (PROCESS|38)
4739+#define K_ENDM (39)
4740+#define K_ALIGN (PROCESS|LAB|40)
4741+#define K_ALTERNATE (41)
4742+#define K_DB (LAB|PROCESS|42)
4743+#define K_DW (LAB|PROCESS|43)
4744+#define K_DL (LAB|PROCESS|44)
4745+#define K_LOCAL (45)
4746+#define K_IFEQ (PROCESS|46)
4747+#define K_IFNE (PROCESS|47)
4748+#define K_IFLT (PROCESS|48)
4749+#define K_IFLE (PROCESS|49)
4750+#define K_IFGE (PROCESS|50)
4751+#define K_IFGT (PROCESS|51)
4752+#define K_IFC (PROCESS|52)
4753+#define K_IFNC (PROCESS|53)
4754+#define K_IRP (PROCESS|54)
4755+#define K_IRPC (PROCESS|55)
4756+
4757+struct keyword {
4758+ char *name;
4759+ int code;
4760+ int extra;
4761+};
4762+
4763+static struct keyword kinfo[] = {
4764+ { "EQU", K_EQU, 0 },
4765+ { "ALTERNATE", K_ALTERNATE, 0 },
4766+ { "ASSIGN", K_ASSIGN, 0 },
4767+ { "REG", K_REG, 0 },
4768+ { "ORG", K_ORG, 0 },
4769+ { "RADIX", K_RADIX, 0 },
4770+ { "DATA", K_DATA, 0 },
4771+ { "DB", K_DB, 0 },
4772+ { "DW", K_DW, 0 },
4773+ { "DL", K_DL, 0 },
4774+ { "DATAB", K_DATAB, 0 },
4775+ { "SDATA", K_SDATA, 0 },
4776+ { "SDATAB", K_SDATAB, 0 },
4777+ { "SDATAZ", K_SDATAZ, 0 },
4778+ { "SDATAC", K_SDATAC, 0 },
4779+ { "RES", K_RES, 0 },
4780+ { "SRES", K_SRES, 0 },
4781+ { "SRESC", K_SRESC, 0 },
4782+ { "SRESZ", K_SRESZ, 0 },
4783+ { "EXPORT", K_EXPORT, 0 },
4784+ { "GLOBAL", K_GLOBAL, 0 },
4785+ { "PRINT", K_PRINT, 0 },
4786+ { "FORM", K_FORM, 0 },
4787+ { "HEADING", K_HEADING, 0 },
4788+ { "PAGE", K_PAGE, 0 },
4789+ { "PROGRAM", K_IGNORED, 0 },
4790+ { "END", K_END, 0 },
4791+ { "INCLUDE", K_INCLUDE, 0 },
4792+ { "ASSIGNA", K_ASSIGNA, 0 },
4793+ { "ASSIGNC", K_ASSIGNC, 0 },
4794+ { "AIF", K_AIF, 0 },
4795+ { "AELSE", K_AELSE, 0 },
4796+ { "AENDI", K_AENDI, 0 },
4797+ { "AREPEAT", K_AREPEAT, 0 },
4798+ { "AENDR", K_AENDR, 0 },
4799+ { "EXITM", K_EXITM, 0 },
4800+ { "MACRO", K_MACRO, 0 },
4801+ { "ENDM", K_ENDM, 0 },
4802+ { "AWHILE", K_AWHILE, 0 },
4803+ { "ALIGN", K_ALIGN, 0 },
4804+ { "AENDW", K_AENDW, 0 },
4805+ { "ALTERNATE", K_ALTERNATE, 0 },
4806+ { "LOCAL", K_LOCAL, 0 },
4807+ { NULL, 0, 0 }
4808+};
4809+
4810+/* Although the conditional operators are handled by gas, we need to
4811+ handle them here as well, in case they are used in a recursive
4812+ macro to end the recursion. */
4813+
4814+static struct keyword mrikinfo[] = {
4815+ { "IFEQ", K_IFEQ, 0 },
4816+ { "IFNE", K_IFNE, 0 },
4817+ { "IFLT", K_IFLT, 0 },
4818+ { "IFLE", K_IFLE, 0 },
4819+ { "IFGE", K_IFGE, 0 },
4820+ { "IFGT", K_IFGT, 0 },
4821+ { "IFC", K_IFC, 0 },
4822+ { "IFNC", K_IFNC, 0 },
4823+ { "ELSEC", K_AELSE, 0 },
4824+ { "ENDC", K_AENDI, 0 },
4825+ { "MEXIT", K_EXITM, 0 },
4826+ { "REPT", K_AREPEAT, 0 },
4827+ { "IRP", K_IRP, 0 },
4828+ { "IRPC", K_IRPC, 0 },
4829+ { "ENDR", K_AENDR, 0 },
4830+ { NULL, 0, 0 }
4831+};
4832+
4833+/* Look for a pseudo op on the line. If one's there then call
4834+ its handler. */
4835+
4836+static int
4837+process_pseudo_op (idx, line, acc)
4838+ int idx;
4839+ sb *line;
4840+ sb *acc;
4841+{
4842+ int oidx = idx;
4843+
4844+ if (line->ptr[idx] == '.' || alternate || mri)
4845+ {
4846+ /* Scan forward and find pseudo name. */
4847+ char *in;
4848+ hash_entry *ptr;
4849+
4850+ char *s;
4851+ char *e;
4852+ if (line->ptr[idx] == '.')
4853+ idx++;
4854+ in = line->ptr + idx;
4855+ s = in;
4856+ e = s;
4857+ sb_reset (acc);
4858+
4859+ while (idx < line->len && *e && ISFIRSTCHAR (*e))
4860+ {
4861+ sb_add_char (acc, *e);
4862+ e++;
4863+ idx++;
4864+ }
4865+
4866+ ptr = hash_lookup (&keyword_hash_table, acc);
4867+
4868+ if (!ptr)
4869+ {
4870+#if 0
4871+ /* This one causes lots of pain when trying to preprocess
4872+ ordinary code. */
4873+ WARNING ((stderr, _("Unrecognised pseudo op `%s'.\n"),
4874+ sb_name (acc)));
4875+#endif
4876+ return 0;
4877+ }
4878+ if (ptr->value.i & LAB)
4879+ {
4880+ /* Output the label. */
4881+ if (label.len)
4882+ {
4883+ fprintf (outfile, "%s:\t", sb_name (&label));
4884+ }
4885+ else
4886+ fprintf (outfile, "\t");
4887+ }
4888+
4889+ if (mri && ptr->value.i == K_END)
4890+ {
4891+ sb t;
4892+
4893+ sb_new (&t);
4894+ sb_add_buffer (&t, line->ptr + oidx, idx - oidx);
4895+ fprintf (outfile, "\t%s", sb_name (&t));
4896+ sb_kill (&t);
4897+ }
4898+
4899+ if (ptr->value.i & PROCESS)
4900+ {
4901+ /* Polish the rest of the line before handling the pseudo op. */
4902+#if 0
4903+ strip_comments (line);
4904+#endif
4905+ sb_reset (acc);
4906+ process_assigns (idx, line, acc);
4907+ sb_reset (line);
4908+ change_base (0, acc, line);
4909+ idx = 0;
4910+ }
4911+ if (!condass_on ())
4912+ {
4913+ switch (ptr->value.i)
4914+ {
4915+ case K_AIF:
4916+ do_aif (idx, line);
4917+ break;
4918+ case K_AELSE:
4919+ do_aelse ();
4920+ break;
4921+ case K_AENDI:
4922+ do_aendi ();
4923+ break;
4924+ }
4925+ return 1;
4926+ }
4927+ else
4928+ {
4929+ switch (ptr->value.i)
4930+ {
4931+ case K_ALTERNATE:
4932+ alternate = 1;
4933+ macro_init (1, mri, 0, exp_get_abs);
4934+ return 1;
4935+ case K_AELSE:
4936+ do_aelse ();
4937+ return 1;
4938+ case K_AENDI:
4939+ do_aendi ();
4940+ return 1;
4941+ case K_ORG:
4942+ ERROR ((stderr, _("ORG command not allowed.\n")));
4943+ break;
4944+ case K_RADIX:
4945+ do_radix (line);
4946+ return 1;
4947+ case K_DB:
4948+ do_data (idx, line, 1);
4949+ return 1;
4950+ case K_DW:
4951+ do_data (idx, line, 2);
4952+ return 1;
4953+ case K_DL:
4954+ do_data (idx, line, 4);
4955+ return 1;
4956+ case K_DATA:
4957+ do_data (idx, line, 0);
4958+ return 1;
4959+ case K_DATAB:
4960+ do_datab (idx, line);
4961+ return 1;
4962+ case K_SDATA:
4963+ do_sdata (idx, line, 0);
4964+ return 1;
4965+ case K_SDATAB:
4966+ do_sdatab (idx, line);
4967+ return 1;
4968+ case K_SDATAC:
4969+ do_sdata (idx, line, 'c');
4970+ return 1;
4971+ case K_SDATAZ:
4972+ do_sdata (idx, line, 'z');
4973+ return 1;
4974+ case K_ASSIGN:
4975+ do_assign (0, 0, line);
4976+ return 1;
4977+ case K_AIF:
4978+ do_aif (idx, line);
4979+ return 1;
4980+ case K_AREPEAT:
4981+ do_arepeat (idx, line);
4982+ return 1;
4983+ case K_AENDW:
4984+ do_aendw ();
4985+ return 1;
4986+ case K_AWHILE:
4987+ do_awhile (idx, line);
4988+ return 1;
4989+ case K_AENDR:
4990+ do_aendr ();
4991+ return 1;
4992+ case K_EQU:
4993+ do_assign (1, idx, line);
4994+ return 1;
4995+ case K_ALIGN:
4996+ do_align (idx, line);
4997+ return 1;
4998+ case K_RES:
4999+ do_res (idx, line, 0);
5000+ return 1;
5001+ case K_SRES:
5002+ do_res (idx, line, 's');
5003+ return 1;
5004+ case K_INCLUDE:
5005+ do_include (idx, line);
5006+ return 1;
5007+ case K_LOCAL:
5008+ do_local (idx, line);
5009+ return 1;
5010+ case K_MACRO:
5011+ do_macro (idx, line);
5012+ return 1;
5013+ case K_ENDM:
5014+ do_endm ();
5015+ return 1;
5016+ case K_SRESC:
5017+ do_res (idx, line, 'c');
5018+ return 1;
5019+ case K_PRINT:
5020+ do_print (idx, line);
5021+ return 1;
5022+ case K_FORM:
5023+ do_form (idx, line);
5024+ return 1;
5025+ case K_HEADING:
5026+ do_heading (idx, line);
5027+ return 1;
5028+ case K_PAGE:
5029+ do_page ();
5030+ return 1;
5031+ case K_GLOBAL:
5032+ case K_EXPORT:
5033+ do_export (line);
5034+ return 1;
5035+ case K_IMPORT:
5036+ return 1;
5037+ case K_SRESZ:
5038+ do_res (idx, line, 'z');
5039+ return 1;
5040+ case K_IGNORED:
5041+ return 1;
5042+ case K_END:
5043+ do_end (line);
5044+ return 1;
5045+ case K_ASSIGNA:
5046+ do_assigna (idx, line);
5047+ return 1;
5048+ case K_ASSIGNC:
5049+ do_assignc (idx, line);
5050+ return 1;
5051+ case K_EXITM:
5052+ do_exitm ();
5053+ return 1;
5054+ case K_REG:
5055+ do_reg (idx, line);
5056+ return 1;
5057+ case K_IFEQ:
5058+ do_if (idx, line, EQ);
5059+ return 1;
5060+ case K_IFNE:
5061+ do_if (idx, line, NE);
5062+ return 1;
5063+ case K_IFLT:
5064+ do_if (idx, line, LT);
5065+ return 1;
5066+ case K_IFLE:
5067+ do_if (idx, line, LE);
5068+ return 1;
5069+ case K_IFGE:
5070+ do_if (idx, line, GE);
5071+ return 1;
5072+ case K_IFGT:
5073+ do_if (idx, line, GT);
5074+ return 1;
5075+ case K_IFC:
5076+ do_ifc (idx, line, 0);
5077+ return 1;
5078+ case K_IFNC:
5079+ do_ifc (idx, line, 1);
5080+ return 1;
5081+ case K_IRP:
5082+ do_irp (idx, line, 0);
5083+ return 1;
5084+ case K_IRPC:
5085+ do_irp (idx, line, 1);
5086+ return 1;
5087+ }
5088+ }
5089+ }
5090+ return 0;
5091+}
5092+
5093+/* Add a keyword to the hash table. */
5094+
5095+static void
5096+add_keyword (name, code)
5097+ const char *name;
5098+ int code;
5099+{
5100+ sb label;
5101+ int j;
5102+
5103+ sb_new (&label);
5104+ sb_add_string (&label, name);
5105+
5106+ hash_add_to_int_table (&keyword_hash_table, &label, code);
5107+
5108+ sb_reset (&label);
5109+ for (j = 0; name[j]; j++)
5110+ sb_add_char (&label, name[j] - 'A' + 'a');
5111+ hash_add_to_int_table (&keyword_hash_table, &label, code);
5112+
5113+ sb_kill (&label);
5114+}
5115+
5116+/* Build the keyword hash table - put each keyword in the table twice,
5117+ once upper and once lower case. */
5118+
5119+static void
5120+process_init ()
5121+{
5122+ int i;
5123+
5124+ for (i = 0; kinfo[i].name; i++)
5125+ add_keyword (kinfo[i].name, kinfo[i].code);
5126+
5127+ if (mri)
5128+ {
5129+ for (i = 0; mrikinfo[i].name; i++)
5130+ add_keyword (mrikinfo[i].name, mrikinfo[i].code);
5131+ }
5132+}
5133+
5134+static void
5135+do_define (string)
5136+ const char *string;
5137+{
5138+ sb label;
5139+ int res = 1;
5140+ hash_entry *ptr;
5141+ sb_new (&label);
5142+
5143+ while (*string)
5144+ {
5145+ if (*string == '=')
5146+ {
5147+ sb value;
5148+ sb_new (&value);
5149+ string++;
5150+ while (*string)
5151+ {
5152+ sb_add_char (&value, *string);
5153+ string++;
5154+ }
5155+ exp_get_abs (_("Invalid expression on command line.\n"),
5156+ 0, &value, &res);
5157+ sb_kill (&value);
5158+ break;
5159+ }
5160+ sb_add_char (&label, *string);
5161+
5162+ string++;
5163+ }
5164+
5165+ ptr = hash_create (&vars, &label);
5166+ free_old_entry (ptr);
5167+ ptr->type = hash_integer;
5168+ ptr->value.i = res;
5169+ sb_kill (&label);
5170+}
5171+
5172+char *program_name;
5173+
5174+/* The list of long options. */
5175+static struct option long_options[] =
5176+{
5177+ { "alternate", no_argument, 0, 'a' },
5178+ { "include", required_argument, 0, 'I' },
5179+ { "commentchar", required_argument, 0, 'c' },
5180+ { "copysource", no_argument, 0, 's' },
5181+ { "debug", no_argument, 0, 'd' },
5182+ { "help", no_argument, 0, 'h' },
5183+ { "mri", no_argument, 0, 'M' },
5184+ { "output", required_argument, 0, 'o' },
5185+ { "print", no_argument, 0, 'p' },
5186+ { "unreasonable", no_argument, 0, 'u' },
5187+ { "version", no_argument, 0, 'v' },
5188+ { "define", required_argument, 0, 'd' },
5189+ { NULL, no_argument, 0, 0 }
5190+};
5191+
5192+/* Show a usage message and exit. */
5193+static void
5194+show_usage (file, status)
5195+ FILE *file;
5196+ int status;
5197+{
5198+ fprintf (file, _("\
5199+Usage: %s \n\
5200+ [-a] [--alternate] enter alternate macro mode\n\
5201+ [-c char] [--commentchar char] change the comment character from !\n\
5202+ [-d] [--debug] print some debugging info\n\
5203+ [-h] [--help] print this message\n\
5204+ [-M] [--mri] enter MRI compatibility mode\n\
5205+ [-o out] [--output out] set the output file\n\
5206+ [-p] [--print] print line numbers\n"), program_name);
5207+ fprintf (file, _("\
5208+ [-s] [--copysource] copy source through as comments \n\
5209+ [-u] [--unreasonable] allow unreasonable nesting\n\
5210+ [-v] [--version] print the program version\n\
5211+ [-Dname=value] create preprocessor variable called name, with value\n\
5212+ [-Ipath] add to include path list\n\
5213+ [in-file]\n"));
5214+ if (status == 0)
5215+ printf (_("Report bugs to %s\n"), REPORT_BUGS_TO);
5216+ exit (status);
5217+}
5218+
5219+/* Display a help message and exit. */
5220+
5221+static void
5222+show_help ()
5223+{
5224+ printf (_("%s: Gnu Assembler Macro Preprocessor\n"), program_name);
5225+ show_usage (stdout, 0);
5226+}
5227+
5228+int main PARAMS ((int, char **));
5229+
5230+int
5231+main (argc, argv)
5232+ int argc;
5233+ char **argv;
5234+{
5235+ int opt;
5236+ char *out_name = 0;
5237+ sp = include_stack;
5238+
5239+ ifstack[0].on = 1;
5240+ ifi = 0;
5241+
5242+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
5243+ setlocale (LC_MESSAGES, "");
5244+#endif
5245+#if defined (HAVE_SETLOCALE)
5246+ setlocale (LC_CTYPE, "");
5247+#endif
5248+ bindtextdomain (PACKAGE, LOCALEDIR);
5249+ textdomain (PACKAGE);
5250+
5251+ program_name = argv[0];
5252+ xmalloc_set_program_name (program_name);
5253+
5254+ hash_new_table (101, &keyword_hash_table);
5255+ hash_new_table (101, &assign_hash_table);
5256+ hash_new_table (101, &vars);
5257+
5258+ sb_new (&label);
5259+
5260+ while ((opt = getopt_long (argc, argv, "I:sdhavc:upo:D:M", long_options,
5261+ (int *) NULL))
5262+ != EOF)
5263+ {
5264+ switch (opt)
5265+ {
5266+ case 'o':
5267+ out_name = optarg;
5268+ break;
5269+ case 'u':
5270+ unreasonable = 1;
5271+ break;
5272+ case 'I':
5273+ {
5274+ include_path *p = (include_path *) xmalloc (sizeof (include_path));
5275+ p->next = NULL;
5276+ sb_new (&p->path);
5277+ sb_add_string (&p->path, optarg);
5278+ if (paths_tail)
5279+ paths_tail->next = p;
5280+ else
5281+ paths_head = p;
5282+ paths_tail = p;
5283+ }
5284+ break;
5285+ case 'p':
5286+ print_line_number = 1;
5287+ break;
5288+ case 'c':
5289+ comment_char = optarg[0];
5290+ break;
5291+ case 'a':
5292+ alternate = 1;
5293+ break;
5294+ case 's':
5295+ copysource = 1;
5296+ break;
5297+ case 'd':
5298+ stats = 1;
5299+ break;
5300+ case 'D':
5301+ do_define (optarg);
5302+ break;
5303+ case 'M':
5304+ mri = 1;
5305+ comment_char = ';';
5306+ break;
5307+ case 'h':
5308+ show_help ();
5309+ /* NOTREACHED */
5310+ case 'v':
5311+ /* This output is intended to follow the GNU standards document. */
5312+ printf (_("GNU assembler pre-processor %s\n"), program_version);
5313+ printf (_("Copyright 1996 Free Software Foundation, Inc.\n"));
5314+ printf (_("\
5315+This program is free software; you may redistribute it under the terms of\n\
5316+the GNU General Public License. This program has absolutely no warranty.\n"));
5317+ exit (0);
5318+ /* NOTREACHED */
5319+ case 0:
5320+ break;
5321+ default:
5322+ show_usage (stderr, 1);
5323+ /* NOTREACHED */
5324+ }
5325+ }
5326+
5327+ process_init ();
5328+
5329+ macro_init (alternate, mri, 0, exp_get_abs);
5330+
5331+ if (out_name)
5332+ {
5333+ outfile = fopen (out_name, "w");
5334+ if (!outfile)
5335+ {
5336+ fprintf (stderr, _("%s: Can't open output file `%s'.\n"),
5337+ program_name, out_name);
5338+ exit (1);
5339+ }
5340+ }
5341+ else
5342+ {
5343+ outfile = stdout;
5344+ }
5345+
5346+ chartype_init ();
5347+ if (!outfile)
5348+ outfile = stdout;
5349+
5350+ /* Process all the input files. */
5351+
5352+ while (optind < argc)
5353+ {
5354+ if (new_file (argv[optind]))
5355+ {
5356+ process_file ();
5357+ }
5358+ else
5359+ {
5360+ fprintf (stderr, _("%s: Can't open input file `%s'.\n"),
5361+ program_name, argv[optind]);
5362+ exit (1);
5363+ }
5364+ optind++;
5365+ }
5366+
5367+ quit ();
5368+ return 0;
5369+}
5370+
5371+/* This function is used because an abort in some of the other files
5372+ may be compiled into as_abort because they include as.h. */
5373+
5374+void
5375+as_abort (file, line, fn)
5376+ const char *file, *fn;
5377+ int line;
5378+{
5379+ fprintf (stderr, _("Internal error, aborting at %s line %d"), file, line);
5380+ if (fn)
5381+ fprintf (stderr, " in %s", fn);
5382+ fprintf (stderr, _("\nPlease report this bug.\n"));
5383+ exit (1);
5384+}
5385diff -Nur binutils-2.13.90.0.18.orig/gas/macro.c binutils-2.13.90.0.18/gas/macro.c
5386--- binutils-2.13.90.0.18.orig/gas/macro.c Sun Feb 2 03:21:18 2003
5387+++ binutils-2.13.90.0.18/gas/macro.c Sun Feb 2 15:19:38 2003
5388@@ -75,8 +75,8 @@
5389 static int sub_actual
5390 PARAMS ((int, sb *, sb *, struct hash_control *, int, sb *, int));
5391 static const char *macro_expand_body
5392- PARAMS ((sb *, sb *, formal_entry *, struct hash_control *, int));
5393-static const char *macro_expand PARAMS ((int, sb *, macro_entry *, sb *));
5394+ PARAMS ((sb *, sb *, formal_entry *, struct hash_control *, int,int ));
5395+static const char *macro_expand PARAMS ((int, sb *, macro_entry *, sb *, int));
5396
5397 #define ISWHITE(x) ((x) == ' ' || (x) == '\t')
5398
5399@@ -653,11 +653,12 @@
5400 /* Expand the body of a macro. */
5401
5402 static const char *
5403-macro_expand_body (in, out, formals, formal_hash, locals)
5404+macro_expand_body (in, out, formals, formal_hash, comment_char, locals)
5405 sb *in;
5406 sb *out;
5407 formal_entry *formals;
5408 struct hash_control *formal_hash;
5409+ int comment_char;
5410 int locals;
5411 {
5412 sb t;
5413@@ -688,7 +689,14 @@
5414 else if (in->ptr[src] == '\\')
5415 {
5416 src++;
5417- if (in->ptr[src] == '(')
5418+ if (in->ptr[src] == comment_char && comment_char != '\0')
5419+ {
5420+ /* This is a comment, just drop the rest of the line. */
5421+ while (src < in->len
5422+ && in->ptr[src] != '\n')
5423+ src++;
5424+ }
5425+ else if (in->ptr[src] == '(')
5426 {
5427 /* Sub in till the next ')' literally. */
5428 src++;
5429@@ -771,7 +779,7 @@
5430 formal_entry *f;
5431
5432 src = sb_skip_white (src + 5, in);
5433- while (in->ptr[src] != '\n')
5434+ while (in->ptr[src] != '\n' && in->ptr[src] != comment_char)
5435 {
5436 static int loccnt;
5437 char buf[20];
5438@@ -798,6 +806,17 @@
5439 }
5440 }
5441 }
5442+ else if (comment_char != '\0'
5443+ && in->ptr[src] == comment_char
5444+ && src + 1 < in->len
5445+ && in->ptr[src + 1] == comment_char
5446+ && !inquote)
5447+ {
5448+ /* Two comment chars in a row cause the rest of the line to
5449+ be dropped. */
5450+ while (src < in->len && in->ptr[src] != '\n')
5451+ src++;
5452+ }
5453 else if (in->ptr[src] == '"'
5454 || (macro_mri && in->ptr[src] == '\''))
5455 {
5456@@ -880,11 +899,12 @@
5457 body. */
5458
5459 static const char *
5460-macro_expand (idx, in, m, out)
5461+macro_expand (idx, in, m, out, comment_char)
5462 int idx;
5463 sb *in;
5464 macro_entry *m;
5465 sb *out;
5466+ int comment_char;
5467 {
5468 sb t;
5469 formal_entry *ptr;
5470@@ -934,7 +954,7 @@
5471
5472 /* Peel off the actuals and store them away in the hash tables' actuals. */
5473 idx = sb_skip_white (idx, in);
5474- while (idx < in->len)
5475+ while (idx < in->len && in->ptr[idx] != comment_char)
5476 {
5477 int scan;
5478
5479@@ -1036,7 +1056,7 @@
5480 sb_add_string (&ptr->actual, buffer);
5481 }
5482
5483- err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash, 1);
5484+ err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash, comment_char, 1);
5485 if (err != NULL)
5486 return err;
5487
5488@@ -1072,9 +1092,10 @@
5489 *EXPAND. Return 1 if a macro is found, 0 otherwise. */
5490
5491 int
5492-check_macro (line, expand, error, info)
5493+check_macro (line, expand, comment_char, error, info)
5494 const char *line;
5495 sb *expand;
5496+ int comment_char;
5497 const char **error;
5498 macro_entry **info;
5499 {
5500@@ -1112,7 +1133,7 @@
5501 sb_add_char (&line_sb, *s++);
5502
5503 sb_new (expand);
5504- *error = macro_expand (0, &line_sb, macro, expand);
5505+ *error = macro_expand (0, &line_sb, macro, expand, comment_char);
5506
5507 sb_kill (&line_sb);
5508
5509@@ -1137,12 +1158,13 @@
5510 success, or an error message otherwise. */
5511
5512 const char *
5513-expand_irp (irpc, idx, in, out, get_line)
5514+expand_irp (irpc, idx, in, out, get_line, comment_char)
5515 int irpc;
5516 int idx;
5517 sb *in;
5518 sb *out;
5519 int (*get_line) PARAMS ((sb *));
5520+ int comment_char;
5521 {
5522 const char *mn;
5523 sb sub;
5524@@ -1180,10 +1202,10 @@
5525 sb_reset (out);
5526
5527 idx = sb_skip_comma (idx, in);
5528- if (idx >= in->len)
5529+ if (idx >= in->len || in->ptr[idx] == comment_char)
5530 {
5531 /* Expand once with a null string. */
5532- err = macro_expand_body (&sub, out, &f, h, 0);
5533+ err = macro_expand_body (&sub, out, &f, h, comment_char, 0);
5534 if (err != NULL)
5535 return err;
5536 }
5537@@ -1191,7 +1213,7 @@
5538 {
5539 if (irpc && in->ptr[idx] == '"')
5540 ++idx;
5541- while (idx < in->len)
5542+ while (idx < in->len && in->ptr[idx] != comment_char)
5543 {
5544 if (!irpc)
5545 idx = get_any_string (idx, in, &f.actual, 1, 0);
5546@@ -1202,7 +1224,7 @@
5547 int nxt;
5548
5549 nxt = sb_skip_white (idx + 1, in);
5550- if (nxt >= in->len)
5551+ if (nxt >= in->len || in->ptr[nxt] == comment_char)
5552 {
5553 idx = nxt;
5554 break;
5555@@ -1212,7 +1234,7 @@
5556 sb_add_char (&f.actual, in->ptr[idx]);
5557 ++idx;
5558 }
5559- err = macro_expand_body (&sub, out, &f, h, 0);
5560+ err = macro_expand_body (&sub, out, &f, h, comment_char, 0);
5561 if (err != NULL)
5562 return err;
5563 if (!irpc)
5564diff -Nur binutils-2.13.90.0.18.orig/gas/macro.h binutils-2.13.90.0.18/gas/macro.h
5565--- binutils-2.13.90.0.18.orig/gas/macro.h Sun Feb 2 03:21:18 2003
5566+++ binutils-2.13.90.0.18/gas/macro.h Sun Feb 2 15:23:24 2003
5567@@ -79,10 +79,10 @@
5568 extern const char *define_macro
5569 PARAMS ((int, sb *, sb *, int (*) PARAMS ((sb *)), const char **));
5570 extern int check_macro
5571- PARAMS ((const char *, sb *, const char **, macro_entry **));
5572+ PARAMS ((const char *, sb *, int, const char **, macro_entry **));
5573 extern void delete_macro
5574 PARAMS ((const char *));
5575 extern const char *expand_irp
5576- PARAMS ((int, int, sb *, sb *, int (*) PARAMS ((sb *))));
5577+ PARAMS ((int, int, sb *, sb *, int (*) PARAMS ((sb *)), int));
5578
5579 #endif
5580diff -Nur binutils-2.13.90.0.18.orig/gas/read.c binutils-2.13.90.0.18/gas/read.c
5581--- binutils-2.13.90.0.18.orig/gas/read.c Sun Feb 2 03:21:18 2003
5582+++ binutils-2.13.90.0.18/gas/read.c Sun Feb 2 15:26:06 2003
5583@@ -862,7 +862,7 @@
5584 const char *err;
5585 macro_entry *macro;
5586
5587- if (check_macro (s, &out, &err, &macro))
5588+ if (check_macro (s, &out, '\0', &err, &macro))
5589 {
5590 if (err != NULL)
5591 as_bad ("%s", err);
5592@@ -1855,7 +1855,7 @@
5593
5594 sb_new (&out);
5595
5596- err = expand_irp (irpc, 0, &s, &out, get_line_sb);
5597+ err = expand_irp (irpc, 0, &s, &out, get_line_sb, '\0');
5598 if (err != NULL)
5599 as_bad_where (file, line, "%s", err);
5600
This page took 0.647517 seconds and 4 git commands to generate.