]> git.pld-linux.org Git - packages/binutils.git/blob - binutils-gasp.patch
- unified gasp.texi source name
[packages/binutils.git] / binutils-gasp.patch
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 @@
4         symbols.c \
5         write.c
6  
7 -CFILES = $(GAS_CFILES) itbl-ops.c cgen.c
8 +CFILES = $(GAS_CFILES) gasp.c itbl-ops.c cgen.c
9  
10  HFILES = \
11         as.h \
12 @@ -455,7 +455,8 @@
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  
22 @@ -517,6 +518,10 @@
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
27 +gasp_new_LDADD = ../bfd/libbfd.la ../libiberty/libiberty.a $(LIBINTL)
28 +gasp_new_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a $(LIBINTL_DEP)
29 +
30  EXPECT = expect
31  RUNTEST = runtest
32  RUNTESTFLAGS=
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 \
38 +       as.h sb.h macro.h $(INCDIR)/xregex.h $(INCDIR)/xregex2.h
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
43 --- binutils-2.23.51.0.9/gas/doc/Makefile.am.orig       2013-02-02 00:24:54.000000000 +0100
44 +++ binutils-2.23.51.0.9/gas/doc/Makefile.am    2013-02-04 21:03:53.135274636 +0100
45 @@ -32,7 +32,7 @@ POD2MAN = pod2man --center="GNU Developm
46  
47  man_MANS = as.1
48  
49 -info_TEXINFOS = as.texi
50 +info_TEXINFOS = as.texi gasp.texi
51  as_TEXINFOS = asconfig.texi $(CPU_DOCS)
52  
53  AM_MAKEINFOFLAGS = -I "$(srcdir)" -I "$(top_srcdir)/../libiberty" \
54 --- binutils-2.16.91.0.2.org/gas/doc/gasp.texi  1970-01-01 00:00:00.000000000 +0000
55 +++ binutils-2.16.91.0.2/gas/doc/gasp.texi      2005-07-21 18:31:04.000000000 +0000
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
1513 --- binutils-2.24.51.0.4/gas/gasp.c.orig        1970-01-01 01:00:00.000000000 +0100
1514 +++ binutils-2.24.51.0.4/gas/gasp.c     2014-10-12 11:32:34.014384388 +0200
1515 @@ -0,0 +1,4015 @@
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"
1564 +#include "bfdver.h"
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 +
1579 +#include "as.h"
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 +const 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 (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 (void);
1741 +static void hash_new_table (int, hash_table *);
1742 +static int hash (sb *);
1743 +static hash_entry *hash_create (hash_table *, sb *);
1744 +static void hash_add_to_string_table (hash_table *, sb *, sb *, int);
1745 +static void hash_add_to_int_table (hash_table *, sb *, int);
1746 +static hash_entry *hash_lookup (hash_table *, sb *);
1747 +static void checkconst (int, exp_t *);
1748 +static int is_flonum (size_t, sb *);
1749 +static int chew_flonum (size_t, sb *, sb *);
1750 +static int sb_strtol (size_t, sb *, int, int *);
1751 +static int level_0 (size_t, sb *, exp_t *);
1752 +static int level_1 (size_t, sb *, exp_t *);
1753 +static int level_2 (size_t, sb *, exp_t *);
1754 +static int level_3 (size_t, sb *, exp_t *);
1755 +static int level_4 (size_t, sb *, exp_t *);
1756 +static int level_5 (size_t, sb *, exp_t *);
1757 +static int exp_parse (size_t, sb *, exp_t *);
1758 +static void exp_string (exp_t *, sb *);
1759 +static size_t exp_get_abs (const char *, size_t, sb *, offsetT *);
1760 +#if 0
1761 +static void strip_comments (sb *);
1762 +#endif
1763 +static void unget (int);
1764 +static void include_buf (sb *, sb *, include_type, int);
1765 +static void include_print_where_line (FILE *);
1766 +static void include_print_line (FILE *);
1767 +static size_t get_line (sb *);
1768 +static int grab_label (sb *, sb *);
1769 +static void change_base (size_t, sb *, sb *);
1770 +static void do_end (sb *);
1771 +static void do_assign (int, size_t, sb *);
1772 +static void do_radix (sb *);
1773 +static int get_opsize (size_t, sb *, int *);
1774 +static int eol (size_t, sb *);
1775 +static void do_data (size_t, sb *, int);
1776 +static void do_datab (size_t, sb *);
1777 +static void gasp_do_align (size_t, sb *);
1778 +static void do_res (size_t, sb *, int);
1779 +static void do_export (sb *);
1780 +static void do_print (size_t, sb *);
1781 +static void do_heading (size_t, sb *);
1782 +static void do_page (void);
1783 +static void do_form (size_t, sb *);
1784 +static int get_any_string (size_t, sb *, sb *, int, int);
1785 +static int skip_openp (size_t, sb *);
1786 +static int skip_closep (size_t, sb *);
1787 +static int dolen (size_t, sb *, sb *);
1788 +static int doinstr (size_t, sb *, sb *);
1789 +static int dosubstr (size_t, sb *, sb *);
1790 +static void process_assigns (size_t, sb *, sb *);
1791 +static int get_and_process (size_t, sb *, sb *);
1792 +static void process_file (void);
1793 +static void free_old_entry (hash_entry *);
1794 +static void do_assigna (size_t, sb *);
1795 +static void do_assignc (size_t, sb *);
1796 +static void do_reg (size_t, sb *);
1797 +static int condass_lookup_name (sb *, size_t, sb *, int);
1798 +static int whatcond (size_t, sb *, int *);
1799 +static int istrue (size_t, sb *);
1800 +static void do_aif (size_t, sb *);
1801 +static void do_aelse (void);
1802 +static void do_aendi (void);
1803 +static int condass_on (void);
1804 +static void do_if (size_t, sb *, int);
1805 +static int get_mri_string (size_t, sb *, sb *, int);
1806 +static void do_ifc (size_t, sb *, int);
1807 +static void do_aendr (void);
1808 +static void do_awhile (size_t, sb *);
1809 +static void do_aendw (void);
1810 +static void do_exitm (void);
1811 +static void do_arepeat (size_t, sb *);
1812 +static void do_endm (void);
1813 +static void do_irp (size_t, sb *, int);
1814 +static void do_local (size_t, sb *);
1815 +static void do_macro (size_t, sb *);
1816 +static int macro_op (size_t, sb *);
1817 +static int getstring (size_t, sb *, sb *);
1818 +static void do_sdata (size_t, sb *, int);
1819 +static void do_sdatab (size_t, sb *);
1820 +static int new_file (const char *);
1821 +static void do_include (size_t, sb *);
1822 +static void include_pop (void);
1823 +static int get (void);
1824 +static int linecount (void);
1825 +static int include_next_index (void);
1826 +static void chartype_init (void);
1827 +static int process_pseudo_op (size_t, sb *, sb *);
1828 +static void add_keyword (const char *, int);
1829 +static void process_init (void);
1830 +static void do_define (const char *);
1831 +static void show_usage (FILE *, int);
1832 +static void show_help (void);
1833 +
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
1850 +sb_print (FILE *outfileP, sb *ptr)
1851 +{
1852 +  size_t i;
1853 +  int nc = 0;
1854 +
1855 +  for (i = 0; i < ptr->len; i++)
1856 +    {
1857 +      if (nc)
1858 +       {
1859 +         fprintf (outfileP, ",");
1860 +       }
1861 +      fprintf (outfileP, "%d", ptr->ptr[i]);
1862 +      nc = 1;
1863 +    }
1864 +}
1865 +
1866 +/* print the sb at ptr to the output file */
1867 +
1868 +static void
1869 +sb_print_at (FILE *outfileP, size_t idx, sb *ptr)
1870 +{
1871 +  size_t i;
1872 +  for (i = idx; i < ptr->len; i++)
1873 +    putc (ptr->ptr[i], outfileP);
1874 +}
1875 +
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 +
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;
1943 +  size_t i;
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)
2083 +     size_t idx;
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)
2113 +     size_t idx;
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)
2139 +     size_t idx;
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)
2172 +     size_t idx;
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)
2219 +     size_t idx;
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)
2262 +     size_t idx;
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)
2297 +     size_t idx;
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)
2336 +     size_t idx;
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)
2363 +     size_t idx;
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)
2399 +     size_t idx;
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 +
2450 +static size_t
2451 +exp_get_abs (emsg, idx, in, val)
2452 +     const char *emsg;
2453 +     size_t idx;
2454 +     sb *in;
2455 +     offsetT *val;
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
2517 +include_buf (name, ptr, type, indx)
2518 +     sb *name;
2519 +     sb *ptr;
2520 +     include_type type;
2521 +     int indx;
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;
2532 +  sp->index = indx;
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 +
2578 +static size_t
2579 +get_line (in)
2580 +     sb *in;
2581 +{
2582 +  int online = 0;
2583 +  int more = 1, ch = 0;
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 +    {
2594 +      ch = get ();
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);
2636 +             ch = '\n'; break;
2637 +           }
2638 +       }
2639 +      else
2640 +       {
2641 +         sb_add_char (in, ch);
2642 +       }
2643 +      online++;
2644 +    }
2645 +
2646 +  return more ? ch : 0;
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 +{
2656 +  size_t i = 0;
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)
2679 +     size_t idx;
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;
2802 +     size_t idx;
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 +{
2822 +  size_t idx = sb_skip_white (0, ptr);
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)
2850 +     size_t idx;
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)
2887 +     size_t idx;
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)
2904 +     size_t idx;
2905 +     sb *in;
2906 +     int size;
2907 +{
2908 +  int opsize = 4;
2909 +  const 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 +    {
2942 +      size_t i;
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)
2976 +     size_t idx;
2977 +     sb *in;
2978 +{
2979 +  int opsize;
2980 +  offsetT repeat;
2981 +  offsetT fill;
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 +
2989 +  fprintf (outfile, ".fill\t%ld,%d,%ld\n", (long)repeat, opsize, (long)fill);
2990 +}
2991 +
2992 +/* .align <size>  */
2993 +
2994 +static void
2995 +gasp_do_align (idx, in)
2996 +     size_t idx;
2997 +     sb *in;
2998 +{
2999 +  int have_fill; offsetT al, fill;
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 +
3013 +  fprintf (outfile, ".align    %ld", (long)al);
3014 +  if (have_fill)
3015 +    fprintf (outfile, ",%ld", (long)fill);
3016 +  fprintf (outfile, "\n");
3017 +}
3018 +
3019 +/* .res[.b|.w|.l] <size>  */
3020 +
3021 +static void
3022 +do_res (idx, in, type)
3023 +     size_t idx;
3024 +     sb *in;
3025 +     int type;
3026 +{
3027 +  int size = 4;
3028 +  offsetT count = 0;
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 +
3041 +      fprintf (outfile, ".space        %ld\n", (long)(count * size));
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)
3058 +     size_t idx;
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)
3082 +     size_t idx;
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)
3104 +     size_t idx;
3105 +     sb *in;
3106 +{
3107 +  offsetT lines = 60;
3108 +  offsetT columns = 132;
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 +    }
3128 +  fprintf (outfile, ".psize %ld,%ld\n", (long)lines, (long)columns);
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)
3142 +     size_t idx;
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 +       {
3162 +         offsetT val;
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);
3170 +         sprintf (buf, "%ld", (long)val);
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)
3223 +     size_t idx;
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)
3238 +     size_t idx;
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)
3252 +     size_t idx;
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)
3275 +     size_t idx;
3276 +     sb *in;
3277 +     sb *out;
3278 +{
3279 +  sb string;
3280 +  sb search;
3281 +  size_t i;
3282 +  offsetT start;
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)
3320 +     size_t idx;
3321 +     sb *in;
3322 +     sb *out;
3323 +{
3324 +  sb string;
3325 +  offsetT pos;
3326 +  offsetT len;
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)
3361 +     size_t idx;
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;
3418 +         size_t cur = idx + 1;
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)
3448 +     size_t idx;
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.  */
3479 +      size_t l;
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 +               {
3511 +                 size_t lx = l;
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)
3598 +     size_t idx;
3599 +     sb *in;
3600 +{
3601 +  sb tmp;
3602 +  offsetT val;
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)
3626 +     size_t idx;
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)
3652 +     size_t idx;
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;
3677 +     size_t idx;
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)
3733 +     size_t idx;
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)
3774 +     size_t idx;
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 +    {
3788 +      int cond2;
3789 +      int same;
3790 +      /* This is a string comparision.  */
3791 +      idx = getstring (idx, in, &acc_a);
3792 +      idx = whatcond (idx, in, &cond2);
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 +
3797 +      if (cond2 != EQ && cond2 != NE)
3798 +       {
3799 +         ERROR ((stderr, _("Comparison operator for strings must be EQ or NE\n")));
3800 +         res = 0;
3801 +       }
3802 +      else
3803 +       res = (cond2 != EQ) ^ same;
3804 +    }
3805 +  else
3806 +    /* This is a numeric expression.  */
3807 +    {
3808 +      offsetT vala;
3809 +      offsetT valb;
3810 +      int cond2;
3811 +      idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"), idx, in, &vala);
3812 +      idx = whatcond (idx, in, &cond2);
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);
3822 +         switch (cond2)
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)
3862 +     size_t idx;
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)
3912 +     size_t idx;
3913 +     sb *in;
3914 +     int cond;
3915 +{
3916 +  offsetT val;
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)
3946 +     size_t idx;
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)
3993 +     size_t idx;
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)
4043 +     size_t idx;
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 +    {
4073 +      int indx = include_next_index ();
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.  */
4083 +      include_buf (&exp, &copy, include_while, indx);
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 +    {
4110 +      int indx = sp->index;
4111 +      include_pop ();
4112 +      while (sp->index == indx
4113 +            && sp->type == type)
4114 +       {
4115 +         include_pop ();
4116 +       }
4117 +    }
4118 +}
4119 +
4120 +/* .AREPEAT  */
4121 +
4122 +static void
4123 +do_arepeat (idx, in)
4124 +     size_t idx;
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.  */
4131 +  offsetT rc;
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 +      */
4159 +      int indx = include_next_index ();
4160 +      sb_add_sb (&copy, &sub);
4161 +      if (rc > 1)
4162 +       {
4163 +         if (!mri)
4164 +           sprintf (buffer, "\t.AREPEAT        %ld\n", (long)(rc - 1));
4165 +         else
4166 +           sprintf (buffer, "\tREPT    %ld\n", (long)(rc - 1));
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 +
4175 +      include_buf (&exp, &copy, include_repeat, indx);
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)
4194 +     size_t idx;
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)
4218 +     size_t idx ATTRIBUTE_UNUSED;
4219 +     sb *line ATTRIBUTE_UNUSED;
4220 +{
4221 +  ERROR ((stderr, _("LOCAL outside of MACRO")));
4222 +}
4223 +
4224 +static void
4225 +do_macro (idx, in)
4226 +     size_t idx;
4227 +     sb *in;
4228 +{
4229 +  const char *err;
4230 +  int line = linecount ();
4231 +
4232 +  err = define_macro (idx, in, &label, get_line, "[gasp]", line, (const char **) NULL);
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)
4239 +     size_t idx;
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)
4271 +     size_t idx;
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 +           {
4309 +             offsetT code;
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)
4353 +     size_t idx;
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 +    {
4365 +      size_t i;
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)
4418 +     size_t idx;
4419 +     sb *in;
4420 +{
4421 +  offsetT repeat;
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 +    {
4429 +      ERROR ((stderr, _("Must have positive SDATAB repeat count (%ld).\n"), (long)repeat));
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)
4475 +     size_t idx;
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 +{
4582 +  static int indx;
4583 +  if (!unreasonable
4584 +      && indx > MAX_REASONABLE)
4585 +    FATAL ((stderr, _("Unreasonable expansion (-u turns off check).\n")));
4586 +  return ++indx;
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 +  const 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)
4764 +     size_t idx;
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 +             gasp_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 +{
5026 +  sb label2;
5027 +  int j;
5028 +
5029 +  sb_new (&label2);
5030 +  sb_add_string (&label2, name);
5031 +
5032 +  hash_add_to_int_table (&keyword_hash_table, &label2, code);
5033 +
5034 +  sb_reset (&label2);
5035 +  for (j = 0; name[j]; j++)
5036 +    sb_add_char (&label2, name[j] - 'A' + 'a');
5037 +  hash_add_to_int_table (&keyword_hash_table, &label2, code);
5038 +
5039 +  sb_kill (&label2);
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 +{
5064 +  sb label2;
5065 +  offsetT res = 1;
5066 +  hash_entry *ptr;
5067 +  sb_new (&label2);
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 +       }
5086 +      sb_add_char (&label2, *string);
5087 +
5088 +      string++;
5089 +    }
5090 +
5091 +  ptr = hash_create (&vars, &label2);
5092 +  free_old_entry (ptr);
5093 +  ptr->type = hash_integer;
5094 +  ptr->value.i = res;
5095 +  sb_kill (&label2);
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 (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 +}
5311 +
5312 +/* duplicated from as internals */
5313 +
5314 +static void
5315 +identify (const 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 (const 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 +      vsnprintf (buffer, sizeof (buffer), format, args);
5362 +      va_end (args);
5363 +      as_warn_internal ((char *) NULL, 0, buffer);
5364 +    }
5365 +}
5366 +
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 (const 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 +      vsnprintf (buffer, sizeof (buffer), format, args);
5381 +      va_end (args);
5382 +      as_warn_internal (file, line, buffer);
5383 +    }
5384 +}
5385 +
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 (const 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 +
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 +  vsnprintf (buffer, sizeof (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 +
5429 +void
5430 +as_bad_where (const char *file, unsigned int line, const char *format, ...)
5431 +{
5432 +  va_list args;
5433 +  char buffer[2000];
5434 +
5435 +  va_start (args, format);
5436 +  vsnprintf (buffer, sizeof (buffer), format, args);
5437 +  va_end (args);
5438 +
5439 +  as_bad_internal (file, line, buffer);
5440 +}
5441 +
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 +
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 +};
5513 +
5514 +/* just a stub to satisfy unused function in sb.o */
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 +
5528 +/* stubs for macro.c linefile support */
5529 +void s_app_line (int appline) { }
5530 +char *input_line_pointer;
5531 --- binutils-2.23.51.0.1/gas/macro.c.orig       2012-08-07 19:47:23.000000000 +0200
5532 +++ binutils-2.23.51.0.1/gas/macro.c    2012-08-21 20:21:33.256276269 +0200
5533 @@ -770,7 +770,7 @@
5534  
5535  static const char *
5536  macro_expand_body (sb *in, sb *out, formal_entry *formals,
5537 -                  struct hash_control *formal_hash, const macro_entry *macro)
5538 +                  struct hash_control *formal_hash, const macro_entry *macro, int comment_char)
5539  {
5540    sb t;
5541    size_t src = 0;
5542 @@ -802,7 +802,14 @@
5543        else if (in->ptr[src] == '\\')
5544         {
5545           src++;
5546 -         if (src < in->len && in->ptr[src] == '(')
5547 +         if (in->ptr[src] == comment_char && comment_char != '\0')
5548 +           {
5549 +             /* This is a comment, just drop the rest of the line.  */
5550 +             while (src < in->len
5551 +                    && in->ptr[src] != '\n')
5552 +               src++;
5553 +           }
5554 +         else if (src < in->len && in->ptr[src] == '(')
5555             {
5556               /* Sub in till the next ')' literally.  */
5557               src++;
5558 @@ -885,7 +892,7 @@
5559           else
5560             {
5561               src = sb_skip_white (src + 5, in);
5562 -             while (in->ptr[src] != '\n')
5563 +             while (in->ptr[src] != '\n' && in->ptr[src] != comment_char)
5564                 {
5565                   const char *name;
5566                   formal_entry *f = new_formal ();
5567 @@ -921,6 +928,17 @@
5568                 }
5569             }
5570         }
5571 +      else if (comment_char != '\0'
5572 +              && in->ptr[src] == comment_char
5573 +              && src + 1 < in->len
5574 +              && in->ptr[src + 1] == comment_char
5575 +              && !inquote)
5576 +       {
5577 +         /* Two comment chars in a row cause the rest of the line to
5578 +            be dropped.  */
5579 +         while (src < in->len && in->ptr[src] != '\n')
5580 +           src++;
5581 +       }
5582        else if (in->ptr[src] == '"'
5583                || (macro_mri && in->ptr[src] == '\''))
5584         {
5585 @@ -1002,7 +1020,7 @@
5586     body.  */
5587  
5588  static const char *
5589 -macro_expand (size_t idx, sb *in, macro_entry *m, sb *out)
5590 +macro_expand (size_t idx, sb *in, macro_entry *m, sb *out, int comment_char)
5591  {
5592    sb t;
5593    formal_entry *ptr;
5594 @@ -1047,7 +1065,7 @@
5595  
5596    /* Peel off the actuals and store them away in the hash tables' actuals.  */
5597    idx = sb_skip_white (idx, in);
5598 -  while (idx < in->len)
5599 +  while (idx < in->len && in->ptr[idx] != comment_char)
5600      {
5601        size_t scan;
5602  
5603 @@ -1178,7 +1196,7 @@
5604           sb_add_string (&ptr->actual, buffer);
5605         }
5606  
5607 -      err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash, m);
5608 +      err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash, m, comment_char);
5609      }
5610  
5611    /* Discard any unnamed formal arguments.  */
5612 @@ -1211,7 +1229,7 @@
5613     *EXPAND.  Return 1 if a macro is found, 0 otherwise.  */
5614  
5615  int
5616 -check_macro (const char *line, sb *expand,
5617 +check_macro (const char *line, sb *expand, int comment_char,
5618              const char **error, macro_entry **info)
5619  {
5620    const char *s;
5621 @@ -1246,7 +1264,7 @@
5622      sb_add_char (&line_sb, *s++);
5623  
5624    sb_new (expand);
5625 -  *error = macro_expand (0, &line_sb, macro, expand);
5626 +  *error = macro_expand (0, &line_sb, macro, expand, comment_char);
5627  
5628    sb_kill (&line_sb);
5629  
5630 @@ -1289,7 +1307,7 @@
5631     success, or an error message otherwise.  */
5632  
5633  const char *
5634 -expand_irp (int irpc, size_t idx, sb *in, sb *out, size_t (*get_line) (sb *))
5635 +expand_irp (int irpc, size_t idx, sb *in, sb *out, size_t (*get_line) (sb *), int comment_char)
5636  {
5637    sb sub;
5638    formal_entry f;
5639 @@ -1322,10 +1340,10 @@
5640    sb_reset (out);
5641  
5642    idx = sb_skip_comma (idx, in);
5643 -  if (idx >= in->len)
5644 +  if (idx >= in->len || in->ptr[idx] == comment_char)
5645      {
5646        /* Expand once with a null string.  */
5647 -      err = macro_expand_body (&sub, out, &f, h, 0);
5648 +      err = macro_expand_body (&sub, out, &f, h, 0, comment_char);
5649      }
5650    else
5651      {
5652 @@ -1337,7 +1355,7 @@
5653           ++idx;
5654         }
5655  
5656 -      while (idx < in->len)
5657 +      while (idx < in->len && in->ptr[idx] != comment_char)
5658         {
5659           if (!irpc)
5660             idx = get_any_string (idx, in, &f.actual);
5661 @@ -1351,7 +1369,7 @@
5662                     in_quotes = ! in_quotes;
5663           
5664                   nxt = sb_skip_white (idx + 1, in);
5665 -                 if (nxt >= in->len)
5666 +                 if (nxt >= in->len || in->ptr[nxt] == comment_char)
5667                     {
5668                       idx = nxt;
5669                       break;
5670 @@ -1362,7 +1380,7 @@
5671               ++idx;
5672             }
5673  
5674 -         err = macro_expand_body (&sub, out, &f, h, 0);
5675 +         err = macro_expand_body (&sub, out, &f, h, 0, comment_char);
5676           if (err != NULL)
5677             break;
5678           if (!irpc)
5679 --- binutils-2.27/gas/macro.h.orig      2016-12-13 17:20:58.662894688 +0100
5680 +++ binutils-2.27/gas/macro.h   2016-12-13 17:36:44.799550552 +0100
5681 @@ -89,8 +89,8 @@
5682  extern void macro_mri_mode (int);
5683  extern const char *define_macro (size_t, sb *, sb *, size_t (*) (sb *),
5684                                  const char *, unsigned int, const char **);
5685 -extern int check_macro (const char *, sb *, const char **, macro_entry **);
5686 +extern int check_macro (const char *, sb *, int, const char **, macro_entry **);
5687  extern void delete_macro (const char *);
5688 -extern const char *expand_irp (int, size_t, sb *, sb *, size_t (*) (sb *));
5689 +extern const char *expand_irp (int, size_t, sb *, sb *, size_t (*) (sb *), int);
5690  
5691  #endif
5692 --- binutils-2.16.91.0.2.org/gas/read.c 2005-06-22 20:53:34.000000000 +0000
5693 +++ binutils-2.16.91.0.2/gas/read.c     2005-07-21 18:31:04.000000000 +0000
5694 @@ -555,7 +555,7 @@
5695    const char *err;
5696    macro_entry *macro;
5697  
5698 -  if (check_macro (line, &out, &err, &macro))
5699 +  if (check_macro (line, &out, '\0', &err, &macro))
5700      {
5701        if (err != NULL)
5702         as_bad ("%s", err);
5703 @@ -1958,7 +1958,7 @@
5704  
5705    sb_new (&out);
5706  
5707 -  err = expand_irp (irpc, 0, &s, &out, get_non_macro_line_sb);
5708 +  err = expand_irp (irpc, 0, &s, &out, get_non_macro_line_sb, '\0');
5709    if (err != NULL)
5710      as_bad_where (file, line, "%s", err);
5711  
5712 --- binutils-2.14.90.0.7.org/gas/doc/gasp.texi  Mon Mar 11 22:37:38 2002
5713 +++ binutils-2.14.90.0.7/gas/doc/gasp.texi      Mon Mar 11 22:37:52 2002
5714 @@ -14,9 +14,10 @@
5715  
5716  @ifinfo
5717  @format
5718 -START-INFO-DIR-ENTRY
5719 -* gasp: (gasp).                     The GNU Assembler Preprocessor
5720 -END-INFO-DIR-ENTRY
5721 +@dircategory Programming tools:
5722 +@direntry
5723 +* gasp: (gasp).                                The GNU Assembler Preprocessor
5724 +@end direntry
5725  @end format
5726  @end ifinfo
5727  
This page took 1.010728 seconds and 3 git commands to generate.