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