NASM 0.98.30
authorH. Peter Anvin <hpa@zytor.com>
Tue, 30 Apr 2002 21:09:12 +0000 (21:09 +0000)
committerH. Peter Anvin <hpa@zytor.com>
Tue, 30 Apr 2002 21:09:12 +0000 (21:09 +0000)
75 files changed:
CHANGES [new file with mode: 0644]
COPYING
ChangeLog
Changes [deleted file]
INSTALL [new file with mode: 0644]
License [deleted file]
MODIFIED [deleted file]
Makefile.in
Mkfiles/Makefile.b32
Mkfiles/Makefile.bc2
Mkfiles/Makefile.bor
Mkfiles/Makefile.dj
Mkfiles/Makefile.djo
Mkfiles/Makefile.dl
Mkfiles/Makefile.dos
Mkfiles/Makefile.emx
Mkfiles/Makefile.lcc
Mkfiles/Makefile.os2
Mkfiles/Makefile.sc
Mkfiles/Makefile.scw
Mkfiles/Makefile.unx
Mkfiles/Makefile.vc
Mkfiles/Makefile.wc
Mkfiles/Makefile.wcw
README
Readme [deleted file]
TODO
Wishlist [deleted file]
doc/Changes [deleted file]
doc/License [deleted file]
doc/Readme [deleted file]
doc/Wishlist [deleted file]
insns.dat
insns.pl
install-sh
lcc/Readme [deleted file]
macros.c [deleted file]
macros.pl
makedist.sh
misc/findleak.pl
misc/nasmstab
misc/pmw.bat
misc/simon.jpg [new file with mode: 0644]
nasm-dir [new file with mode: 0755]
nasm-version [new file with mode: 0755]
nasm.1
nasm.c
nasm.h
outaout.c [deleted file]
outas86.c [deleted file]
outbin.c [deleted file]
outcoff.c [deleted file]
outdbg.c [deleted file]
outelf.c [deleted file]
outforms.h [deleted file]
outobj.c [deleted file]
output/outaout.c [new file with mode: 0644]
output/outas86.c [new file with mode: 0644]
output/outbin.c [new file with mode: 0644]
output/outcoff.c [new file with mode: 0644]
output/outdbg.c [new file with mode: 0644]
output/outelf.c [new file with mode: 0644]
output/outieee.c [new file with mode: 0644]
output/outobj.c [new file with mode: 0644]
output/outrdf.c [new file with mode: 0644]
output/outrdf2.c [new file with mode: 0644]
outrdf.c [deleted file]
outrdf2.c [deleted file]
parser.c
rdoff/Makefile.dj [deleted file]
rdoff/Makefile.emx [deleted file]
rdoff/Makefile.sc [deleted file]
rdoff/Makefile.unx [deleted file]
rdoff/test/makelib.sh
zoutieee.c [deleted file]

diff --git a/CHANGES b/CHANGES
new file mode 100644 (file)
index 0000000..a10592c
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,1237 @@
+0.98.30
+-------
+
+* Changed doc files a lot: completely removed old READMExx and
+Wishlist files, incorporating all information in CHANGES and TODO.
+* I waited a long time to rename zoutieee.c to (original) outieee.c
+* moved all output modules to output/ subdirectory.
+* Added 'make strip' target to strip debug info from nasm & ndisasm.
+* Added INSTALL file with installation instructions.
+* Added -v option description to nasm man.
+* Added dist makefile target to produce source distributions.
+
+
+0.98.28
+-------
+
+* Fastcooked this for Debian's Woody release:
+Frank applied the INCBIN bug patch to 0.98.25alt and called
+it 0.98.28 to not confuse poor little apt-get.
+
+
+0.98.26
+-------
+
+* Reorganised files even better from 0.98.25alt
+
+
+0.98.25alt
+----------
+
+* Prettified the source tree. Moved files to more
+reasonable places.
+* Added findleak.pl script to misc/ directory.
+* FIXME: Frank, document this please.
+
+
+0.98.25
+-------
+
+* FIXME: Frank, document this please.
+
+
+0.98.24p1
+---------
+
+* FIXME: Frank, document this please.
+
+
+0.98.24
+-------
+
+* FIXME: Frank, document this please.
+
+
+0.98.23
+-------
+
+* FIXME: Frank, document this please.
+
+
+0.98.22
+-------
+
+* FIXME: Frank, document this please.
+
+
+0.98.21
+-------
+
+* FIXME: Frank, document this please.
+
+
+0.98.20
+-------
+
+* FIXME: Frank, document this please.
+
+
+0.98.19
+-------
+
+* FIXME: Frank, document this please.
+
+
+0.98.18
+-------
+
+* FIXME: Frank, document this please.
+
+
+0.98.17
+-------
+
+* FIXME: Frank, document this please.
+
+
+0.98.16
+-------
+
+* FIXME: Frank, document this please.
+
+
+0.98.14
+-------
+
+* FIXME: Frank, document this please.
+
+
+0.98.12
+-------
+
+* FIXME: Frank, document this please.
+
+
+0.98.09
+-------
+
+* FIXME: Frank, document this please.
+
+
+0.98.08
+-------
+
+* FIXME: Frank, document this please.
+
+
+0.98.09b with John Coffman patches released 28-Oct-2001
+-------------------------------------------------------
+
+Changes from 0.98.07 release to 98.09b as of 28-Oct-2001
+
+* More closely compatible with 0.98 when -O0 is implied
+or specified.  Not strictly identical, since backward 
+branches in range of short offsets are recognized, and signed
+byte values with no explicit size specification will be
+assembled as a single byte.
+
+* More forgiving with the PUSH instruction.  0.98 requires
+a size to be specified always.  0.98.09b will imply the size
+from the current BITS setting (16 or 32).
+
+* Changed definition of the optimization flag:
+
+       -O0     strict two-pass assembly, JMP and Jcc are
+               handled more like 0.98, except that back-
+               ward JMPs are short, if possible.
+
+       -O1     strict two-pass assembly, but forward
+               branches are assembled with code guaranteed
+               to reach; may produce larger code than
+               -O0, but will produce successful assembly
+               more often if branch offset sizes are not
+               specified.
+
+       -O2     multi-pass optimization, minimize branch
+               offsets; also will minimize signed immed-
+               iate bytes, overriding size specification.
+
+       -O3     like -O2, but more passes taken, if needed
+
+
+0.98.07 released 01/28/01
+-------------------------
+
+* fbk - added Stepane Denis' SSE2 instructions to a *working*
+        version of the code - some earlier versions were based on
+        broken code - sorry 'bout that. version "0.98.07"
+
+
+01/28/01
+--------
+
+* fbk - cosmetic modifications to nasm.c, nasm.h,
+        AUTHORS, MODIFIED
+
+
+0.98.06f released 01/18/01
+--------------------------
+
+* fbk - "metalbrain"s jecxz bug fix in insns.dat
+        - alter nasmdoc.src to match - version "0.98.06f"
+
+
+0.98.06e released 01/09/01
+--------------------------
+
+* fbk - removed the "outforms.h" file - it appears to be
+        someone's old backup of "outform.h". version "0.98.06e" 
+
+
+01/09/01
+--------
+
+* fbk - finally added the fix for the "multiple %includes bug",
+        known since 7/27/99 - reported originally (?) and sent to
+        us by Austin Lunnen - he reports that John Fine had a fix
+        within the day. Here it is...
+
+* Nelson Rush resigns from the group. Big thanks to Nelson for
+  his leadership and enthusiasm in getting these changes
+  incorporated into Nasm!
+
+* fbk - [list +], [list -] directives - ineptly implemented, should
+        be re-written or removed, perhaps.
+
+* Brian Raiter / fbk - "elfso bug" fix - applied to aoutb format
+                       as well - testing might be desirable...
+
+
+08/07/00
+--------
+
+* James Seter - -postfix, -prefix command line switches.
+* Yuri Zaporogets - rdoff utility changes.
+
+
+0.98p1
+------
+
+* GAS-like palign (Panos Minos)
+* FIXME: Frank, fill this in with details
+
+
+0.98bf (bug-fixed, aka brain-fuck)
+----------------------------------
+
+* FIXME: Frank, fill this in
+
+
+0.98.03 with John Coffman's changes released 27-Jul-2000
+--------------------------------------------------------
+
+* Added signed byte optimizations for the 0x81/0x83 class
+of instructions: ADC, ADD, AND, CMP, OR, SBB, SUB, XOR:
+when used as 'ADD reg16,imm' or 'ADD reg32,imm.'  Also
+optimization of signed byte form of 'PUSH imm' and 'IMUL
+reg,imm'/'IMUL reg,reg,imm.'  No size specification is needed.
+
+* Added multi-pass JMP and Jcc offset optimization.  Offsets
+on forward references will preferentially use the short form,
+without the need to code a specific size (short or near) for
+the branch.  Added instructions for 'Jcc label' to use the
+form 'Jnotcc $+3/JMP label', in cases where a short offset
+is out of bounds.  If compiling for a 386 or higher CPU, then
+the 386 form of Jcc will be used instead.
+
+This feature is controlled by a new command-line switch: "O",
+(upper case letter O).  "-O0" reverts the assembler to no
+extra optimization passes, "-O1" allows up to 5 extra passes,
+and "-O2"(default), allows up to 10 extra optimization passes.
+
+* Added a new directive:  'cpu XXX', where XXX is any of: 
+8086, 186, 286, 386, 486, 586, pentium, 686, PPro, P2, P3 or
+Katmai.  All are case insensitive.  All instructions will
+be selected only if they apply to the selected cpu or lower.
+Corrected a couple of bugs in cpu-dependence in 'insns.dat'.
+
+* Added to 'standard.mac', the "use16" and "use32" forms of
+the "bits 16/32" directive. This is nothing new, just conforms
+to a lot of other assemblers. (minor)
+
+* Changed label allocation from 320/32 (10000 labels @ 200K+) 
+to 32/37 (1000 labels); makes running under DOS much easier.
+Since additional label space is allocated dynamically, this
+should have no effect on large programs with lots of labels.
+The 37 is a prime, believed to be better for hashing. (minor)
+
+* Integrated patchfile 0.98-0.98.01.  I call this version
+0.98.03, for historical reasons:  0.98.02 was trashed.
+
+--John Coffman <johninsd@san.rr.com>               27-Jul-2000
+
+
+Kendall Bennett's SciTech MGL changes
+-------------------------------------
+Note that you must define "TASM_COMPAT" at compile-time
+to get the Tasm Ideal Mode compatibility.
+
+All changes can be compiled in and out using the TASM_COMPAT macros,
+and when compiled without TASM_COMPAT defined we get the exact same
+binary as the unmodified 0.98 sources.
+
+standard.mac, macros.c:
+ . Added macros to ignore TASM directives before first include
+
+nasm.h:
+ . Added extern declaration for tasm_compatible_mode
+
+nasm.c:
+ . Added global variable tasm_compatible_mode
+ . Added command line switch for TASM compatible mode (-t)
+ . Changed version command line to reflect when compiled with TASM additions
+ . Added response file processing to allow all arguments on a single
+   line (response file is @resp rather than -@resp for NASM format).
+
+labels.c:
+ . Changes islocal() macro to support TASM style @@local labels.
+ . Added islocalchar() macro to support TASM style @@local labels.
+
+parser.c:
+ . Added support for TASM style memory references (ie: mov [DWORD eax],10
+   rather than the NASM style mov DWORD [eax],10).
+
+preproc.c:
+ . Added new directives, %arg, %local, %stacksize to directives table
+ . Added support for TASM style directives without a leading % symbol.
+
+Integrated a block of changes from Andrew Zabolotny <bit@eltech.ru>:
+
+* A new keyword %xdefine and its case-insensitive counterpart %ixdefine.
+    They work almost the same way as %define and %idefine but expand
+    the definition immediately, not on the invocation. Something like a cross
+    between %define and %assign. The "x" suffix stands for "eXpand", so
+    "xdefine" can be deciphered as "expand-and-define". Thus you can do
+    things like this:
+
+       %assign ofs     0
+       
+       %macro  arg     1
+               %xdefine %1 dword [esp+ofs]
+               %assign ofs ofs+4
+       %endmacro
+
+* Changed the place where the expansion of %$name macros are expanded.
+    Now they are converted into ..@ctxnum.name form when detokenizing, so
+    there are no quirks as before when using %$name arguments to macros,
+    in macros etc. For example:
+
+       %macro  abc     1
+               %define %1 hello
+       %endm
+
+       abc     %$here
+       %$here
+
+    Now last line will be expanded into "hello" as expected. This also allows
+    for lots of goodies, a good example are extended "proc" macros included
+    in this archive.
+
+* Added a check for "cstk" in smacro_defined() before calling get_ctx() -
+    this allows for things like:
+
+       %ifdef %$abc
+       %endif
+
+    to work without warnings even in no context.
+
+* Added a check for "cstk" in %if*ctx and %elif*ctx directives -
+    this allows to use %ifctx without excessive warnings. If there is
+    no active context, %ifctx goes through "false" branch.
+
+* Removed "user error: " prefix with %error directive: it just clobbers the
+    output and has absolutely no functionality. Besides, this allows to write
+    macros that does not differ from built-in functions in any way.
+
+* Added expansion of string that is output by %error directive. Now you
+    can do things like:
+
+       %define hello(x) Hello, x!
+
+       %define %$name andy
+       %error "hello(%$name)"
+
+    Same happened with %include directive.
+
+* Now all directives that expect an identifier will try to expand and
+    concatenate everything without whitespaces in between before usage.
+    For example, with "unfixed" nasm the commands
+
+       %define %$abc hello
+       %define __%$abc goodbye
+       __%$abc
+
+    would produce "incorrect" output: last line will expand to
+
+       hello goodbyehello
+
+    Not quite what you expected, eh? :-) The answer is that preprocessor
+    treats the %define construct as if it would be
+
+       %define __ %$abc goodbye
+
+    (note the white space between __ and %$abc). After my "fix" it
+    will "correctly" expand into
+
+       goodbye
+
+    as expected. Note that I use quotes around words "correct", "incorrect"
+    etc because this is rather a feature not a bug; however current behaviour
+    is more logical (and allows more advanced macro usage :-).
+
+    Same change was applied to:
+       %push,%macro,%imacro,%define,%idefine,%xdefine,%ixdefine,
+       %assign,%iassign,%undef
+
+* A new directive [WARNING {+|-}warning-id] have been added. It works only
+    if the assembly phase is enabled (i.e. it doesn't work with nasm -e).
+
+* A new warning type: macro-selfref. By default this warning is disabled;
+    when enabled NASM warns when a macro self-references itself; for example
+    the following source:
+
+       [WARNING macro-selfref]
+
+       %macro          push    1-*
+               %rep    %0
+                       push    %1
+                       %rotate 1
+               %endrep
+       %endmacro
+
+                       push    eax,ebx,ecx
+
+    will produce a warning, but if we remove the first line we won't see it
+    anymore (which is The Right Thing To Do {tm} IMHO since C preprocessor
+    eats such constructs without warnings at all).
+
+* Added a "error" routine to preprocessor which always will set ERR_PASS1
+    bit in severity_code. This removes annoying repeated errors on first
+    and second passes from preprocessor.
+
+* Added the %+ operator in single-line macros for concatenating two
+    identifiers. Usage example:
+
+       %define _myfunc _otherfunc
+       %define cextern(x) _ %+ x
+       cextern (myfunc)
+
+    After first expansion, third line will become "_myfunc". After this
+    expansion is performed again so it becomes "_otherunc".
+
+* Now if preprocessor is in a non-emmitting state, no warning or error
+    will be emmitted. Example:
+
+       %if 1
+               mov     eax,ebx
+       %else
+               put anything you want between these two brackets,
+               even macro-parameter references %1 or local labels %$zz
+               or macro-local labels %%zz - no warning will be emmitted.
+       %endif
+
+* Context-local variables on expansion as a last resort are looked up
+    in outer contexts. For example, the following piece:
+
+       %push   outer
+       %define %$a [esp]
+
+               %push   inner
+               %$a
+               %pop
+       %pop
+
+    will expand correctly the fourth line to [esp]; if we'll define another
+    %$a inside the "inner" context, it will take precedence over outer
+    definition. However, this modification has been applied only to
+    expand_smacro and not to smacro_define: as a consequence expansion
+    looks in outer contexts, but %ifdef won't look in outer contexts.
+
+    This behaviour is needed because we don't want nested contexts to
+    act on already defined local macros. Example:
+
+       %define %$arg1  [esp+4]
+       test    eax,eax
+       if      nz
+               mov     eax,%$arg1
+       endif
+
+    In this example the "if" mmacro enters into the "if" context, so %$arg1
+    is not valid anymore inside "if". Of course it could be worked around
+    by using explicitely %$$arg1 but this is ugly IMHO.
+
+* Fixed memory leak in %undef. The origline wasn't freed before
+    exiting on success.
+
+* Fixed trap in preprocessor when line expanded to empty set of tokens.
+    This happens, for example, in the following case:
+
+       #define SOMETHING
+       SOMETHING
+
+
+0.98
+----
+
+All changes since NASM 0.98p3 have been produced by H. Peter Anvin <hpa@zytor.com>.
+
+* The documentation comment delimiter is \# not #.
+* Allow EQU definitions to refer to external labels; reported by
+  Pedro Gimeno.
+* Re-enable support for RDOFF v1; reported by Pedro Gimeno.
+* Updated License file per OK from Simon and Julian.
+
+
+0.98p9
+------
+
+* Update documentation (although the instruction set reference will
+  have to wait; I don't want to hold up the 0.98 release for it.)
+* Verified that the NASM implementation of the PEXTRW and PMOVMSKB
+  instructions is correct.  The encoding differs from what the Intel
+  manuals document, but the Pentium III behaviour matches NASM, not
+  the Intel manuals.
+* Fix handling of implicit sizes in PSHUFW and PINSRW, reported by
+  Stefan Hoffmeister.
+* Resurrect the -s option, which was removed when changing the
+  diagnostic output to stdout.
+
+
+0.98p8
+------
+
+* Fix for "DB" when NASM is running on a bigendian machine.
+* Invoke insns.pl once for each output script, making Makefile.in
+  legal for "make -j".
+* Improve the Unix configure-based makefiles to make package
+  creation easier.
+* Included an RPM .spec file for building RPM (RedHat Package Manager)
+  packages on Linux or Unix systems.
+* Fix Makefile dependency problems.
+* Change src/rdsrc.pl to include sectioning information in info
+  output; required for install-info to work.
+* Updated the RDOFF distribution to version 2 from Jules; minor
+  massaging to make it compile in my environment.
+* Split doc files that can be built by anyone with a Perl interpreter off
+  into a separate archive.
+* "Dress rehearsal" release!
+
+
+0.98p7
+------
+
+* Fixed opcodes with a third byte-sized immediate argument to not
+  complain if given "byte" on the immediate.
+* Allow %undef to remove single-line macros with arguments.  This
+  matches the behaviour of #undef in the C preprocessor.
+* Allow -d, -u, -i and -p to be specified as -D, -U, -I and -P for
+  compatibility with most C compilers and preprocessors.  This allows
+  Makefile options to be shared between cc and nasm, for example.
+* Minor cleanups.
+* Went through the list of Katmai instructions and hopefully fixed the
+  (rather few) mistakes in it.
+* (Hopefully) fixed a number of disassembler bugs related to ambiguous
+  instructions (disambiguated by -p) and SSE instructions with REP.
+* Fix for bug reported by Mark Junger: "call dword 0x12345678" should
+  work and may add an OSP (affected CALL, JMP, Jcc).
+* Fix for environments when "stderr" isn't a compile-time constant.
+
+
+0.98p6
+------
+
+* Took officially over coordination of the 0.98 release; so drop
+  the p3.x notation. Skipped p4 and p5 to avoid confusion with John
+  Fine's J4 and J5 releases.
+* Update the documentation; however, it still doesn't include
+  documentation for the various new instructions.  I somehow wonder if
+  it makes sense to have an instruction set reference in the assembler
+  manual when Intel et al have PDF versions of their manuals online.
+* Recognize "idt" or "centaur" for the -p option to ndisasm.
+* Changed error messages back to stderr where they belong, but add an
+  -E option to redirect them elsewhere (the DOS shell cannot redirect
+  stderr.)
+* -M option to generate Makefile dependencies (based on code from Alex
+  Verstak.)
+* %undef preprocessor directive, and -u option, that undefines a
+  single-line macro.
+* OS/2 Makefile (Mkfiles/Makefile.os2) for Borland under OS/2; from
+  Chuck Crayne.
+* Various minor bugfixes (reported by):
+  - Dangling %s in preproc.c (Martin Junker)
+* THERE ARE KNOWN BUGS IN SSE AND THE OTHER KATMAI INSTRUCTIONS.  I am
+  on a trip and didn't bring the Katmai instruction reference, so I
+  can't work on them right now.
+* Updated the License file per agreement with Simon and Jules to
+  include a GPL distribution clause.
+
+
+0.98p3.7
+--------
+
+* (Hopefully) fixed the canned Makefiles to include the outrdf2 and
+  zoutieee modules.
+* Renamed changes.asm to changed.asm.
+
+
+0.98p3.6
+--------
+
+* Fixed a bunch of instructions that were added in 0.98p3.5 which had
+  memory operands, and the address-size prefix was missing from the
+  instruction pattern.
+
+
+0.98p3.5
+--------
+
+* Merged in changes from John S. Fine's 0.98-J5 release.  John's based
+  0.98-J5 on my 0.98p3.3 release; this merges the changes.
+* Expanded the instructions flag field to a long so we can fit more
+  flags; mark SSE (KNI) and AMD or Katmai-specific instructions as
+  such.
+* Fix the "PRIV" flag on a bunch of instructions, and create new
+  "PROT" flag for protected-mode-only instructions (orthogonal to if
+  the instruction is privileged!) and new "SMM" flag for SMM-only
+  instructions.
+* Added AMD-only SYSCALL and SYSRET instructions.
+* Make SSE actually work, and add new Katmai MMX instructions.
+* Added a -p (preferred vendor) option to ndisasm so that it can
+  distinguish e.g. Cyrix opcodes also used in SSE.  For example:
+
+       ndisasm -p cyrix aliased.bin
+       00000000  670F514310        paddsiw mm0,[ebx+0x10]
+       00000005  670F514320        paddsiw mm0,[ebx+0x20]
+       ndisasm -p intel aliased.bin
+       00000000  670F514310        sqrtps xmm0,[ebx+0x10]
+       00000005  670F514320        sqrtps xmm0,[ebx+0x20]
+* Added a bunch of Cyrix-specific instructions.
+
+
+0.98p3.4
+--------
+
+* Made at least an attempt to modify all the additional Makefiles (in
+  the Mkfiles directory).  I can't test it, but this was the best I
+  could do.
+* DOS DJGPP+"Opus Make" Makefile from John S. Fine.
+* changes.asm changes from John S. Fine.
+
+
+0.98p3.3
+--------
+
+* Patch from Conan Brink to allow nesting of %rep directives.
+* If we're going to allow INT01 as an alias for INT1/ICEBP (one of
+  Jules 0.98p3 changes), then we should allow INT03 as an alias for INT3
+  as well.
+* Updated changes.asm to include the latest changes.
+* Tried to clean up the <CR>s that had snuck in from a DOS/Windows
+  environment into my Unix environment, and try to make sure than
+  DOS/Windows users get them back.
+* We would silently generate broken tools if insns.dat wasn't sorted
+  properly.  Change insns.pl so that the order doesn't matter.
+* Fix bug in insns.pl (introduced by me) which would cause conditional
+  instructions to have an extra "cc" in disassembly, e.g. "jnz"
+  disassembled as "jccnz".
+
+
+0.98p3.2
+--------
+
+* Merged in John S. Fine's changes from his 0.98-J4 prerelease; see
+  http://www.csoft.net/cz/johnfine/
+* Changed previous "spotless" Makefile target (appropriate for distribution)
+  to "distclean", and added "cleaner" target which is same as "clean"
+  except deletes files generated by Perl scripts; "spotless" is union.
+* Removed BASIC programs from distribution.  Get a Perl interpreter
+  instead (see below.)
+* Calling this "pre-release 3.2" rather than "p3-hpa2" because of
+  John's contributions.
+* Actually link in the IEEE output format (zoutieee.c); fix a bunch of
+  compiler warnings in that file.  Note I don't know what IEEE output
+  is supposed to look like, so these changes were made "blind".
+
+
+0.98p3-hpa
+----------
+
+* Merged nasm098p3.zip with nasm-0.97.tar.gz to create a fully
+  buildable version for Unix systems (Makefile.in updates, etc.)
+* Changed insns.pl to create the instruction tables in nasm.h and
+  names.c, so that a new instruction can be added by adding it *only*
+  to insns.dat.
+* Added the following new instructions: SYSENTER, SYSEXIT, FXSAVE,
+  FXRSTOR, UD1, UD2 (the latter two are two opcodes that Intel
+  guarantee will never be used; one of them is documented as UD2 in
+  Intel documentation, the other one just as "Undefined Opcode" --
+  calling it UD1 seemed to make sense.)
+* MAX_SYMBOL was defined to be 9, but LOADALL286 and LOADALL386 are 10
+  characters long.  Now MAX_SYMBOL is derived from insns.dat.
+* A note on the BASIC programs included: forget them.  insns.bas is
+  already out of date.  Get yourself a Perl interpreter for your
+  platform of choice at:
+
+       http://www.cpan.org/ports/index.html
+
+
+0.98 pre-release 3
+-------------------
+
+added response file support, improved command line handling, new layout
+help screen
+
+fixed limit checking bug, 'OUT byte nn, reg' bug, and a couple of rdoff
+related bugs, updated Wishlist; 0.98 Prerelease 3.
+
+
+0.98 pre-release 2
+-------------------
+
+fixed bug in outcoff.c to do with truncating section names longer
+than 8 characters, referencing beyond end of string; 0.98 pre-release 2
+
+
+0.98 pre-released May 1999
+--------------------------
+
+Fixed a bug whereby STRUC didn't work at all in RDF.
+
+Fixed a problem with group specification in PUBDEFs in OBJ.
+
+Improved ease of adding new output formats. Contribution due to
+Fox Cutter.
+
+Fixed a bug in relocations in the `bin' format: was showing up when
+a relocatable reference crossed an 8192-byte boundary in any output
+section.
+
+Fixed a bug in local labels: local-label lookups were inconsistent
+between passes one and two if an EQU occurred between the definition
+of a global label and the subsequent use of a local label local to
+that global.
+
+Fixed a seg-fault in the preprocessor (again) which happened when
+you use a blank line as the first line of a multi-line macro
+definition and then defined a label on the same line as a call to
+that macro.
+
+Fixed a stale-pointer bug in the handling of the NASM environment
+variable. Thanks to Thomas McWilliams.
+
+ELF had a hard limit on the number of sections which caused
+segfaults when transgressed. Fixed.
+
+Added ability for ndisasm to read from stdin by using `-' as the
+filename.
+
+ndisasm wasn't outputting the TO keyword. Fixed.
+
+Fixed error cascade on bogus expression in %if - an error in
+evaluation was causing the entire %if to be discarded, thus creating
+trouble later when the %else or %endif was encountered.
+
+Forward reference tracking was instruction-granular not operand-
+granular, which was causing 286-specific code to be generated
+needlessly on code of the form `shr word [forwardref],1'. Thanks to
+Jim Hague for sending a patch.
+
+All messages now appear on stdout, as sending them to stderr serves
+no useful purpose other than to make redirection difficult.
+
+Fixed the problem with EQUs pointing to an external symbol - this
+now generates an error message.
+
+Allowed multiple size prefixes to an operand, of which only the first
+is taken into account.
+
+Incorporated John Fine's changes, including fixes of a large number
+of preprocessor bugs, some small problems in OBJ, and a reworking of
+label handling to define labels before their line is assembled, rather
+than after.
+
+Reformatted a lot of the source code to be more readable. Included
+'coding.txt' as a guideline for how to format code for contributors.
+
+Stopped nested %reps causing a panic - they now cause a slightly more
+friendly error message instead.
+
+Fixed floating point constant problems (patch by Pedro Gimeno)
+
+Fixed the return value of insn_size() not being checked for -1, indicating
+an error.
+
+Incorporated 3D now instructions.
+
+Fixed the 'mov eax, eax + ebx' bug.
+
+Fixed the GLOBAL EQU bug in ELF. Released developers release 3.
+
+Incorporated John Fine's command line parsing changes
+
+Incorporated David Lindauer's OMF debug support
+
+Made changes for LCC 4.0 support (__NASM_CDecl__, removed register size
+specification warning when sizes agree).
+
+Released NASM 0.98 Pre-release 1
+
+
+0.97 released December 1997
+---------------------------
+
+This was entirely a bug-fix release to 0.96, which seems to have got
+cursed. Silly me.
+
+Fixed stupid mistake in OBJ which caused `MOV EAX,<constant>' to
+fail. Caused by an error in the `MOV EAX,<segment>' support.
+
+ndisasm hung at EOF when compiled with lcc on Linux because lcc on
+Linux somehow breaks feof(). ndisasm now does not rely on feof().
+
+A heading in the documentation was missing due to a markup error in
+the indexing. Fixed.
+
+Fixed failure to update all pointers on realloc() within extended-
+operand code in parser.c. Was causing wrong behaviour and seg faults
+on lines such as `dd 0.0,0.0,0.0,0.0,...'
+
+Fixed a subtle preprocessor bug whereby invoking one multi-line
+macro on the first line of the expansion of another, when the second
+had been invoked with a label defined before it, didn't expand the
+inner macro. 
+
+Added internal.doc back in to the distribution archives - it was
+missing in 0.96 *blush*
+
+Fixed bug causing 0.96 to be unable to assemble its own test files,
+specifically objtest.asm. *blush again*
+
+Fixed seg-faults and bogus error messages caused by mismatching
+%rep and %endrep within multi-line macro definitions.
+
+Fixed a problem with buffer overrun in OBJ, which was causing
+corruption at ends of long PUBDEF records.
+
+Separated DOS archives into main-program and documentation to reduce
+download size.
+
+
+0.96 released November 1997
+---------------------------
+
+Fixed a bug whereby, if `nasm sourcefile' would cause a filename
+collision warning and put output into `nasm.out', then `nasm
+sourcefile -o outputfile' still gave the warning even though the
+`-o' was honoured.
+
+Fixed name pollution under Digital UNIX: one of its header files
+defined R_SP, which broke the enum in nasm.h.
+
+Fixed minor instruction table problems: FUCOM and FUCOMP didn't have
+two-operand forms; NDISASM didn't recognise the longer register
+forms of PUSH and POP (eg FF F3 for PUSH BX); TEST mem,imm32 was
+flagged as undocumented; the 32-bit forms of CMOV had 16-bit operand
+size prefixes; `AAD imm' and `AAM imm' are no longer flagged as
+undocumented because the Intel Architecture reference documents
+them.
+
+Fixed a problem with the local-label mechanism, whereby strange
+types of symbol (EQUs, auto-defined OBJ segment base symbols)
+interfered with the `previous global label' value and screwed up
+local labels.
+
+Fixed a bug whereby the stub preprocessor didn't communicate with
+the listing file generator, so that the -a and -l options in
+conjunction would produce a useless listing file.
+
+Merged `os2' object file format back into `obj', after discovering
+that `obj' _also_ shouldn't have a link pass separator in a module
+containing a non-trivial MODEND. Flat segments are now declared
+using the FLAT attribute. `os2' is no longer a valid object format
+name: use `obj'.
+
+Removed the fixed-size temporary storage in the evaluator. Very very
+long expressions (like `mov ax,1+1+1+1+...' for two hundred 1s or
+so) should now no longer crash NASM.
+
+Fixed a bug involving segfaults on disassembly of MMX instructions,
+by changing the meaning of one of the operand-type flags in nasm.h.
+This may cause other apparently unrelated MMX problems; it needs to
+be tested thoroughly.
+
+Fixed some buffer overrun problems with large OBJ output files.
+Thanks to DJ Delorie for the bug report and fix.
+
+Made preprocess-only mode actually listen to the %line markers as it
+prints them, so that it can report errors more sanely.
+
+Re-designed the evaluator to keep more sensible track of expressions
+involving forward references: can now cope with previously-nightmare
+situations such as
+   mov ax,foo | bar
+   foo equ 1
+   bar equ 2
+
+Added the ALIGN and ALIGNB standard macros.
+
+Added PIC support in ELF: use of WRT to obtain the four extra
+relocation types needed.
+
+Added the ability for output file formats to define their own
+extensions to the GLOBAL, COMMON and EXTERN directives.
+
+Implemented common-variable alignment, and global-symbol type and
+size declarations, in ELF.
+
+Implemented NEAR and FAR keywords for common variables, plus
+far-common element size specification, in OBJ.
+
+Added a feature whereby EXTERNs and COMMONs in OBJ can be given a
+default WRT specification (either a segment or a group).
+
+Transformed the Unix NASM archive into an auto-configuring package.
+
+Added a sanity-check for people applying SEG to things which are
+already segment bases: this previously went unnoticed by the SEG
+processing and caused OBJ-driver panics later.
+
+Added the ability, in OBJ format, to deal with `MOV EAX,<segment>'
+type references: OBJ doesn't directly support dword-size segment
+base fixups, but as long as the low two bytes of the constant term
+are zero, a word-size fixup can be generated instead and it will
+work.
+
+Added the ability to specify sections' alignment requirements in
+Win32 object files and pure binary files.
+
+Added preprocess-time expression evaluation: the %assign (and
+%iassign) directive and the bare %if (and %elif) conditional. Added
+relational operators to the evaluator, for use only in %if
+constructs: the standard relationals = < > <= >= <> (and C-like
+synonyms == and !=) plus low-precedence logical operators &&, ^^ and
+||.
+
+Added a preprocessor repeat construct: %rep / %exitrep / %endrep.
+
+Added the __FILE__ and __LINE__ standard macros.
+
+Added a sanity check for number constants being greater than
+0xFFFFFFFF. The warning can be disabled.
+
+Added the %0 token whereby a variadic multi-line macro can tell how
+many parameters it's been given in a specific invocation.
+
+Added %rotate, allowing multi-line macro parameters to be cycled.
+
+Added the `*' option for the maximum parameter count on multi-line
+macros, allowing them to take arbitrarily many parameters.
+
+Added the ability for the user-level forms of EXTERN, GLOBAL and
+COMMON to take more than one argument.
+
+Added the IMPORT and EXPORT directives in OBJ format, to deal with
+Windows DLLs.
+
+Added some more preprocessor %if constructs: %ifidn / %ifidni (exact
+textual identity), and %ifid / %ifnum / %ifstr (token type testing).
+
+Added the ability to distinguish SHL AX,1 (the 8086 version) from
+SHL AX,BYTE 1 (the 286-and-upwards version whose constant happens to
+be 1).
+
+Added NetBSD/FreeBSD/OpenBSD's variant of a.out format, complete
+with PIC shared library features.
+
+Changed NASM's idiosyncratic handling of FCLEX, FDISI, FENI, FINIT,
+FSAVE, FSTCW, FSTENV, and FSTSW to bring it into line with the
+otherwise accepted standard. The previous behaviour, though it was a
+deliberate feature, was a deliberate feature based on a
+misunderstanding. Apologies for the inconvenience.
+
+Improved the flexibility of ABSOLUTE: you can now give it an
+expression rather than being restricted to a constant, and it can
+take relocatable arguments as well.
+
+Added the ability for a variable to be declared as EXTERN multiple
+times, and the subsequent definitions are just ignored.
+
+We now allow instruction prefixes (CS, DS, LOCK, REPZ etc) to be
+alone on a line (without a following instruction).
+
+Improved sanity checks on whether the arguments to EXTERN, GLOBAL
+and COMMON are valid identifiers.
+
+Added misc/exebin.mac to allow direct generation of .EXE files by
+hacking up an EXE header using DB and DW; also added test/binexe.asm
+to demonstrate the use of this. Thanks to Yann Guidon for
+contributing the EXE header code.
+
+ndisasm forgot to check whether the input file had been successfully
+opened. Now it does. Doh!
+
+Added the Cyrix extensions to the MMX instruction set.
+
+Added a hinting mechanism to allow [EAX+EBX] and [EBX+EAX] to be
+assembled differently. This is important since [ESI+EBP] and
+[EBP+ESI] have different default base segment registers.
+
+Added support for the PharLap OMF extension for 4096-byte segment
+alignment.
+
+
+0.95 released July 1997
+-----------------------
+
+Fixed yet another ELF bug. This one manifested if the user relied on
+the default segment, and attempted to define global symbols without
+first explicitly declaring the target segment.
+
+Added makefiles (for NASM and the RDF tools) to build Win32 console
+apps under Symantec C++. Donated by Mark Junker.
+
+Added `macros.bas' and `insns.bas', QBasic versions of the Perl
+scripts that convert `standard.mac' to `macros.c' and convert
+`insns.dat' to `insnsa.c' and `insnsd.c'. Also thanks to Mark
+Junker.
+
+Changed the diassembled forms of the conditional instructions so
+that JB is now emitted as JC, and other similar changes. Suggested
+list by Ulrich Doewich.
+
+Added `@' to the list of valid characters to begin an identifier
+with.
+
+Documentary changes, notably the addition of the `Common Problems'
+section in nasm.doc.
+
+Fixed a bug relating to 32-bit PC-relative fixups in OBJ.
+
+Fixed a bug in perm_copy() in labels.c which was causing exceptions
+in cleanup_labels() on some systems.
+
+Positivity sanity check in TIMES argument changed from a warning to
+an error following a further complaint.
+
+Changed the acceptable limits on byte and word operands to allow
+things like `~10111001b' to work.
+
+Fixed a major problem in the preprocessor which caused seg-faults if
+macro definitions contained blank lines or comment-only lines.
+
+Fixed inadequate error checking on the commas separating the
+arguments to `db', `dw' etc.
+
+Fixed a crippling bug in the handling of macros with operand counts
+defined with a `+' modifier.
+
+Fixed a bug whereby object file formats which stored the input file
+name in the output file (such as OBJ and COFF) weren't doing so
+correctly when the output file name was specified on the command
+line.
+
+Removed [INC] and [INCLUDE] support for good, since they were
+obsolete anyway.
+
+Fixed a bug in OBJ which caused all fixups to be output in 16-bit
+(old-format) FIXUPP records, rather than putting the 32-bit ones in
+FIXUPP32 (new-format) records.
+
+Added, tentatively, OS/2 object file support (as a minor variant on
+OBJ).
+
+Updates to Fox Cutter's Borland C makefile, Makefile.bc2.
+
+Removed a spurious second fclose() on the output file.
+
+Added the `-s' command line option to redirect all messages which
+would go to stderr (errors, help text) to stdout instead.
+
+Added the `-w' command line option to selectively suppress some
+classes of assembly warning messages.
+
+Added the `-p' pre-include and `-d' pre-define command-line options.
+
+Added an include file search path: the `-i' command line option.
+
+Fixed a silly little preprocessor bug whereby starting a line with a
+`%!' environment-variable reference caused an `unknown directive'
+error.
+
+Added the long-awaited listing file support: the `-l' command line
+option.
+
+Fixed a problem with OBJ format whereby, in the absence of any
+explicit segment definition, non-global symbols declared in the
+implicit default segment generated spurious EXTDEF records in the
+output.
+
+Added the NASM environment variable.
+
+From this version forward, Win32 console-mode binaries will be
+included in the DOS distribution in addition to the 16-bit binaries.
+Added Makefile.vc for this purpose.
+
+Added `return 0;' to test/objlink.c to prevent compiler warnings.
+
+Added the __NASM_MAJOR__ and __NASM_MINOR__ standard defines.
+
+Added an alternative memory-reference syntax in which prefixing an
+operand with `&' is equivalent to enclosing it in square brackets,
+at the request of Fox Cutter.
+
+Errors in pass two now cause the program to return a non-zero error
+code, which they didn't before.
+
+Fixed the single-line macro cycle detection, which didn't work at
+all on macros with no parameters (caused an infinite loop). Also
+changed the behaviour of single-line macro cycle detection to work
+like cpp, so that macros like `extrn' as given in the documentation
+can be implemented.
+
+Fixed the implementation of WRT, which was too restrictive in that
+you couldn't do `mov ax,[di+abc wrt dgroup]' because (di+abc) wasn't
+a relocatable reference.
+
+
+0.94 released April 1997
+------------------------
+
+Major item: added the macro processor.
+
+Added undocumented instructions SMI, IBTS, XBTS and LOADALL286. Also
+reorganised CMPXCHG instruction into early-486 and Pentium forms.
+Thanks to Thobias Jones for the information.
+
+Fixed two more stupid bugs in ELF, which were causing `ld' to
+continue to seg-fault in a lot of non-trivial cases.
+
+Fixed a seg-fault in the label manager.
+
+Stopped FBLD and FBSTP from _requiring_ the TWORD keyword, which is
+the only option for BCD loads/stores in any case.
+
+Ensured FLDCW, FSTCW and FSTSW can cope with the WORD keyword, if
+anyone bothers to provide it. Previously they complained unless no
+keyword at all was present.
+
+Some forms of FDIV/FDIVR and FSUB/FSUBR were still inverted: a
+vestige of a bug that I thought had been fixed in 0.92. This was
+fixed, hopefully for good this time...
+
+Another minor phase error (insofar as a phase error can _ever_ be
+minor) fixed, this one occurring in code of the form
+   rol ax,forward_reference
+   forward_reference equ 1
+
+The number supplied to TIMES is now sanity-checked for positivity,
+and also may be greater than 64K (which previously didn't work on
+16-bit systems).
+
+Added Watcom C makefiles, and misc/pmw.bat, donated by Dominik Behr.
+
+Added the INCBIN pseudo-opcode.
+
+Due to the advent of the preprocessor, the [INCLUDE] and [INC]
+directives have become obsolete. They are still supported in this
+version, with a warning, but won't be in the next.
+
+Fixed a bug in OBJ format, which caused incorrect object records to
+be output when absolute labels were made global.
+
+Updates to RDOFF subdirectory, and changes to outrdf.c.
+
+
+0.93 released January 1997
+--------------------------
+
+This release went out in a great hurry after semi-crippling bugs
+were found in 0.92.
+
+Really _did_ fix the stack overflows this time. *blush*
+
+Had problems with EA instruction sizes changing between passes, when
+an offset contained a forward reference and so 4 bytes were
+allocated for the offset in pass one; by pass two the symbol had
+been defined and happened to be a small absolute value, so only 1
+byte got allocated, causing instruction size mismatch between passes
+and hence incorrect address calculations. Fixed.
+
+Stupid bug in the revised ELF section generation fixed (associated
+string-table section for .symtab was hard-coded as 7, even when this
+didn't fit with the real section table). Was causing `ld' to
+seg-fault under Linux.
+
+Included a new Borland C makefile, Makefile.bc2, donated by Fox
+Cutter <lmb@comtch.iea.com>.
+
+
+0.92 released January 1997
+--------------------------
+
+The FDIVP/FDIVRP and FSUBP/FSUBRP pairs had been inverted: this was
+fixed. This also affected the LCC driver.
+
+Fixed a bug regarding 32-bit effective addresses of the form
+[other_register+ESP].
+
+Documentary changes, notably documentation of the fact that Borland
+Win32 compilers use `obj' rather than `win32' object format.
+
+Fixed the COMENT record in OBJ files, which was formatted
+incorrectly.
+
+Fixed a bug causing segfaults in large RDF files.
+
+OBJ format now strips initial periods from segment and group
+definitions, in order to avoid complications with the local label
+syntax.
+
+Fixed a bug in disassembling far calls and jumps in NDISASM.
+
+Added support for user-defined sections in COFF and ELF files.
+
+Compiled the DOS binaries with a sensible amount of stack, to
+prevent stack overflows on any arithmetic expression containing
+parentheses.
+
+Fixed a bug in handling of files that do not terminate in a newline.
+
+
+0.91 released November 1996
+---------------------------
+
+Loads of bug fixes.
+Support for RDF added.
+Support for DBG debugging format added.
+Support for 32-bit extensions to Microsoft OBJ format added.
+Revised for Borland C: some variable names changed, makefile added.
+LCC support revised to actually work.
+JMP/CALL NEAR/FAR notation added.
+`a16', `o16', `a32' and `o32' prefixes added.
+Range checking on short jumps implemented.
+MMX instruction support added.
+Negative floating point constant support added.
+Memory handling improved to bypass 64K barrier under DOS.
+$ prefix to force treatment of reserved words as identifiers added.
+Default-size mechanism for object formats added.
+Compile-time configurability added.
+`#', `@', `~' and `?' are now valid characters in labels.
+`-e' and `-k' options in NDISASM added.
+
+
+0.90 released October 1996
+--------------------------
+
+First release version. First support for object file output. Other
+changes from previous version (0.3x) too numerous to document.
diff --git a/COPYING b/COPYING
index 60549be514af76c5db0c17ce6bbe01b2f81e2d9e..82de29fb2caef1ccf5272d690b2a97af79098867 100644 (file)
--- a/COPYING
+++ b/COPYING
-                   GNU GENERAL PUBLIC LICENSE
-                      Version 2, June 1991
 
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
-                           Preamble
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
 
   The licenses for most software are designed to take away your
 freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
 
   To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+^L
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes a de-facto standard.  To achieve this, non-free programs must
+be allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
 
   The precise terms and conditions for copying, distribution and
-modification follow.
-\f
-                   GNU GENERAL PUBLIC LICENSE
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+^L
+                  GNU LESSER GENERAL PUBLIC LICENSE
    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control
+compilation and installation of the library.
+
+  Activities other than copying, distribution and modification are not
 covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
 distribute such modifications or work under the terms of Section 1
 above, provided that you also meet all of these conditions:
 
-    a) You must cause the modified files to carry prominent notices
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
     stating that you changed the files and the date of any change.
 
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-\f
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
 These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
+identifiable sections of that work are not derived from the Library,
 and can be reasonably considered independent and separate works in
 themselves, then this License, and its terms, do not apply to those
 sections when you distribute them as separate works.  But when you
 distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
+on the Library, the distribution of the whole must be on the terms of
 this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
+entire whole, and thus to each and every part regardless of who wrote
+it.
 
 Thus, it is not the intent of this section to claim rights or contest
 your rights to work written entirely by you; rather, the intent is to
 exercise the right to control the distribution of derivative or
-collective works based on the Program.
+collective works based on the Library.
 
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
 a storage or distribution medium does not bring the other work under
 the scope of this License.
 
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+^L
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
 compelled to copy the source along with the object code.
-\f
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+^L
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at least
+    three years, to give the same user the materials specified in
+    Subsection 6a, above, for a charge no more than the cost of
+    performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+^L
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
 signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
+distribute the Library or its derivative works.  These actions are
 prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
 all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
+the Library or works based on it.
 
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
 restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
+You are not responsible for enforcing compliance by third parties with
 this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
+^L
+  11. If, as a consequence of a court judgment or allegation of patent
 infringement or for any other reason (not limited to patent issues),
 conditions are imposed on you (whether by court order, agreement or
 otherwise) that contradict the conditions of this License, they do not
 excuse you from the conditions of this License.  If you cannot
 distribute so as to satisfy simultaneously your obligations under this
 License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
 all those who receive copies directly or indirectly through you, then
 the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
+refrain entirely from distribution of the Library.
 
 If any portion of this section is held invalid or unenforceable under
 any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
+apply, and the section as a whole is intended to apply in other
 circumstances.
 
 It is not the purpose of this section to induce you to infringe any
 patents or other property right claims or to contest validity of any
 such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
+integrity of the free software distribution system which is
 implemented by public license practices.  Many people have made
 generous contributions to the wide range of software distributed
 through that system in reliance on consistent application of that
@@ -225,116 +404,59 @@ impose that choice.
 
 This section is intended to make thoroughly clear what is believed to
 be a consequence of the rest of this License.
-\f
-  8. If the distribution and/or use of the Program is restricted in
+
+  12. If the distribution and/or use of the Library is restricted in
 certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
+original copyright holder who places the Library under this License
+may add an explicit geographical distribution limitation excluding those
+countries, so that distribution is permitted only in or among
 countries not thus excluded.  In such case, this License incorporates
 the limitation as if written in the body of this License.
 
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-                           NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-                    END OF TERMS AND CONDITIONS
-\f
-           How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) 19yy  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) 19yy name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+^L
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+^L
index 13f7c282c2c8ed047faef8eeb5e0c9d430921df4..649574db094b6ca4acf15b66637627b0280d7acc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,21 @@
 
-2002-04-11  Stanislav Karchebny  <berk@madfire.net>
+2002-04-29  Stanislav Karchebny  <madfire@users.sourceforge.net>
+
+   * (Makefile.in): added 'strip' target to strip debug info.
+   * (INSTALL): added INSTALL file.
+   * (nasm.1): added -v option description.
+
+
+2002-04-29  Frank Kotler  <fbkotler@users.sourceforge.net>
+
+   * (parser.c): fixed INCBIN bug reported by Rebel.
+
+
+2002-04-11  Stanislav Karchebny  <madfire@users.sourceforge.net>
+
+   * Started ChangeLog for recording per-file changes in the project.
+     We could get away without ChangeLog at all (use CVS logs), but we
+     lose CVS so often its better to have log glued to the sources =)
+     You should record changes in CHANGES also, not for every change
+     but rather when making a release.
 
-   * Started ChangeLog instead of Changes. ChangeLog is better because all recent changes
-     are on top of the file, easy for inspection.
-     Old entries from doc/Changes will eventually be added here.
diff --git a/Changes b/Changes
deleted file mode 100644 (file)
index f383182..0000000
--- a/Changes
+++ /dev/null
@@ -1,542 +0,0 @@
-Change log for NASM
-===================
-
-This is the Changelog for the official releases; this is a modified
-version.  For the changes from the official release, see the MODIFIED file.
-
-0.90 released October 1996
---------------------------
-
-First release version. First support for object file output. Other
-changes from previous version (0.3x) too numerous to document.
-
-0.91 released November 1996
----------------------------
-
-Loads of bug fixes.
-Support for RDF added.
-Support for DBG debugging format added.
-Support for 32-bit extensions to Microsoft OBJ format added.
-Revised for Borland C: some variable names changed, makefile added.
-LCC support revised to actually work.
-JMP/CALL NEAR/FAR notation added.
-`a16', `o16', `a32' and `o32' prefixes added.
-Range checking on short jumps implemented.
-MMX instruction support added.
-Negative floating point constant support added.
-Memory handling improved to bypass 64K barrier under DOS.
-$ prefix to force treatment of reserved words as identifiers added.
-Default-size mechanism for object formats added.
-Compile-time configurability added.
-`#', `@', `~' and `?' are now valid characters in labels.
-`-e' and `-k' options in NDISASM added.
-
-0.92 released January 1997
---------------------------
-
-The FDIVP/FDIVRP and FSUBP/FSUBRP pairs had been inverted: this was
-fixed. This also affected the LCC driver.
-
-Fixed a bug regarding 32-bit effective addresses of the form
-[other_register+ESP].
-
-Documentary changes, notably documentation of the fact that Borland
-Win32 compilers use `obj' rather than `win32' object format.
-
-Fixed the COMENT record in OBJ files, which was formatted
-incorrectly.
-
-Fixed a bug causing segfaults in large RDF files.
-
-OBJ format now strips initial periods from segment and group
-definitions, in order to avoid complications with the local label
-syntax.
-
-Fixed a bug in disassembling far calls and jumps in NDISASM.
-
-Added support for user-defined sections in COFF and ELF files.
-
-Compiled the DOS binaries with a sensible amount of stack, to
-prevent stack overflows on any arithmetic expression containing
-parentheses.
-
-Fixed a bug in handling of files that do not terminate in a newline.
-
-0.93 released January 1997
---------------------------
-
-This release went out in a great hurry after semi-crippling bugs
-were found in 0.92.
-
-Really _did_ fix the stack overflows this time. *blush*
-
-Had problems with EA instruction sizes changing between passes, when
-an offset contained a forward reference and so 4 bytes were
-allocated for the offset in pass one; by pass two the symbol had
-been defined and happened to be a small absolute value, so only 1
-byte got allocated, causing instruction size mismatch between passes
-and hence incorrect address calculations. Fixed.
-
-Stupid bug in the revised ELF section generation fixed (associated
-string-table section for .symtab was hard-coded as 7, even when this
-didn't fit with the real section table). Was causing `ld' to
-seg-fault under Linux.
-
-Included a new Borland C makefile, Makefile.bc2, donated by Fox
-Cutter <lmb@comtch.iea.com>.
-
-0.94 released April 1997
-------------------------
-
-Major item: added the macro processor.
-
-Added undocumented instructions SMI, IBTS, XBTS and LOADALL286. Also
-reorganised CMPXCHG instruction into early-486 and Pentium forms.
-Thanks to Thobias Jones for the information.
-
-Fixed two more stupid bugs in ELF, which were causing `ld' to
-continue to seg-fault in a lot of non-trivial cases.
-
-Fixed a seg-fault in the label manager.
-
-Stopped FBLD and FBSTP from _requiring_ the TWORD keyword, which is
-the only option for BCD loads/stores in any case.
-
-Ensured FLDCW, FSTCW and FSTSW can cope with the WORD keyword, if
-anyone bothers to provide it. Previously they complained unless no
-keyword at all was present.
-
-Some forms of FDIV/FDIVR and FSUB/FSUBR were still inverted: a
-vestige of a bug that I thought had been fixed in 0.92. This was
-fixed, hopefully for good this time...
-
-Another minor phase error (insofar as a phase error can _ever_ be
-minor) fixed, this one occurring in code of the form
-   rol ax,forward_reference
-   forward_reference equ 1
-
-The number supplied to TIMES is now sanity-checked for positivity,
-and also may be greater than 64K (which previously didn't work on
-16-bit systems).
-
-Added Watcom C makefiles, and misc/pmw.bat, donated by Dominik Behr.
-
-Added the INCBIN pseudo-opcode.
-
-Due to the advent of the preprocessor, the [INCLUDE] and [INC]
-directives have become obsolete. They are still supported in this
-version, with a warning, but won't be in the next.
-
-Fixed a bug in OBJ format, which caused incorrect object records to
-be output when absolute labels were made global.
-
-Updates to RDOFF subdirectory, and changes to outrdf.c.
-
-0.95 released July 1997
------------------------
-
-Fixed yet another ELF bug. This one manifested if the user relied on
-the default segment, and attempted to define global symbols without
-first explicitly declaring the target segment.
-
-Added makefiles (for NASM and the RDF tools) to build Win32 console
-apps under Symantec C++. Donated by Mark Junker.
-
-Added `macros.bas' and `insns.bas', QBasic versions of the Perl
-scripts that convert `standard.mac' to `macros.c' and convert
-`insns.dat' to `insnsa.c' and `insnsd.c'. Also thanks to Mark
-Junker.
-
-Changed the diassembled forms of the conditional instructions so
-that JB is now emitted as JC, and other similar changes. Suggested
-list by Ulrich Doewich.
-
-Added `@' to the list of valid characters to begin an identifier
-with.
-
-Documentary changes, notably the addition of the `Common Problems'
-section in nasm.doc.
-
-Fixed a bug relating to 32-bit PC-relative fixups in OBJ.
-
-Fixed a bug in perm_copy() in labels.c which was causing exceptions
-in cleanup_labels() on some systems.
-
-Positivity sanity check in TIMES argument changed from a warning to
-an error following a further complaint.
-
-Changed the acceptable limits on byte and word operands to allow
-things like `~10111001b' to work.
-
-Fixed a major problem in the preprocessor which caused seg-faults if
-macro definitions contained blank lines or comment-only lines.
-
-Fixed inadequate error checking on the commas separating the
-arguments to `db', `dw' etc.
-
-Fixed a crippling bug in the handling of macros with operand counts
-defined with a `+' modifier.
-
-Fixed a bug whereby object file formats which stored the input file
-name in the output file (such as OBJ and COFF) weren't doing so
-correctly when the output file name was specified on the command
-line.
-
-Removed [INC] and [INCLUDE] support for good, since they were
-obsolete anyway.
-
-Fixed a bug in OBJ which caused all fixups to be output in 16-bit
-(old-format) FIXUPP records, rather than putting the 32-bit ones in
-FIXUPP32 (new-format) records.
-
-Added, tentatively, OS/2 object file support (as a minor variant on
-OBJ).
-
-Updates to Fox Cutter's Borland C makefile, Makefile.bc2.
-
-Removed a spurious second fclose() on the output file.
-
-Added the `-s' command line option to redirect all messages which
-would go to stderr (errors, help text) to stdout instead.
-
-Added the `-w' command line option to selectively suppress some
-classes of assembly warning messages.
-
-Added the `-p' pre-include and `-d' pre-define command-line options.
-
-Added an include file search path: the `-i' command line option.
-
-Fixed a silly little preprocessor bug whereby starting a line with a
-`%!' environment-variable reference caused an `unknown directive'
-error.
-
-Added the long-awaited listing file support: the `-l' command line
-option.
-
-Fixed a problem with OBJ format whereby, in the absence of any
-explicit segment definition, non-global symbols declared in the
-implicit default segment generated spurious EXTDEF records in the
-output.
-
-Added the NASM environment variable.
-
-From this version forward, Win32 console-mode binaries will be
-included in the DOS distribution in addition to the 16-bit binaries.
-Added Makefile.vc for this purpose.
-
-Added `return 0;' to test/objlink.c to prevent compiler warnings.
-
-Added the __NASM_MAJOR__ and __NASM_MINOR__ standard defines.
-
-Added an alternative memory-reference syntax in which prefixing an
-operand with `&' is equivalent to enclosing it in square brackets,
-at the request of Fox Cutter.
-
-Errors in pass two now cause the program to return a non-zero error
-code, which they didn't before.
-
-Fixed the single-line macro cycle detection, which didn't work at
-all on macros with no parameters (caused an infinite loop). Also
-changed the behaviour of single-line macro cycle detection to work
-like cpp, so that macros like `extrn' as given in the documentation
-can be implemented.
-
-Fixed the implementation of WRT, which was too restrictive in that
-you couldn't do `mov ax,[di+abc wrt dgroup]' because (di+abc) wasn't
-a relocatable reference.
-
-0.96 released November 1997
----------------------------
-
-Fixed a bug whereby, if `nasm sourcefile' would cause a filename
-collision warning and put output into `nasm.out', then `nasm
-sourcefile -o outputfile' still gave the warning even though the
-`-o' was honoured.
-
-Fixed name pollution under Digital UNIX: one of its header files
-defined R_SP, which broke the enum in nasm.h.
-
-Fixed minor instruction table problems: FUCOM and FUCOMP didn't have
-two-operand forms; NDISASM didn't recognise the longer register
-forms of PUSH and POP (eg FF F3 for PUSH BX); TEST mem,imm32 was
-flagged as undocumented; the 32-bit forms of CMOV had 16-bit operand
-size prefixes; `AAD imm' and `AAM imm' are no longer flagged as
-undocumented because the Intel Architecture reference documents
-them.
-
-Fixed a problem with the local-label mechanism, whereby strange
-types of symbol (EQUs, auto-defined OBJ segment base symbols)
-interfered with the `previous global label' value and screwed up
-local labels.
-
-Fixed a bug whereby the stub preprocessor didn't communicate with
-the listing file generator, so that the -a and -l options in
-conjunction would produce a useless listing file.
-
-Merged `os2' object file format back into `obj', after discovering
-that `obj' _also_ shouldn't have a link pass separator in a module
-containing a non-trivial MODEND. Flat segments are now declared
-using the FLAT attribute. `os2' is no longer a valid object format
-name: use `obj'.
-
-Removed the fixed-size temporary storage in the evaluator. Very very
-long expressions (like `mov ax,1+1+1+1+...' for two hundred 1s or
-so) should now no longer crash NASM.
-
-Fixed a bug involving segfaults on disassembly of MMX instructions,
-by changing the meaning of one of the operand-type flags in nasm.h.
-This may cause other apparently unrelated MMX problems; it needs to
-be tested thoroughly.
-
-Fixed some buffer overrun problems with large OBJ output files.
-Thanks to DJ Delorie for the bug report and fix.
-
-Made preprocess-only mode actually listen to the %line markers as it
-prints them, so that it can report errors more sanely.
-
-Re-designed the evaluator to keep more sensible track of expressions
-involving forward references: can now cope with previously-nightmare
-situations such as
-   mov ax,foo | bar
-   foo equ 1
-   bar equ 2
-
-Added the ALIGN and ALIGNB standard macros.
-
-Added PIC support in ELF: use of WRT to obtain the four extra
-relocation types needed.
-
-Added the ability for output file formats to define their own
-extensions to the GLOBAL, COMMON and EXTERN directives.
-
-Implemented common-variable alignment, and global-symbol type and
-size declarations, in ELF.
-
-Implemented NEAR and FAR keywords for common variables, plus
-far-common element size specification, in OBJ.
-
-Added a feature whereby EXTERNs and COMMONs in OBJ can be given a
-default WRT specification (either a segment or a group).
-
-Transformed the Unix NASM archive into an auto-configuring package.
-
-Added a sanity-check for people applying SEG to things which are
-already segment bases: this previously went unnoticed by the SEG
-processing and caused OBJ-driver panics later.
-
-Added the ability, in OBJ format, to deal with `MOV EAX,<segment>'
-type references: OBJ doesn't directly support dword-size segment
-base fixups, but as long as the low two bytes of the constant term
-are zero, a word-size fixup can be generated instead and it will
-work.
-
-Added the ability to specify sections' alignment requirements in
-Win32 object files and pure binary files.
-
-Added preprocess-time expression evaluation: the %assign (and
-%iassign) directive and the bare %if (and %elif) conditional. Added
-relational operators to the evaluator, for use only in %if
-constructs: the standard relationals = < > <= >= <> (and C-like
-synonyms == and !=) plus low-precedence logical operators &&, ^^ and
-||.
-
-Added a preprocessor repeat construct: %rep / %exitrep / %endrep.
-
-Added the __FILE__ and __LINE__ standard macros.
-
-Added a sanity check for number constants being greater than
-0xFFFFFFFF. The warning can be disabled.
-
-Added the %0 token whereby a variadic multi-line macro can tell how
-many parameters it's been given in a specific invocation.
-
-Added %rotate, allowing multi-line macro parameters to be cycled.
-
-Added the `*' option for the maximum parameter count on multi-line
-macros, allowing them to take arbitrarily many parameters.
-
-Added the ability for the user-level forms of EXTERN, GLOBAL and
-COMMON to take more than one argument.
-
-Added the IMPORT and EXPORT directives in OBJ format, to deal with
-Windows DLLs.
-
-Added some more preprocessor %if constructs: %ifidn / %ifidni (exact
-textual identity), and %ifid / %ifnum / %ifstr (token type testing).
-
-Added the ability to distinguish SHL AX,1 (the 8086 version) from
-SHL AX,BYTE 1 (the 286-and-upwards version whose constant happens to
-be 1).
-
-Added NetBSD/FreeBSD/OpenBSD's variant of a.out format, complete
-with PIC shared library features.
-
-Changed NASM's idiosyncratic handling of FCLEX, FDISI, FENI, FINIT,
-FSAVE, FSTCW, FSTENV, and FSTSW to bring it into line with the
-otherwise accepted standard. The previous behaviour, though it was a
-deliberate feature, was a deliberate feature based on a
-misunderstanding. Apologies for the inconvenience.
-
-Improved the flexibility of ABSOLUTE: you can now give it an
-expression rather than being restricted to a constant, and it can
-take relocatable arguments as well.
-
-Added the ability for a variable to be declared as EXTERN multiple
-times, and the subsequent definitions are just ignored.
-
-We now allow instruction prefixes (CS, DS, LOCK, REPZ etc) to be
-alone on a line (without a following instruction).
-
-Improved sanity checks on whether the arguments to EXTERN, GLOBAL
-and COMMON are valid identifiers.
-
-Added misc/exebin.mac to allow direct generation of .EXE files by
-hacking up an EXE header using DB and DW; also added test/binexe.asm
-to demonstrate the use of this. Thanks to Yann Guidon for
-contributing the EXE header code.
-
-ndisasm forgot to check whether the input file had been successfully
-opened. Now it does. Doh!
-
-Added the Cyrix extensions to the MMX instruction set.
-
-Added a hinting mechanism to allow [EAX+EBX] and [EBX+EAX] to be
-assembled differently. This is important since [ESI+EBP] and
-[EBP+ESI] have different default base segment registers.
-
-Added support for the PharLap OMF extension for 4096-byte segment
-alignment.
-
-0.97 released December 1997
----------------------------
-
-This was entirely a bug-fix release to 0.96, which seems to have got
-cursed. Silly me.
-
-Fixed stupid mistake in OBJ which caused `MOV EAX,<constant>' to
-fail. Caused by an error in the `MOV EAX,<segment>' support.
-
-ndisasm hung at EOF when compiled with lcc on Linux because lcc on
-Linux somehow breaks feof(). ndisasm now does not rely on feof().
-
-A heading in the documentation was missing due to a markup error in
-the indexing. Fixed.
-
-Fixed failure to update all pointers on realloc() within extended-
-operand code in parser.c. Was causing wrong behaviour and seg faults
-on lines such as `dd 0.0,0.0,0.0,0.0,...'
-
-Fixed a subtle preprocessor bug whereby invoking one multi-line
-macro on the first line of the expansion of another, when the second
-had been invoked with a label defined before it, didn't expand the
-inner macro. 
-
-Added internal.doc back in to the distribution archives - it was
-missing in 0.96 *blush*
-
-Fixed bug causing 0.96 to be unable to assemble its own test files,
-specifically objtest.asm. *blush again*
-
-Fixed seg-faults and bogus error messages caused by mismatching
-%rep and %endrep within multi-line macro definitions.
-
-Fixed a problem with buffer overrun in OBJ, which was causing
-corruption at ends of long PUBDEF records.
-
-Separated DOS archives into main-program and documentation to reduce
-download size.
-
-0.98 released May 1999
-----------------------
-
-Fixed a bug whereby STRUC didn't work at all in RDF.
-
-Fixed a problem with group specification in PUBDEFs in OBJ.
-
-Improved ease of adding new output formats. Contribution due to
-Fox Cutter.
-
-Fixed a bug in relocations in the `bin' format: was showing up when
-a relocatable reference crossed an 8192-byte boundary in any output
-section.
-
-Fixed a bug in local labels: local-label lookups were inconsistent
-between passes one and two if an EQU occurred between the definition
-of a global label and the subsequent use of a local label local to
-that global.
-
-Fixed a seg-fault in the preprocessor (again) which happened when
-you use a blank line as the first line of a multi-line macro
-definition and then defined a label on the same line as a call to
-that macro.
-
-Fixed a stale-pointer bug in the handling of the NASM environment
-variable. Thanks to Thomas McWilliams.
-
-ELF had a hard limit on the number of sections which caused
-segfaults when transgressed. Fixed.
-
-Added ability for ndisasm to read from stdin by using `-' as the
-filename.
-
-ndisasm wasn't outputting the TO keyword. Fixed.
-
-Fixed error cascade on bogus expression in %if - an error in
-evaluation was causing the entire %if to be discarded, thus creating
-trouble later when the %else or %endif was encountered.
-
-Forward reference tracking was instruction-granular not operand-
-granular, which was causing 286-specific code to be generated
-needlessly on code of the form `shr word [forwardref],1'. Thanks to
-Jim Hague for sending a patch.
-
-All messages now appear on stdout, as sending them to stderr serves
-no useful purpose other than to make redirection difficult.
-
-Fixed the problem with EQUs pointing to an external symbol - this
-now generates an error message.
-
-Allowed multiple size prefixes to an operand, of which only the first
-is taken into account.
-
-Incorporated John Fine's changes, including fixes of a large number
-of preprocessor bugs, some small problems in OBJ, and a reworking of
-label handling to define labels before their line is assembled, rather
-than after.
-
-Reformatted a lot of the source code to be more readable. Included
-'coding.txt' as a guideline for how to format code for contributors.
-
-Stopped nested %reps causing a panic - they now cause a slightly more
-friendly error message instead.
-
-Fixed floating point constant problems (patch by Pedro Gimeno)
-
-Fixed the return value of insn_size() not being checked for -1, indicating
-an error.
-
-Incorporated 3D now instructions.
-
-Fixed the 'mov eax, eax + ebx' bug.
-
-Fixed the GLOBAL EQU bug in ELF. Released developers release 3.
-
-Incorporated John Fine's command line parsing changes
-
-Incorporated David Lindauer's OMF debug support
-
-Made changes for LCC 4.0 support (__NASM_CDecl__, removed register size
-specification warning when sizes agree).
-
-Released NASM 0.98 Pre-release 1
-
-fixed bug in outcoff.c to do with truncating section names longer
-than 8 characters, referencing beyond end of string; 0.98 pre-release 2
-
-added response file support, improved command line handling, new layout
-help screen
-
-fixed limit checking bug, 'OUT byte nn, reg' bug, and a couple of rdoff
-related bugs, updated Wishlist; 0.98 Prerelease 3.
-
-See the file "MODIFIED" for changes after 0.98p3.
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..2d77e3a
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,59 @@
+
+Installing nasm from source
+===========================
+
+Installing nasm is pretty straightforward on UN*X systems with GNU tools installed.
+
+If you checked out source from CVS you will need to run autoconf to generate configure,
+otherwise you don't have to.
+
+$ autoconf
+
+Then run configure to detect your platform settings and generate makefiles.
+
+$ ./configure
+
+You can get information about available configuration options by running `./configure --help`.
+
+If configure fails, please send bug report with detailed platform information to
+<nasm-bugs@lists.sourceforge.net> and we will try to help you asap!
+
+If everything went okay, type
+
+$ make
+
+to build nasm, ndisasm and rdoff tools
+or
+
+$ make everything
+
+to build the former plus the docs.
+
+You can decrease the size of produces executables by stripping off unnecessary information, to
+achieve this run
+
+$ make strip
+
+If you install to a system-wide location you might need to become root:
+$ su
+<enter root password>
+
+then
+
+$ make install
+
+optionally followed by 
+
+$ make install_rdf
+
+Or you can 
+
+$ make install_everything
+
+to install everything =)
+
+
+Thats it, enjoy!
+
+PS. Installation instructions for other platforms are underway.
+
diff --git a/License b/License
deleted file mode 100644 (file)
index c85c212..0000000
--- a/License
+++ /dev/null
@@ -1,119 +0,0 @@
-
-Terms and Conditions for the use of the Netwide Assembler
-=========================================================
-
-Can I have the gist without reading the legalese?
--------------------------------------------------
-
-Basically, NASM is free. You can't charge for it. You can copy it as
-much as you like. You can incorporate it, or bits of it, into other
-free programs if you want. (But we want to know about it if you do,
-and we want to be mentioned in the credits.) We may well allow you
-to incorporate it into commercial software too, but we'll probably
-demand some money for it, and we'll certainly demand to be given
-credit. And in extreme cases (although I can't immediately think of
-a reason we might actually want to do this) we may refuse to let you
-do it at all.
-
-NASM LICENCE AGREEMENT
-======================
-
-By "the Software" this licence refers to the complete contents of
-the NASM archive, excluding this licence document itself, and
-excluding the contents of the `test' directory. The Netwide
-Disassembler, NDISASM, is specifically included under this licence.
-
-I. The Software is freely redistributable; anyone may copy the
-Software, or parts of the Software, and give away as many copies as
-they like to anyone, as long as this licence document is kept with
-the Software. Charging a fee for the Software is prohibited,
-although a fee may be charged for the act of transferring a copy,
-and you can offer warranty protection and charge a fee for that.
-
-II. The Software, or parts thereof, may be incorporated into other
-freely redistributable software (by which we mean software that may
-be obtained free of charge) without requiring permission from the
-authors, as long as due credit is given to the authors of the
-Software in the resulting work, as long as the authors are informed
-of this action if possible, and as long as those parts of the
-Software that are used remain under this licence.
-
-III. Modified forms of the Software may be created and distributed
-as long as the authors are informed of this action if possible, as
-long as the resulting work remains under this licence, as long as
-the modified form of the Software is distributed with documentation
-which still gives credit to the original authors of the Software,
-and as long as the modified form of the Software is distributed with
-a clear statement that it is not the original form of the Software
-in the form that it was distributed by the authors.
-
-IV. The Software, or parts thereof, may be incorporated into other
-software which is not freely redistributable (i.e. software for
-which a fee is charged), as long as permission is granted from the
-authors of the Software. The authors reserve the right to grant this
-permission only for a fee, which may at our option take the form of
-royalty payments. The authors also reserve the right to refuse to
-grant permission if they deem it necessary. For further information
-about who exactly the authors are, see clause XI below.
-
-V. The Software may be incorporated, in its original archive form,
-into software collections or archives which are not freely
-redistributable, as long as it is clearly stated that the Software
-itself remains freely redistributable and remains under this licence
-and no other. Such collections are deemed not to fall under article
-IV of this licence.
-
-VI. Object files or programs generated by the Software as output do
-not fall under this licence at all, and may be placed under any
-licence the author wishes. The authors explicitly lay no claim to,
-and assert no rights over, any programs written by other people and
-assembled into object form by the Software.
-
-VII. You may not copy, modify or distribute the Software except
-under the terms given in this licence document. You may not
-sublicense the Software or in any way place it under any other
-licence than this one. Since you have not signed this licence, you
-are not of course required to accept it; however, no other licence
-applies to the Software, and nothing else grants you any permission
-to copy, modify, sublicense or distribute the Software in any way.
-These actions are therefore prohibited if you do not accept this
-licence.
-
-VIII. There is no warranty for the Software, to the extent permitted
-by applicable law. The authors provide the Software "as is" without
-warranty of any kind, either expressed or implied, including but not
-limited to the implied warranties of merchantability and fitness for
-a particular purpose. The entire risk as to the quality and
-performance of the Software is with you. Should the Software prove
-defective, you assume the cost of all necessary servicing, repair or
-correction.
-
-IX. In no event, unless required by applicable law or agreed to in
-writing, will any of the authors be liable to you for damages,
-including any general, special, incidental or consequential damages,
-arising out of the use or the inability to use the Software,
-including but not limited to loss of data or data being rendered
-inaccurate or a failure of the Software to operate with any other
-programs, even if you have been advised of the possibility of such
-damages.
-
-X. In addition to what this Licence otherwise provides, the Software
-may be distributed in such a way as to be compliant with the GNU
-General Public Licence, as published by the Free Software Foundation,
-Cambridge, MA, USA; version 2, or, at your option, any later version;
-incorporated herein by reference.  You must include a copy of this
-Licence with such distribution.  Furthermore, patches sent to the
-authors for the purpose of inclusion in the official release version
-are considered cleared for release under the full terms of this
-Licence.
-
-XI. The authors of NASM are the original authors (Simon Tatham and
-Julian Hall) and all those who the original authors feel have
-contributed significantly to the overall project.  If you wish to
-contact the authors, Julian Hall (jules@earthcorp.com) should be your
-first port of call.
-
-XII. Should any part of this agreement be deemed unenforcable, it is
-intended that the remainder of the agreement be held in force.
-
-END OF LICENCE AGREEMENT
diff --git a/MODIFIED b/MODIFIED
deleted file mode 100644 (file)
index eead729..0000000
--- a/MODIFIED
+++ /dev/null
@@ -1,224 +0,0 @@
-01/28/01 - fbk - added Stepane Denis' SSE2 instructions to a *working*
-           version of the code - some earlier versions were based on
-           broken code - sorry 'bout that. version "0.98.07"
-
-01/28/01 - fbk - cosmetic modifications to nasm.c, nasm.h,
-           AUTHORS, MODIFIED
-
-01/18/01 - fbk - "metalbrain"s jecxz bug fix in insns.dat
-           - alter nasmdoc.src to match - version "0.98.06f"
-
-01/09/01 - fbk - removed the "outforms.h" file - it appears to be
-           someone's old backup of "outform.h". version "0.98.06e" 
-
-01/09/01 - fbk - finally added the fix for the "multiple %includes bug",
-           known since 7/27/99 - reported originally (?) and sent to
-           us by Austin Lunnen - he reports that John Fine had a fix
-           within the day. Here it is...
-
----- Nelson Rush resigns from the group. Big thanks to Nelson for
-           his leadership and enthusiasm in getting these changes
-           incorporated into Nasm!
-
----- fbk - [list +], [list -] directives - ineptly implemented, should
-           be re-written or removed, perhaps.
-
----- Brian Raiter / fbk - "elfso bug" fix - applied to aoutb format
-           as well - testing might be desirable...
-
-08/07/00 - James Seter - -postfix, -prefix command line switches.
-
----- Yuri Zaporogets - rdoff utility changes.
-
-John Coffman's changes:
-For the JMP and other optimizations see the file README03.txt.
-
-Kendall Bennett's changes:
-For changes since the 0.98 release see the file scitech.txt. Note
-            that you must define "TASM_COMPAT" at compile-time
-            to get the Tasm Ideal Mode compatibility.
-
-----------------------------------------------
-... this is the 0.98 "modified" file ...
---------------------------------------------------
-This file details changes since NASM 0.98p3.  All the releases in this
-file have been produced by H. Peter Anvin <hpa@zytor.com>.
-
-For release 0.98:
-* The documentation comment delimiter is \# not #.
-* Allow EQU definitions to refer to external labels; reported by
-  Pedro Gimeno.
-* Re-enable support for RDOFF v1; reported by Pedro Gimeno.
-* Updated License file per OK from Simon and Julian.
-
-For release 0.98p9:
-* Update documentation (although the instruction set reference will
-  have to wait; I don't want to hold up the 0.98 release for it.)
-* Verified that the NASM implementation of the PEXTRW and PMOVMSKB
-  instructions is correct.  The encoding differs from what the Intel
-  manuals document, but the Pentium III behaviour matches NASM, not
-  the Intel manuals.
-* Fix handling of implicit sizes in PSHUFW and PINSRW, reported by
-  Stefan Hoffmeister.
-* Resurrect the -s option, which was removed when changing the
-  diagnostic output to stdout.
-
-For release 0.98p8:
-* Fix for "DB" when NASM is running on a bigendian machine.
-* Invoke insns.pl once for each output script, making Makefile.in
-  legal for "make -j".
-* Improve the Unix configure-based makefiles to make package
-  creation easier.
-* Included an RPM .spec file for building RPM (RedHat Package Manager)
-  packages on Linux or Unix systems.
-* Fix Makefile dependency problems.
-* Change src/rdsrc.pl to include sectioning information in info
-  output; required for install-info to work.
-* Updated the RDOFF distribution to version 2 from Jules; minor
-  massaging to make it compile in my environment.
-* Split doc files that can be built by anyone with a Perl interpreter off
-  into a separate archive.
-* "Dress rehearsal" release!
-
-For release 0.98p7:
-
-* Fixed opcodes with a third byte-sized immediate argument to not
-  complain if given "byte" on the immediate.
-* Allow %undef to remove single-line macros with arguments.  This
-  matches the behaviour of #undef in the C preprocessor.
-* Allow -d, -u, -i and -p to be specified as -D, -U, -I and -P for
-  compatibility with most C compilers and preprocessors.  This allows
-  Makefile options to be shared between cc and nasm, for example.
-* Minor cleanups.
-* Went through the list of Katmai instructions and hopefully fixed the
-  (rather few) mistakes in it.
-* (Hopefully) fixed a number of disassembler bugs related to ambiguous
-  instructions (disambiguated by -p) and SSE instructions with REP.
-* Fix for bug reported by Mark Junger: "call dword 0x12345678" should
-  work and may add an OSP (affected CALL, JMP, Jcc).
-* Fix for environments when "stderr" isn't a compile-time constant.
-
-For release 0.98p6:
-
-* Took officially over coordination of the 0.98 release; so drop
-  the p3.x notation. Skipped p4 and p5 to avoid confusion with John
-  Fine's J4 and J5 releases.
-* Update the documentation; however, it still doesn't include
-  documentation for the various new instructions.  I somehow wonder if
-  it makes sense to have an instruction set reference in the assembler
-  manual when Intel et al have PDF versions of their manuals online.
-* Recognize "idt" or "centaur" for the -p option to ndisasm.
-* Changed error messages back to stderr where they belong, but add an
-  -E option to redirect them elsewhere (the DOS shell cannot redirect
-  stderr.)
-* -M option to generate Makefile dependencies (based on code from Alex
-  Verstak.)
-* %undef preprocessor directive, and -u option, that undefines a
-  single-line macro.
-* OS/2 Makefile (Mkfiles/Makefile.os2) for Borland under OS/2; from
-  Chuck Crayne.
-* Various minor bugfixes (reported by):
-  - Dangling %s in preproc.c (Martin Junker)
-* THERE ARE KNOWN BUGS IN SSE AND THE OTHER KATMAI INSTRUCTIONS.  I am
-  on a trip and didn't bring the Katmai instruction reference, so I
-  can't work on them right now.
-* Updated the License file per agreement with Simon and Jules to
-  include a GPL distribution clause.
-
-For release 0.98p3.7:
-
-* (Hopefully) fixed the canned Makefiles to include the outrdf2 and
-  zoutieee modules.
-* Renamed changes.asm to changed.asm.
-
-For release 0.98p3.6:
-
-* Fixed a bunch of instructions that were added in 0.98p3.5 which had
-  memory operands, and the address-size prefix was missing from the
-  instruction pattern.
-
-For release 0.98p3.5:
-
-* Merged in changes from John S. Fine's 0.98-J5 release.  John's based
-  0.98-J5 on my 0.98p3.3 release; this merges the changes.
-* Expanded the instructions flag field to a long so we can fit more
-  flags; mark SSE (KNI) and AMD or Katmai-specific instructions as
-  such.
-* Fix the "PRIV" flag on a bunch of instructions, and create new
-  "PROT" flag for protected-mode-only instructions (orthogonal to if
-  the instruction is privileged!) and new "SMM" flag for SMM-only
-  instructions.
-* Added AMD-only SYSCALL and SYSRET instructions.
-* Make SSE actually work, and add new Katmai MMX instructions.
-* Added a -p (preferred vendor) option to ndisasm so that it can
-  distinguish e.g. Cyrix opcodes also used in SSE.  For example:
-
-       ndisasm -p cyrix aliased.bin
-       00000000  670F514310        paddsiw mm0,[ebx+0x10]
-       00000005  670F514320        paddsiw mm0,[ebx+0x20]
-       ndisasm -p intel aliased.bin
-       00000000  670F514310        sqrtps xmm0,[ebx+0x10]
-       00000005  670F514320        sqrtps xmm0,[ebx+0x20]
-* Added a bunch of Cyrix-specific instructions.
-
-For release 0.98p3.4:
-
-* Made at least an attempt to modify all the additional Makefiles (in
-  the Mkfiles directory).  I can't test it, but this was the best I
-  could do.
-* DOS DJGPP+"Opus Make" Makefile from John S. Fine.
-* changes.asm changes from John S. Fine.
-
-
-For release 0.98p3.3:
-
-* Patch from Conan Brink to allow nesting of %rep directives.
-* If we're going to allow INT01 as an alias for INT1/ICEBP (one of
-  Jules 0.98p3 changes), then we should allow INT03 as an alias for INT3
-  as well.
-* Updated changes.asm to include the latest changes.
-* Tried to clean up the <CR>s that had snuck in from a DOS/Windows
-  environment into my Unix environment, and try to make sure than
-  DOS/Windows users get them back.
-* We would silently generate broken tools if insns.dat wasn't sorted
-  properly.  Change insns.pl so that the order doesn't matter.
-* Fix bug in insns.pl (introduced by me) which would cause conditional
-  instructions to have an extra "cc" in disassembly, e.g. "jnz"
-  disassembled as "jccnz".
-
-
-For release 0.98p3.2:
-
-* Merged in John S. Fine's changes from his 0.98-J4 prerelease; see
-  http://www.csoft.net/cz/johnfine/
-* Changed previous "spotless" Makefile target (appropriate for distribution)
-  to "distclean", and added "cleaner" target which is same as "clean"
-  except deletes files generated by Perl scripts; "spotless" is union.
-* Removed BASIC programs from distribution.  Get a Perl interpreter
-  instead (see below.)
-* Calling this "pre-release 3.2" rather than "p3-hpa2" because of
-  John's contributions.
-* Actually link in the IEEE output format (zoutieee.c); fix a bunch of
-  compiler warnings in that file.  Note I don't know what IEEE output
-  is supposed to look like, so these changes were made "blind".
-
-
-For release 0.98p3-hpa:
-
-* Merged nasm098p3.zip with nasm-0.97.tar.gz to create a fully
-  buildable version for Unix systems (Makefile.in updates, etc.)
-* Changed insns.pl to create the instruction tables in nasm.h and
-  names.c, so that a new instruction can be added by adding it *only*
-  to insns.dat.
-* Added the following new instructions: SYSENTER, SYSEXIT, FXSAVE,
-  FXRSTOR, UD1, UD2 (the latter two are two opcodes that Intel
-  guarantee will never be used; one of them is documented as UD2 in
-  Intel documentation, the other one just as "Undefined Opcode" --
-  calling it UD1 seemed to make sense.)
-* MAX_SYMBOL was defined to be 9, but LOADALL286 and LOADALL386 are 10
-  characters long.  Now MAX_SYMBOL is derived from insns.dat.
-* A note on the BASIC programs included: forget them.  insns.bas is
-  already out of date.  Get yourself a Perl interpreter for your
-  platform of choice at:
-
-       http://www.cpan.org/ports/index.html
index fb1f3877e6dccf321007f681ea7610c200fc239d..6fabb205ae863e9b177a91c4ae0bb22ffae00955 100644 (file)
@@ -27,7 +27,7 @@ NROFF         = @NROFF@
 .SUFFIXES: .c .i .s .o .1 .man
 
 .PHONY: all doc rdf install clean distclean cleaner spotless install_rdf
-.PHONY: install_doc everything install_everything
+.PHONY: install_doc everything install_everything strip perlreq dist
 
 .c.o:
        $(CC) -c $(CFLAGS) -o $@ $<
@@ -42,8 +42,8 @@ NROFF         = @NROFF@
        $(NROFF) -man $< > $@
 
 NASM = nasm.o nasmlib.o float.o insnsa.o assemble.o labels.o \
-       parser.o outform.o outbin.o outaout.o outcoff.o outelf.o \
-       outobj.o outas86.o outrdf2.o outdbg.o zoutieee.o \
+       parser.o outform.o output/outbin.o output/outaout.o output/outcoff.o output/outelf.o \
+       output/outobj.o output/outas86.o output/outrdf2.o output/outdbg.o output/outieee.o \
        preproc.o listing.o eval.o
 
 NDISASM = ndisasm.o disasm.o sync.o nasmlib.o insnsd.o
@@ -69,19 +69,19 @@ nasm.o: nasm.c nasm.h insnsi.h nasmlib.h preproc.h parser.h assemble.h labels.h
  outform.h listing.h insns.h
 nasmlib.o: nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
 ndisasm.o: ndisasm.c nasm.h insnsi.h nasmlib.h sync.h disasm.h
-outaout.o: outaout.c nasm.h insnsi.h nasmlib.h outform.h
-outas86.o: outas86.c nasm.h insnsi.h nasmlib.h outform.h
-outbin.o: outbin.c nasm.h insnsi.h nasmlib.h outform.h
-outcoff.o: outcoff.c nasm.h insnsi.h nasmlib.h outform.h
-outdbg.o: outdbg.c nasm.h insnsi.h nasmlib.h outform.h
-outelf.o: outelf.c nasm.h insnsi.h nasmlib.h outform.h
+output/outaout.o: output/outaout.c nasm.h insnsi.h nasmlib.h outform.h
+output/outas86.o: output/outas86.c nasm.h insnsi.h nasmlib.h outform.h
+output/outbin.o: output/outbin.c nasm.h insnsi.h nasmlib.h outform.h
+output/outcoff.o: output/outcoff.c nasm.h insnsi.h nasmlib.h outform.h
+output/outdbg.o: output/outdbg.c nasm.h insnsi.h nasmlib.h outform.h
+output/outelf.o: output/outelf.c nasm.h insnsi.h nasmlib.h outform.h
 outform.o: outform.c outform.h nasm.h insnsi.h
-outobj.o: outobj.c nasm.h insnsi.h nasmlib.h outform.h
-outrdf2.o: outrdf2.c nasm.h insnsi.h nasmlib.h outform.h
+output/outobj.o: output/outobj.c nasm.h insnsi.h nasmlib.h outform.h
+output/outrdf2.o: output/outrdf2.c nasm.h insnsi.h nasmlib.h outform.h
+output/outieee.o: output/outieee.c nasm.h insnsi.h nasmlib.h outform.h
 parser.o: parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
 preproc.o: preproc.c nasm.h insnsi.h nasmlib.h macros.c
 sync.o: sync.c sync.h
-zoutieee.o: zoutieee.c nasm.h insnsi.h nasmlib.h outform.h
 
 # These source files are automagically generated from a single
 # instruction-table file by a Perl script. They're distributed,
@@ -104,6 +104,10 @@ insnsn.c: insns.dat insns.pl
 macros.c: standard.mac macros.pl
        perl $(srcdir)/macros.pl $(srcdir)/standard.mac
 
+# This target generates all files that require perl.
+# This allows easier generation of distribution (see dist target).
+perlreq: macros.c insnsa.c insnsd.c insnsi.h insnsn.c
+
 install: nasm ndisasm
        $(INSTALL_PROGRAM) nasm $(INSTALLROOT)$(bindir)/nasm
        $(INSTALL_PROGRAM) ndisasm $(INSTALLROOT)$(bindir)/ndisasm
@@ -124,6 +128,9 @@ cleaner: clean
 
 spotless: distclean cleaner
 
+strip:
+       strip --strip-unneeded nasm ndisasm
+
 rdf:
        cd rdoff && $(MAKE)
 
@@ -140,3 +147,7 @@ everything: all doc rdf
 
 install_everything: everything install install_doc install_rdf
 
+dist: spotless perlreq
+       autoconf
+       rm -rf ./autom4te.cache
+       tar cvjf ../nasm-`./nasm-version`-`date +%Y%m%d`.tar.bz2 ../`./nasm-dir`
index 3b92d0b4d2c787d6b8d442e46509fff288914a64..98dc6f8aac78d58f43b0ea85866cb4114d8a2c11 100644 (file)
@@ -80,10 +80,10 @@ SUFFIX= w#       # by default, this makefile produces nasmw.exe and ndisasmw.exe
 
 
 NASMOBJS = nasm.$(OBJ) nasmlib.$(OBJ) float.$(OBJ) insnsa.$(OBJ) \
-          assemble.$(OBJ) labels.$(OBJ) parser.$(OBJ) outform.$(OBJ) \
-                 outbin.$(OBJ) outaout.$(OBJ) outcoff.$(OBJ) outelf.$(OBJ) \
-                 outobj.$(OBJ) outas86.$(OBJ) outrdf.$(OBJ) outdbg.$(OBJ) \
-                  outrdf2.$(OBJ) zoutieee.$(OBJ) \
+            assemble.$(OBJ) labels.$(OBJ) parser.$(OBJ) outform.$(OBJ) \
+                 output/outbin.$(OBJ) output/outaout.$(OBJ) output/outcoff.$(OBJ) output/outelf.$(OBJ) \
+                 output/outobj.$(OBJ) output/outas86.$(OBJ) output/outrdf.$(OBJ) output/outdbg.$(OBJ) \
+        output/outrdf2.$(OBJ) output/outieee.$(OBJ) \
                  preproc.$(OBJ) listing.$(OBJ) eval.$(OBJ)
 
 NDISASMOBJS = ndisasm.$(OBJ) disasm.$(OBJ) sync.$(OBJ) nasmlib.$(OBJ) \
@@ -126,15 +126,15 @@ nasm.$(OBJ): nasm.c nasm.h insnsi.h nasmlib.h parser.h assemble.h labels.h \
              listing.h outform.h
 nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
 ndisasm.$(OBJ): ndisasm.c nasm.h insnsi.h sync.h disasm.h
-outas86.$(OBJ): outas86.c nasm.h insnsi.h nasmlib.h
-outaout.$(OBJ): outaout.c nasm.h insnsi.h nasmlib.h
-outbin.$(OBJ): outbin.c nasm.h insnsi.h nasmlib.h
-outcoff.$(OBJ): outcoff.c nasm.h insnsi.h nasmlib.h
-outdbg.$(OBJ): outdbg.c nasm.h insnsi.h nasmlib.h
-outelf.$(OBJ): outelf.c nasm.h insnsi.h nasmlib.h
-outobj.$(OBJ): outobj.c nasm.h insnsi.h nasmlib.h
-outrdf2.$(OBJ): outrdf2.c nasm.h insnsi.h nasmlib.h
-zoutieee.$(OBJ): zoutieee.c nasm.h insnsi.h nasmlib.h
+output/outas86.$(OBJ): output/outas86.c nasm.h insnsi.h nasmlib.h
+output/outaout.$(OBJ): output/outaout.c nasm.h insnsi.h nasmlib.h
+output/outbin.$(OBJ): output/outbin.c nasm.h insnsi.h nasmlib.h
+output/outcoff.$(OBJ): output/outcoff.c nasm.h insnsi.h nasmlib.h
+output/outdbg.$(OBJ): output/outdbg.c nasm.h insnsi.h nasmlib.h
+output/outelf.$(OBJ): output/outelf.c nasm.h insnsi.h nasmlib.h
+output/outobj.$(OBJ): output/outobj.c nasm.h insnsi.h nasmlib.h
+output/outrdf2.$(OBJ): output/outrdf2.c nasm.h insnsi.h nasmlib.h
+output/outieee.$(OBJ): output/outieee.c nasm.h insnsi.h nasmlib.h
 outform.$(OBJ): outform.c outform.h nasm.h insnsi.h
 parser.$(OBJ): parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
 preproc.$(OBJ): preproc.c macros.c preproc.h nasm.h insnsi.h nasmlib.h
index a6a31ee3aeb3fbf25b7760c5562a8bb459191aab..49f10d3718b5edeaac8c603a928e369bccd76cbd 100644 (file)
@@ -109,7 +109,7 @@ NDISASMOBJS = $(OBJD)ndisasm.$(OBJ)  $(OBJD)disasm.$(OBJ) $(OBJD)sync.$(OBJ) \
 OUTOBJ= $(OBJD)outbin.$(OBJ) $(OBJD)outaout.$(OBJ) $(OBJD)outcoff.$(OBJ) \
         $(OBJD)outelf.$(OBJ) $(OBJD)outobj.$(OBJ)  $(OBJD)outas86.$(OBJ) \
         $(OBJD)outrdf.$(OBJ) $(OBJD)outdbg.$(OBJ)  $(OBJD)outrdf2.$(OBJ) \
-       $(OBJD)zoutieee.$(OBJ)
+       $(OBJD)outieee.$(OBJ)
 
 
 ################################################################
@@ -201,31 +201,31 @@ $(OBJD)nasmlibd.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h
 ################################################################
 # Dependencies for all of the output format's OBJ files
 
-$(OBJD)outas86.$(OBJ): outas86.c nasm.h insnsi.h nasmlib.h
+$(OBJD)outas86.$(OBJ): output/outas86.c nasm.h insnsi.h nasmlib.h
         $(NASM_ASM)
 
-$(OBJD)outaout.$(OBJ): outaout.c nasm.h insnsi.h nasmlib.h
+$(OBJD)outaout.$(OBJ): output/outaout.c nasm.h insnsi.h nasmlib.h
         $(NASM_ASM)
 
-$(OBJD)outbin.$(OBJ): outbin.c nasm.h insnsi.h nasmlib.h
+$(OBJD)outbin.$(OBJ): output/outbin.c nasm.h insnsi.h nasmlib.h
         $(NASM_ASM)
 
-$(OBJD)outcoff.$(OBJ): outcoff.c nasm.h insnsi.h nasmlib.h
+$(OBJD)outcoff.$(OBJ): output/outcoff.c nasm.h insnsi.h nasmlib.h
         $(NASM_ASM)
 
-$(OBJD)outdbg.$(OBJ): outdbg.c nasm.h insnsi.h nasmlib.h
+$(OBJD)outdbg.$(OBJ): output/outdbg.c nasm.h insnsi.h nasmlib.h
         $(NASM_ASM)
 
-$(OBJD)outelf.$(OBJ): outelf.c nasm.h insnsi.h nasmlib.h
+$(OBJD)outelf.$(OBJ): output/outelf.c nasm.h insnsi.h nasmlib.h
         $(NASM_ASM)
 
-$(OBJD)outobj.$(OBJ): outobj.c nasm.h insnsi.h nasmlib.h
+$(OBJD)outobj.$(OBJ): output/outobj.c nasm.h insnsi.h nasmlib.h
         $(NASM_ASM)
 
-$(OBJD)outrdf2.$(OBJ): outrdf2.c nasm.h insnsi.h nasmlib.h
+$(OBJD)outrdf2.$(OBJ): output/outrdf2.c nasm.h insnsi.h nasmlib.h
         $(NASM_ASM)
 
-$(OBJD)zoutieee.$(OBJ): zoutieee.c nasm.h insnsi.h nasmlib.h
+$(OBJD)outieee.$(OBJ): output/outieee.c nasm.h insnsi.h nasmlib.h
         $(NASM_ASM)
 
 $(OBJD)outform.$(OBJ): outform.c outform.h nasm.h insnsi.h
index eeb59cd2aa86e7c207a0153627aff35be958befd..49d3355d76ecc09737930958b28979e1de0a9ba5 100644 (file)
@@ -25,9 +25,9 @@ OBJ = obj#
 
 NASMOBJS1 = nasm.$(OBJ) nasmlib.$(OBJ) float.$(OBJ) insnsa.$(OBJ)
 NASMOBJS2 = assemble.$(OBJ) labels.$(OBJ) parser.$(OBJ) outform.$(OBJ)
-NASMOBJS3 = outbin.$(OBJ) outaout.$(OBJ) outcoff.$(OBJ) outelf.$(OBJ)
-NASMOBJS4 = outobj.$(OBJ) outas86.$(OBJ) outdbg.$(OBJ) outrdf.$(OBJ)
-NASMOBJS5 = outrdf2.$(OBJ) zoutieee.$(OBJ)
+NASMOBJS3 = output/outbin.$(OBJ) output/outaout.$(OBJ) output/outcoff.$(OBJ) output/outelf.$(OBJ)
+NASMOBJS4 = output/outobj.$(OBJ) output/outas86.$(OBJ) output/outdbg.$(OBJ) output/outrdf.$(OBJ)
+NASMOBJS5 = output/outrdf2.$(OBJ) output/outieee.$(OBJ)
 NASMOBJS6 = preproc.$(OBJ) listing.$(OBJ) eval.$(OBJ)
 
 NASMOBJS = $(NASMOBJS1) $(NASMOBJS2) $(NASMOBJS3) $(NASMOBJS4) $(NASMOBJS5) \
@@ -65,15 +65,15 @@ nasm.$(OBJ): nasm.c nasm.h insnsi.h nasmlib.h parser.h assemble.h labels.h \
              listing.h outform.h
 nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
 ndisasm.$(OBJ): ndisasm.c nasm.h insnsi.h sync.h disasm.h
-outas86.$(OBJ): outas86.c nasm.h insnsi.h nasmlib.h
-outaout.$(OBJ): outaout.c nasm.h insnsi.h nasmlib.h
-outbin.$(OBJ): outbin.c nasm.h insnsi.h nasmlib.h
-outcoff.$(OBJ): outcoff.c nasm.h insnsi.h nasmlib.h
-outdbg.$(OBJ): outdbg.c nasm.h insnsi.h nasmlib.h
-outelf.$(OBJ): outelf.c nasm.h insnsi.h nasmlib.h
-outobj.$(OBJ): outobj.c nasm.h insnsi.h nasmlib.h
-outrdf2.$(OBJ): outrdf2.c nasm.h insnsi.h nasmlib.h
-zoutieee.$(OBJ): zoutieee.c nasm.h insnsi.h nasmlib.h
+output/outas86.$(OBJ): output/outas86.c nasm.h insnsi.h nasmlib.h
+output/outaout.$(OBJ): output/outaout.c nasm.h insnsi.h nasmlib.h
+output/outbin.$(OBJ): output/outbin.c nasm.h insnsi.h nasmlib.h
+output/outcoff.$(OBJ): output/outcoff.c nasm.h insnsi.h nasmlib.h
+output/outdbg.$(OBJ): output/outdbg.c nasm.h insnsi.h nasmlib.h
+output/outelf.$(OBJ): output/outelf.c nasm.h insnsi.h nasmlib.h
+output/outobj.$(OBJ): output/outobj.c nasm.h insnsi.h nasmlib.h
+output/outrdf2.$(OBJ): output/outrdf2.c nasm.h insnsi.h nasmlib.h
+output/outieee.$(OBJ): output/outieee.c nasm.h insnsi.h nasmlib.h
 outform.$(OBJ): outform.c outform.h nasm.h insnsi.h
 parser.$(OBJ): parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
 preproc.$(OBJ): preproc.c macros.c preproc.h nasm.h insnsi.h nasmlib.h
index abfe2b2b30c255039afa5460982d30fb1ec0111b..afa3d033751803d6f4173eb12dfc488e3d02ce49 100644 (file)
@@ -22,9 +22,9 @@ CFLAGS = -O2 -I.
        $(CC) -c $(CFLAGS) $*.c
 
 NASM = nasm.o nasmlib.o float.o insnsa.o assemble.o labels.o \
-       parser.o outform.o outbin.o outaout.o outcoff.o outelf.o \
-       outobj.o outas86.o outrdf.o outdbg.o preproc.o listing.o \
-       eval.o outrdf2.o zoutieee.o
+       parser.o outform.o output/outbin.o output/outaout.o output/outcoff.o output/outelf.o \
+       output/outobj.o output/outas86.o output/outrdf.o output/outdbg.o preproc.o listing.o \
+       eval.o output/outrdf2.o output/outieee.o
 
 NDISASM = ndisasm.o disasm.o sync.o nasmlib.o insnsd.o
 
@@ -48,16 +48,16 @@ nasm.o: nasm.c nasm.h insnsi.h nasmlib.h preproc.h parser.h assemble.h labels.h
  outform.h listing.h
 nasmlib.o: nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
 ndisasm.o: ndisasm.c nasm.h insnsi.h nasmlib.h sync.h disasm.h
-outaout.o: outaout.c nasm.h insnsi.h nasmlib.h outform.h
-outas86.o: outas86.c nasm.h insnsi.h nasmlib.h outform.h
-outbin.o: outbin.c nasm.h insnsi.h nasmlib.h outform.h
-outcoff.o: outcoff.c nasm.h insnsi.h nasmlib.h outform.h
-outdbg.o: outdbg.c nasm.h insnsi.h nasmlib.h outform.h
-outelf.o: outelf.c nasm.h insnsi.h nasmlib.h outform.h
+output/outaout.o: output/outaout.c nasm.h insnsi.h nasmlib.h outform.h
+output/outas86.o: output/outas86.c nasm.h insnsi.h nasmlib.h outform.h
+output/outbin.o: output/outbin.c nasm.h insnsi.h nasmlib.h outform.h
+output/outcoff.o: output/outcoff.c nasm.h insnsi.h nasmlib.h outform.h
+output/outdbg.o: output/outdbg.c nasm.h insnsi.h nasmlib.h outform.h
+output/outelf.o: output/outelf.c nasm.h insnsi.h nasmlib.h outform.h
 outform.o: outform.c outform.h nasm.h insnsi.h
-outobj.o: outobj.c nasm.h insnsi.h nasmlib.h outform.h
-outrdf2.o: outrdf2.c nasm.h insnsi.h nasmlib.h outform.h
-zoutieee.o: zoutieee.c nasm.h insnsi.h nasmlib.h outform.h
+output/outobj.o: output/outobj.c nasm.h insnsi.h nasmlib.h outform.h
+output/outrdf2.o: output/outrdf2.c nasm.h insnsi.h nasmlib.h outform.h
+output/outieee.o: output/outieee.c nasm.h insnsi.h nasmlib.h outform.h
 parser.o: parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
 preproc.o: preproc.c nasm.h insnsi.h nasmlib.h macros.c
 sync.o: sync.c sync.h
index 1b529c376d801e8862974cd72e5e4b8ef3b81179..5206f1affd5b7f697e6bfc8d376371ee48df43b1 100644 (file)
@@ -40,18 +40,18 @@ CFLAGS = -O3
        tcc -O -Z -c -ml -d -DOF_ONLY -DOF_BIN -DOF_OBJ -If:\public\turboc -I. $*.c >$*.err
 
 NASM = nasm.o nasmlib.o float.o insnsa.o assemble.o labels.o \
-       parser.o outform.o outbin.o outaout.o outcoff.o outelf.o \
-       outobj.o outas86.o outrdf.o outrdf2.o zoutieee.o outdbg.o preproc.o listing.o \
+       parser.o outform.o output/outbin.o output/outaout.o output/outcoff.o output/outelf.o \
+       output/outobj.o output/outas86.o output/outrdf.o output/outrdf2.o output/outieee.o output/outdbg.o preproc.o listing.o \
        eval.o
 
 NASML = nasm.ol nasmlib.ol float.ol insnsa.ol assemble.ol labels.ol \
-       parser.ol outform.ol outbin.ol outaout.ol outcoff.ol outelf.ol \
-       outobj.ol outas86.ol outrdf.ol outrdf2.ol zoutieee.ol outdbg.ol preproc.ol listing.ol \
+       parser.ol outform.ol output/outbin.ol output/outaout.ol output/outcoff.ol output/outelf.ol \
+       output/outobj.ol output/outas86.ol output/outrdf.ol output/outrdf2.ol output/outieee.ol output/outdbg.ol preproc.ol listing.ol \
        eval.ol
 
 NASM16 = nasm.obj nasmlib.obj float.obj insnsa.obj assemble.obj labels.obj \
-       parser.obj outform.obj outbin.obj \
-       outobj.obj preproc.obj listing.obj \
+       parser.obj outform.obj output/outbin.obj \
+       output/outobj.obj preproc.obj listing.obj \
        eval.obj
 
 NDISASM = ndisasm.o disasm.o sync.o nasmlib.o insnsd.o
@@ -99,19 +99,19 @@ nasm.o: nasm.c nasm.h insnsi.h nasmlib.h preproc.h parser.h assemble.h labels.h
  outform.h listing.h
 nasmlib.o: nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
 ndisasm.o: ndisasm.c nasm.h insnsi.h nasmlib.h sync.h disasm.h
-outaout.o: outaout.c nasm.h insnsi.h nasmlib.h outform.h
-outas86.o: outas86.c nasm.h insnsi.h nasmlib.h outform.h
-outbin.o: outbin.c nasm.h insnsi.h nasmlib.h outform.h
-outcoff.o: outcoff.c nasm.h insnsi.h nasmlib.h outform.h
-outdbg.o: outdbg.c nasm.h insnsi.h nasmlib.h outform.h
-outelf.o: outelf.c nasm.h insnsi.h nasmlib.h outform.h
+output/outaout.o: output/outaout.c nasm.h insnsi.h nasmlib.h outform.h
+output/outas86.o: output/outas86.c nasm.h insnsi.h nasmlib.h outform.h
+output/outbin.o: output/outbin.c nasm.h insnsi.h nasmlib.h outform.h
+output/outcoff.o: output/outcoff.c nasm.h insnsi.h nasmlib.h outform.h
+output/outdbg.o: output/outdbg.c nasm.h insnsi.h nasmlib.h outform.h
+output/outelf.o: output/outelf.c nasm.h insnsi.h nasmlib.h outform.h
 outform.o: outform.c outform.h nasm.h insnsi.h
-outobj.o: outobj.c nasm.h insnsi.h nasmlib.h outform.h
-outrdf2.o: outrdf2.c nasm.h insnsi.h nasmlib.h outform.h
+output/outobj.o: output/outobj.c nasm.h insnsi.h nasmlib.h outform.h
+output/outrdf2.o: output/outrdf2.c nasm.h insnsi.h nasmlib.h outform.h
 parser.o: parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
 preproc.o: preproc.c nasm.h insnsi.h nasmlib.h macros.c
 sync.o: sync.c sync.h
-zoutieee.o: zoutieee.c nasm.h insnsi.h nasmlib.h outform.h
+output/outieee.o: output/outieee.c nasm.h insnsi.h nasmlib.h outform.h
 
 assemble.ol: assemble.c nasm.h insnsi.h nasmlib.h assemble.h insns.h
 disasm.ol: disasm.c nasm.h insnsi.h disasm.h sync.h insns.h names.c insnsn.c
@@ -125,19 +125,19 @@ nasm.ol: nasm.c nasm.h insnsi.h nasmlib.h preproc.h parser.h assemble.h labels.h
  outform.h listing.h
 nasmlib.ol: nasmlib.c nasm.h insnsi.h nasmlib.h
 ndisasm.ol: ndisasm.c nasm.h insnsi.h nasmlib.h sync.h disasm.h
-outaout.ol: outaout.c nasm.h insnsi.h nasmlib.h outform.h
-outas86.ol: outas86.c nasm.h insnsi.h nasmlib.h outform.h
-outbin.ol: outbin.c nasm.h insnsi.h nasmlib.h outform.h
-outcoff.ol: outcoff.c nasm.h insnsi.h nasmlib.h outform.h
-outdbg.ol: outdbg.c nasm.h insnsi.h nasmlib.h outform.h
-outelf.ol: outelf.c nasm.h insnsi.h nasmlib.h outform.h
+output/outaout.ol: output/outaout.c nasm.h insnsi.h nasmlib.h outform.h
+output/outas86.ol: output/outas86.c nasm.h insnsi.h nasmlib.h outform.h
+output/outbin.ol: output/outbin.c nasm.h insnsi.h nasmlib.h outform.h
+output/outcoff.ol: output/outcoff.c nasm.h insnsi.h nasmlib.h outform.h
+output/outdbg.ol: output/outdbg.c nasm.h insnsi.h nasmlib.h outform.h
+output/outelf.ol: output/outelf.c nasm.h insnsi.h nasmlib.h outform.h
 outform.ol: outform.c outform.h nasm.h insnsi.h
-outobj.ol: outobj.c nasm.h insnsi.h nasmlib.h outform.h
-outrdf2.ol: outrdf2.c nasm.h insnsi.h nasmlib.h outform.h
+output/outobj.ol: output/outobj.c nasm.h insnsi.h nasmlib.h outform.h
+output/outrdf2.ol: output/outrdf2.c nasm.h insnsi.h nasmlib.h outform.h
 parser.ol: parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
 preproc.ol: preproc.c nasm.h insnsi.h nasmlib.h macros.c
 sync.ol: sync.c sync.h
-zoutieee.ol: zoutieee.c nasm.h insnsi.h nasmlib.h outform.h
+output/outieee.ol: output/outieee.c nasm.h insnsi.h nasmlib.h outform.h
 
 assemble.obj: assemble.c nasm.h insnsi.h nasmlib.h assemble.h insns.h
 disasm.obj: disasm.c nasm.h insnsi.h disasm.h sync.h insns.h names.c insnsn.c
@@ -151,19 +151,19 @@ nasm.obj: nasm.c nasm.h insnsi.h nasmlib.h preproc.h parser.h assemble.h labels.
  outform.h listing.h
 nasmlib.obj: nasmlib.c nasm.h insnsi.h nasmlib.h
 ndisasm.obj: ndisasm.c nasm.h insnsi.h nasmlib.h sync.h disasm.h
-outaout.obj: outaout.c nasm.h insnsi.h nasmlib.h outform.h
-outas86.obj: outas86.c nasm.h insnsi.h nasmlib.h outform.h
-outbin.obj: outbin.c nasm.h insnsi.h nasmlib.h outform.h
-outcoff.obj: outcoff.c nasm.h insnsi.h nasmlib.h outform.h
-outdbg.obj: outdbg.c nasm.h insnsi.h nasmlib.h outform.h
-outelf.obj: outelf.c nasm.h insnsi.h nasmlib.h outform.h
+output/outaout.obj: output/outaout.c nasm.h insnsi.h nasmlib.h outform.h
+output/outas86.obj: output/outas86.c nasm.h insnsi.h nasmlib.h outform.h
+output/outbin.obj: output/outbin.c nasm.h insnsi.h nasmlib.h outform.h
+output/outcoff.obj: output/outcoff.c nasm.h insnsi.h nasmlib.h outform.h
+output/outdbg.obj: output/outdbg.c nasm.h insnsi.h nasmlib.h outform.h
+output/outelf.obj: output/outelf.c nasm.h insnsi.h nasmlib.h outform.h
 outform.obj: outform.c outform.h nasm.h insnsi.h
-outobj.obj: outobj.c nasm.h insnsi.h nasmlib.h outform.h
-outrdf2.obj: outrdf2.c nasm.h insnsi.h nasmlib.h outform.h
+output/outobj.obj: output/outobj.c nasm.h insnsi.h nasmlib.h outform.h
+output/outrdf2.obj: output/outrdf2.c nasm.h insnsi.h nasmlib.h outform.h
 parser.obj: parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
 preproc.obj: preproc.c nasm.h insnsi.h nasmlib.h macros.c
 sync.obj: sync.c sync.h
-zoutieee.obj: zoutieee.c nasm.h insnsi.h nasmlib.h outform.h
+output/outieee.obj: output/outieee.c nasm.h insnsi.h nasmlib.h outform.h
 
 # These four source files are automagically generated from a single
 # instruction-table file by a Perl script. They're distributed,
index aadc7bc6dd98200fb0e3a509030248676be26e07..a13d19dd539ba4d0f1cd2b52d8f0d04b94cdbe83 100644 (file)
@@ -21,9 +21,9 @@ NDISASMOBJS = ndisasm.$(OBJ) disasm.$(OBJ) sync.$(OBJ) nasmlib.$(OBJ) \
 
 NASMOBJS = nasm.$(OBJ) nasmlib.$(OBJ) eval.$(OBJ) float.$(OBJ) insnsa.$(OBJ) \
            assemble.$(OBJ) labels.$(OBJ) parser.$(OBJ) outform.$(OBJ) \
-          outbin.$(OBJ) outaout.$(OBJ) outcoff.$(OBJ) outelf.$(OBJ) \
-          outobj.$(OBJ) outas86.$(OBJ) outrdf.$(OBJ) outrdf2.$(OBJ) outdbg.$(OBJ) \
-           preproc.$(OBJ) listing.$(OBJ) zoutieee.$(OBJ)
+          output/outbin.$(OBJ) output/outaout.$(OBJ) output/outcoff.$(OBJ) output/outelf.$(OBJ) \
+          output/outobj.$(OBJ) output/outas86.$(OBJ) output/outrdf.$(OBJ) output/outrdf2.$(OBJ) output/outdbg.$(OBJ) \
+           preproc.$(OBJ) listing.$(OBJ) output/outieee.$(OBJ)
 
 all : nasm.exe ndisasm.exe
 
index 6b87d1f6076bef316b24fcd8813ad2d2f2b62f01..b6574f87f9f40cfda7687f8dc2af5264c6c8bb63 100644 (file)
@@ -23,9 +23,9 @@ OBJ = obj#
 
 NASMOBJS = nasm.$(OBJ) nasmlib.$(OBJ) float.$(OBJ) insnsa.$(OBJ) \
            assemble.$(OBJ) labels.$(OBJ) parser.$(OBJ) outform.$(OBJ) \
-          outbin.$(OBJ) outaout.$(OBJ) outcoff.$(OBJ) outelf.$(OBJ) \
-          outobj.$(OBJ) outas86.$(OBJ) outrdf.$(OBJ) outrdf2.$(OBJ) \
-          zoutieee.$(OBJ) outdbg.$(OBJ) preproc.$(OBJ) listing.$(OBJ) \
+          output/outbin.$(OBJ) output/outaout.$(OBJ) output/outcoff.$(OBJ) output/outelf.$(OBJ) \
+          output/outobj.$(OBJ) output/outas86.$(OBJ) output/outrdf.$(OBJ) output/outrdf2.$(OBJ) \
+          output/outieee.$(OBJ) output/outdbg.$(OBJ) preproc.$(OBJ) listing.$(OBJ) \
           eval.$(OBJ)
 
 NDISASMOBJS = ndisasm.$(OBJ) disasm.$(OBJ) sync.$(OBJ) nasmlib.$(OBJ) \
@@ -52,15 +52,15 @@ nasm.$(OBJ): nasm.c nasm.h insnsi.h nasmlib.h parser.h assemble.h labels.h \
        listing.h outform.h
 nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
 ndisasm.$(OBJ): ndisasm.c nasm.h insnsi.h sync.h disasm.h
-outas86.$(OBJ): outas86.c nasm.h insnsi.h nasmlib.h
-outaout.$(OBJ): outaout.c nasm.h insnsi.h nasmlib.h
-outbin.$(OBJ): outbin.c nasm.h insnsi.h nasmlib.h
-outcoff.$(OBJ): outcoff.c nasm.h insnsi.h nasmlib.h
-outdbg.$(OBJ): outdbg.c nasm.h insnsi.h nasmlib.h
-outelf.$(OBJ): outelf.c nasm.h insnsi.h nasmlib.h
-outobj.$(OBJ): outobj.c nasm.h insnsi.h nasmlib.h
-outrdf2.$(OBJ): outrdf2.c nasm.h insnsi.h nasmlib.h
-zoutieee.$(OBJ): zoutieee.c nasm.h insnsi.h nasmlib.h
+output/outas86.$(OBJ): output/outas86.c nasm.h insnsi.h nasmlib.h
+output/outaout.$(OBJ): output/outaout.c nasm.h insnsi.h nasmlib.h
+output/outbin.$(OBJ): output/outbin.c nasm.h insnsi.h nasmlib.h
+output/outcoff.$(OBJ): output/outcoff.c nasm.h insnsi.h nasmlib.h
+output/outdbg.$(OBJ): output/outdbg.c nasm.h insnsi.h nasmlib.h
+output/outelf.$(OBJ): output/outelf.c nasm.h insnsi.h nasmlib.h
+output/outobj.$(OBJ): output/outobj.c nasm.h insnsi.h nasmlib.h
+output/outrdf2.$(OBJ): output/outrdf2.c nasm.h insnsi.h nasmlib.h
+output/outieee.$(OBJ): output/outieee.c nasm.h insnsi.h nasmlib.h
 outform.$(OBJ): outform.c outform.h nasm.h insnsi.h
 parser.$(OBJ): parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
 preproc.$(OBJ): preproc.c macros.c preproc.h nasm.h insnsi.h nasmlib.h
index 9d532654f28eb4f6561dbc4a4cb50c4aecad39df..26264a9377e584e02a045185b3a88f1ddf709abc 100644 (file)
@@ -44,8 +44,8 @@ NROFF         = echo
        $(NROFF) -man $< > $@
 
 NASM = nasm.o nasmlib.o float.o insnsa.o assemble.o labels.o \
-       parser.o outform.o outbin.o outaout.o outcoff.o outelf.o \
-       outobj.o outas86.o outrdf.o outrdf2.o outdbg.o zoutieee.o \
+       parser.o outform.o output/outbin.o output/outaout.o output/outcoff.o output/outelf.o \
+       output/outobj.o output/outas86.o output/outrdf.o output/outrdf2.o output/outdbg.o output/outieee.o \
        preproc.o listing.o eval.o
 
 NDISASM = ndisasm.o disasm.o sync.o nasmlib.o insnsd.o
@@ -71,19 +71,19 @@ nasm.o: nasm.c nasm.h insnsi.h nasmlib.h preproc.h parser.h assemble.h labels.h
  outform.h listing.h
 nasmlib.o: nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
 ndisasm.o: ndisasm.c nasm.h insnsi.h nasmlib.h sync.h disasm.h
-outaout.o: outaout.c nasm.h insnsi.h nasmlib.h outform.h
-outas86.o: outas86.c nasm.h insnsi.h nasmlib.h outform.h
-outbin.o: outbin.c nasm.h insnsi.h nasmlib.h outform.h
-outcoff.o: outcoff.c nasm.h insnsi.h nasmlib.h outform.h
-outdbg.o: outdbg.c nasm.h insnsi.h nasmlib.h outform.h
-outelf.o: outelf.c nasm.h insnsi.h nasmlib.h outform.h
+output/outaout.o: output/outaout.c nasm.h insnsi.h nasmlib.h outform.h
+output/outas86.o: output/outas86.c nasm.h insnsi.h nasmlib.h outform.h
+output/outbin.o: output/outbin.c nasm.h insnsi.h nasmlib.h outform.h
+output/outcoff.o: output/outcoff.c nasm.h insnsi.h nasmlib.h outform.h
+output/outdbg.o: output/outdbg.c nasm.h insnsi.h nasmlib.h outform.h
+output/outelf.o: output/outelf.c nasm.h insnsi.h nasmlib.h outform.h
 outform.o: outform.c outform.h nasm.h insnsi.h
-outobj.o: outobj.c nasm.h insnsi.h nasmlib.h outform.h
-outrdf2.o: outrdf2.c nasm.h insnsi.h nasmlib.h outform.h
+output/outobj.o: output/outobj.c nasm.h insnsi.h nasmlib.h outform.h
+output/outrdf2.o: output/outrdf2.c nasm.h insnsi.h nasmlib.h outform.h
 parser.o: parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
 preproc.o: preproc.c nasm.h insnsi.h nasmlib.h macros.c
 sync.o: sync.c sync.h
-zoutieee.o: zoutieee.c nasm.h insnsi.h nasmlib.h outform.h
+output/outieee.o: output/outieee.c nasm.h insnsi.h nasmlib.h outform.h
 
 # These source files are automagically generated from a single
 # instruction-table file by a Perl script. They're distributed,
index c5bbec732a0a2392a03a5bc9d4e4ca023a49012f..9c6a937849c8474993297cf139c8166511cdf0c4 100644 (file)
@@ -22,9 +22,9 @@ OBJ = obj
         $(CC) -o $@ $*.c
 
 NASM = nasm.${OBJ} nasmlib.${OBJ} float.${OBJ} insnsa.${OBJ} assemble.${OBJ} labels.${OBJ} \
-       parser.${OBJ} outform.${OBJ} outbin.${OBJ} outaout.${OBJ} outcoff.${OBJ} outelf.${OBJ} \
-       outobj.${OBJ} outas86.${OBJ} outrdf.${OBJ} outdbg.${OBJ} outrdf2.${OBJ} \
-       zoutieee.${OBJ} preproc.${OBJ} listing.${OBJ} eval.${OBJ}
+       parser.${OBJ} outform.${OBJ} output/outbin.${OBJ} output/outaout.${OBJ} output/outcoff.${OBJ} output/outelf.${OBJ} \
+       output/outobj.${OBJ} output/outas86.${OBJ} output/outrdf.${OBJ} output/outdbg.${OBJ} output/outrdf2.${OBJ} \
+       output/outieee.${OBJ} preproc.${OBJ} listing.${OBJ} eval.${OBJ}
 
 NDISASM = ndisasm.${OBJ} disasm.${OBJ} sync.${OBJ} nasmlib.${OBJ} insnsd.${OBJ}
 
@@ -44,16 +44,16 @@ NASM.LNK: makefile.lcc
         echo parser.$(OBJ) >> NASM.LNK
         echo preproc.$(OBJ) >> NASM.LNK
         echo outform.$(OBJ) >> NASM.LNK
-        echo outbin.$(OBJ) >> NASM.LNK
-        echo outaout.$(OBJ) >> NASM.LNK
-        echo outcoff.$(OBJ) >> NASM.LNK
-        echo outelf.$(OBJ) >> NASM.LNK
-        echo outobj.$(OBJ) >> NASM.LNK
-        echo outas86.$(OBJ) >> NASM.LNK
-        echo outrdf.$(OBJ) >> NASM.LNK
-        echo outrdf2.$(OBJ) >> NASM.LNK
-        echo zoutieee.$(OBJ) >> NASM.LNK
-        echo outdbg.$(OBJ) >> NASM.LNK
+        echo output/outbin.$(OBJ) >> NASM.LNK
+        echo output/outaout.$(OBJ) >> NASM.LNK
+        echo output/outcoff.$(OBJ) >> NASM.LNK
+        echo output/outelf.$(OBJ) >> NASM.LNK
+        echo output/outobj.$(OBJ) >> NASM.LNK
+        echo output/outas86.$(OBJ) >> NASM.LNK
+        echo output/outrdf.$(OBJ) >> NASM.LNK
+        echo output/outrdf2.$(OBJ) >> NASM.LNK
+        echo output/outieee.$(OBJ) >> NASM.LNK
+        echo output/outdbg.$(OBJ) >> NASM.LNK
 
 NDISASM.LNK: makefile.lcc
         echo ndisasm.$(OBJ) > NDISASM.LNK
@@ -80,16 +80,16 @@ nasm.${OBJ}: nasm.c nasm.h insnsi.h nasmlib.h preproc.h parser.h assemble.h labe
  outform.h listing.h
 nasmlib.${OBJ}: nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
 ndisasm.${OBJ}: ndisasm.c nasm.h insnsi.h nasmlib.h sync.h disasm.h
-outaout.${OBJ}: outaout.c nasm.h insnsi.h nasmlib.h outform.h
-outas86.${OBJ}: outas86.c nasm.h insnsi.h nasmlib.h outform.h
-outbin.${OBJ}: outbin.c nasm.h insnsi.h nasmlib.h outform.h
-outcoff.${OBJ}: outcoff.c nasm.h insnsi.h nasmlib.h outform.h
-outdbg.${OBJ}: outdbg.c nasm.h insnsi.h nasmlib.h outform.h
-outelf.${OBJ}: outelf.c nasm.h insnsi.h nasmlib.h outform.h
+output/outaout.${OBJ}: output/outaout.c nasm.h insnsi.h nasmlib.h outform.h
+output/outas86.${OBJ}: output/outas86.c nasm.h insnsi.h nasmlib.h outform.h
+output/outbin.${OBJ}: output/outbin.c nasm.h insnsi.h nasmlib.h outform.h
+output/outcoff.${OBJ}: output/outcoff.c nasm.h insnsi.h nasmlib.h outform.h
+output/outdbg.${OBJ}: output/outdbg.c nasm.h insnsi.h nasmlib.h outform.h
+output/outelf.${OBJ}: output/outelf.c nasm.h insnsi.h nasmlib.h outform.h
 outform.${OBJ}: outform.c outform.h nasm.h insnsi.h
-outobj.${OBJ}: outobj.c nasm.h insnsi.h nasmlib.h outform.h
-outrdf2.${OBJ}: outrdf2.c nasm.h insnsi.h nasmlib.h outform.h
-zoutieee.${OBJ}: zoutieee.c nasm.h insnsi.h nasmlib.h outform.h
+output/outobj.${OBJ}: output/outobj.c nasm.h insnsi.h nasmlib.h outform.h
+output/outrdf2.${OBJ}: output/outrdf2.c nasm.h insnsi.h nasmlib.h outform.h
+output/outieee.${OBJ}: output/outieee.c nasm.h insnsi.h nasmlib.h outform.h
 parser.${OBJ}: parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
 preproc.${OBJ}: preproc.c nasm.h insnsi.h nasmlib.h macros.c
 sync.${OBJ}: sync.c sync.h
index f9236fe6c80ee792264d765e0f157b08cd113212..de4bad3c90708665b8a96791cc48051687c3040d 100644 (file)
@@ -168,25 +168,25 @@ $(OBJD)nasmlibd.$(OBJ): nasmlib.c nasm.h nasmlib.h
 ################################################################
 # Dependencies for all of the output format's OBJ files
 
-$(OBJD)outas86.$(OBJ): outas86.c nasm.h nasmlib.h
+$(OBJD)outas86.$(OBJ): output/outas86.c nasm.h nasmlib.h
         $(NASM_ASM)
 
-$(OBJD)outaout.$(OBJ): outaout.c nasm.h nasmlib.h
+$(OBJD)outaout.$(OBJ): output/outaout.c nasm.h nasmlib.h
         $(NASM_ASM)
 
-$(OBJD)outbin.$(OBJ): outbin.c nasm.h nasmlib.h
+$(OBJD)outbin.$(OBJ): output/outbin.c nasm.h nasmlib.h
         $(NASM_ASM)
 
-$(OBJD)outcoff.$(OBJ): outcoff.c nasm.h nasmlib.h
+$(OBJD)outcoff.$(OBJ): output/outcoff.c nasm.h nasmlib.h
         $(NASM_ASM)
 
-$(OBJD)outdbg.$(OBJ): outdbg.c nasm.h nasmlib.h
+$(OBJD)outdbg.$(OBJ): output/outdbg.c nasm.h nasmlib.h
         $(NASM_ASM)
 
-$(OBJD)outelf.$(OBJ): outelf.c nasm.h nasmlib.h
+$(OBJD)outelf.$(OBJ): output/outelf.c nasm.h nasmlib.h
         $(NASM_ASM)
 
-$(OBJD)outobj.$(OBJ): outobj.c nasm.h nasmlib.h
+$(OBJD)outobj.$(OBJ): output/outobj.c nasm.h nasmlib.h
         $(NASM_ASM)
 
 $(OBJD)outform.$(OBJ): outform.c outform.h nasm.h
index 6563b69d1e999a69e4445b3976ea0d6950ba7937..aa932b1d140b9cddc05bbd06232aaa61cbbaf99b 100644 (file)
@@ -44,9 +44,9 @@ OBJ = obj
 
 NASMOBJS = nasm.$(OBJ) nasmlib.$(OBJ) float.$(OBJ) insnsa.$(OBJ) \
            assemble.$(OBJ) labels.$(OBJ) parser.$(OBJ) outform.$(OBJ) \
-          outbin.$(OBJ) outaout.$(OBJ) outcoff.$(OBJ) outelf.$(OBJ) \
-          outobj.$(OBJ) outas86.$(OBJ) outrdf.$(OBJ) outrdf2.$(OBJ) \
-          zoutieee.$(OBJ) outdbg.$(OBJ) \
+          output/outbin.$(OBJ) output/outaout.$(OBJ) output/outcoff.$(OBJ) output/outelf.$(OBJ) \
+          output/outobj.$(OBJ) output/outas86.$(OBJ) output/outrdf.$(OBJ) output/outrdf2.$(OBJ) \
+          output/outieee.$(OBJ) output/outdbg.$(OBJ) \
           preproc.$(OBJ) listing.$(OBJ) eval.$(OBJ)
 
 NDISASMOBJS = ndisasm.$(OBJ) disasm.$(OBJ) sync.$(OBJ) nasmlib.$(OBJ) \
@@ -92,15 +92,15 @@ nasm.$(OBJ): nasm.c nasm.h insnsi.h nasmlib.h parser.h assemble.h labels.h \
        listing.h outform.h
 nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
 ndisasm.$(OBJ): ndisasm.c nasm.h insnsi.h sync.h disasm.h
-outas86.$(OBJ): outas86.c nasm.h insnsi.h nasmlib.h
-outaout.$(OBJ): outaout.c nasm.h insnsi.h nasmlib.h
-outbin.$(OBJ): outbin.c nasm.h insnsi.h nasmlib.h
-outcoff.$(OBJ): outcoff.c nasm.h insnsi.h nasmlib.h
-outdbg.$(OBJ): outdbg.c nasm.h insnsi.h nasmlib.h
-outelf.$(OBJ): outelf.c nasm.h insnsi.h nasmlib.h
-outobj.$(OBJ): outobj.c nasm.h insnsi.h nasmlib.h
-outrdf2.$(OBJ): outrdf2.c nasm.h insnsi.h nasmlib.h
-zoutieee.$(OBJ): zoutieee.c nasm.h insnsi.h nasmlib.h
+output/outas86.$(OBJ): output/outas86.c nasm.h insnsi.h nasmlib.h
+output/outaout.$(OBJ): output/outaout.c nasm.h insnsi.h nasmlib.h
+output/outbin.$(OBJ): output/outbin.c nasm.h insnsi.h nasmlib.h
+output/outcoff.$(OBJ): output/outcoff.c nasm.h insnsi.h nasmlib.h
+output/outdbg.$(OBJ): output/outdbg.c nasm.h insnsi.h nasmlib.h
+output/outelf.$(OBJ): output/outelf.c nasm.h insnsi.h nasmlib.h
+output/outobj.$(OBJ): output/outobj.c nasm.h insnsi.h nasmlib.h
+output/outrdf2.$(OBJ): output/outrdf2.c nasm.h insnsi.h nasmlib.h
+output/outieee.$(OBJ): output/outieee.c nasm.h insnsi.h nasmlib.h
 outform.$(OBJ): outform.c outform.h nasm.h insnsi.h
 parser.$(OBJ): parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
 preproc.$(OBJ): preproc.c macros.c preproc.h nasm.h insnsi.h nasmlib.h
index d7ce92e47f31e9bd138ccd365f50b9f8957af17a..5cd067476d5ae5d6688ff5abfd7719a835c3d7cd 100644 (file)
@@ -44,9 +44,9 @@ OBJ = obj
 
 NASMOBJS = nasm.$(OBJ) nasmlib.$(OBJ) float.$(OBJ) insnsa.$(OBJ) \
            assemble.$(OBJ) labels.$(OBJ) parser.$(OBJ) outform.$(OBJ) \
-          outbin.$(OBJ) outaout.$(OBJ) outcoff.$(OBJ) outelf.$(OBJ) \
-          outobj.$(OBJ) outas86.$(OBJ) outrdf.$(OBJ) outdbg.$(OBJ) \
-          outrdf2.$(OBJ) zoutieee.$(OBJ) \
+          output/outbin.$(OBJ) output/outaout.$(OBJ) output/outcoff.$(OBJ) output/outelf.$(OBJ) \
+          output/outobj.$(OBJ) output/outas86.$(OBJ) output/outrdf.$(OBJ) output/outdbg.$(OBJ) \
+          output/outrdf2.$(OBJ) output/outieee.$(OBJ) \
           preproc.$(OBJ) listing.$(OBJ) eval.$(OBJ)
 
 NDISASMOBJS = ndisasm.$(OBJ) disasm.$(OBJ) sync.$(OBJ) nasmlib.$(OBJ) \
@@ -92,15 +92,15 @@ nasm.$(OBJ): nasm.c nasm.h insnsi.h nasmlib.h parser.h assemble.h labels.h \
        listing.h outform.h
 nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
 ndisasm.$(OBJ): ndisasm.c nasm.h insnsi.h sync.h disasm.h
-outas86.$(OBJ): outas86.c nasm.h insnsi.h nasmlib.h
-outaout.$(OBJ): outaout.c nasm.h insnsi.h nasmlib.h
-outbin.$(OBJ): outbin.c nasm.h insnsi.h nasmlib.h
-outcoff.$(OBJ): outcoff.c nasm.h insnsi.h nasmlib.h
-outdbg.$(OBJ): outdbg.c nasm.h insnsi.h nasmlib.h
-outelf.$(OBJ): outelf.c nasm.h insnsi.h nasmlib.h
-outobj.$(OBJ): outobj.c nasm.h insnsi.h nasmlib.h
-outrdf2.$(OBJ): outrdf2.c nasm.h insnsi.h nasmlib.h
-zoutieee.$(OBJ): zoutieee.c nasm.h insnsi.h nasmlib.h
+output/outas86.$(OBJ): output/outas86.c nasm.h insnsi.h nasmlib.h
+output/outaout.$(OBJ): output/outaout.c nasm.h insnsi.h nasmlib.h
+output/outbin.$(OBJ): output/outbin.c nasm.h insnsi.h nasmlib.h
+output/outcoff.$(OBJ): output/outcoff.c nasm.h insnsi.h nasmlib.h
+output/outdbg.$(OBJ): output/outdbg.c nasm.h insnsi.h nasmlib.h
+output/outelf.$(OBJ): output/outelf.c nasm.h insnsi.h nasmlib.h
+output/outobj.$(OBJ): output/outobj.c nasm.h insnsi.h nasmlib.h
+output/outrdf2.$(OBJ): output/outrdf2.c nasm.h insnsi.h nasmlib.h
+output/outieee.$(OBJ): output/outieee.c nasm.h insnsi.h nasmlib.h
 outform.$(OBJ): outform.c outform.h nasm.h insnsi.h
 parser.$(OBJ): parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
 preproc.$(OBJ): preproc.c macros.c preproc.h nasm.h insnsi.h nasmlib.h
index 9bcb0c879843c76bc88f3b8950d979b2c4b50582..b56884995215d46e34f185eeb9bfa177e60b3529 100644 (file)
@@ -2,11 +2,11 @@
 # `configure' fails to generate a workable Makefile.
 #
 # If `configure' doesn't work for you, *please* inform <hpa@zytor.com>
+# and <nasm-bugs@lists.sourceforge.net>
 #
 # The Netwide Assembler is copyright (C) 1996 Simon Tatham and
 # Julian Hall. All rights reserved. The software is
-# redistributable under the licence given in the file "Licence"
-# distributed in the NASM archive.
+# redistributable under the GNU Lesser General Public License.
 
 # You may need to adjust these values.
 
@@ -28,9 +28,9 @@ INSTALL_DATA = ${INSTALL} -m 644
        $(CC) -c $(CFLAGS) $*.c
 
 NASM = nasm.o nasmlib.o float.o insnsa.o assemble.o labels.o \
-       parser.o outform.o outbin.o outaout.o outcoff.o outelf.o \
-       outobj.o outas86.o outrdf.o outdbg.o preproc.o listing.o \
-       eval.o outrdf2.o zoutieee.o
+       parser.o outform.o output/outbin.o output/outaout.o output/outcoff.o output/outelf.o \
+       output/outobj.o output/outas86.o output/outrdf.o output/outdbg.o preproc.o listing.o \
+       eval.o output/outrdf2.o output/outieee.o
 
 NDISASM = ndisasm.o disasm.o sync.o nasmlib.o insnsd.o
 
@@ -54,16 +54,16 @@ nasm.o: nasm.c nasm.h insnsi.h nasmlib.h preproc.h parser.h assemble.h labels.h
  outform.h listing.h
 nasmlib.o: nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
 ndisasm.o: ndisasm.c nasm.h insnsi.h nasmlib.h sync.h disasm.h
-outaout.o: outaout.c nasm.h insnsi.h nasmlib.h outform.h
-outas86.o: outas86.c nasm.h insnsi.h nasmlib.h outform.h
-outbin.o: outbin.c nasm.h insnsi.h nasmlib.h outform.h
-outcoff.o: outcoff.c nasm.h insnsi.h nasmlib.h outform.h
-outdbg.o: outdbg.c nasm.h insnsi.h nasmlib.h outform.h
-outelf.o: outelf.c nasm.h insnsi.h nasmlib.h outform.h
+output/outaout.o: output/outaout.c nasm.h insnsi.h nasmlib.h outform.h
+output/outas86.o: output/outas86.c nasm.h insnsi.h nasmlib.h outform.h
+output/outbin.o: output/outbin.c nasm.h insnsi.h nasmlib.h outform.h
+output/outcoff.o: output/outcoff.c nasm.h insnsi.h nasmlib.h outform.h
+output/outdbg.o: output/outdbg.c nasm.h insnsi.h nasmlib.h outform.h
+output/outelf.o: output/outelf.c nasm.h insnsi.h nasmlib.h outform.h
 outform.o: outform.c outform.h nasm.h insnsi.h
-outobj.o: outobj.c nasm.h insnsi.h nasmlib.h outform.h
-outrdf2.o: outrdf2.c nasm.h insnsi.h nasmlib.h outform.h
-zoutieee.o: zoutieee.c nasm.h insnsi.h nasmlib.h outform.h
+output/outobj.o: output/outobj.c nasm.h insnsi.h nasmlib.h outform.h
+output/outrdf2.o: output/outrdf2.c nasm.h insnsi.h nasmlib.h outform.h
+output/outieee.o: output/outieee.c nasm.h insnsi.h nasmlib.h outform.h
 parser.o: parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
 preproc.o: preproc.c nasm.h insnsi.h nasmlib.h macros.c
 sync.o: sync.c sync.h
index 4b8c280ac77c7ec3d2e8ebb09f650d3dc435d41f..da6ecfc2bf46523ea6dc4a6552de6ac7a8186c82 100644 (file)
@@ -22,10 +22,10 @@ SUFFIX = w#  # by default, this makefile produces nasmw.exe and ndisasmw.exe
 
 NASMOBJS = nasm.$(OBJ) nasmlib.$(OBJ) float.$(OBJ) insnsa.$(OBJ) \
            assemble.$(OBJ) labels.$(OBJ) parser.$(OBJ) outform.$(OBJ) \
-          outbin.$(OBJ) outaout.$(OBJ) outcoff.$(OBJ) outelf.$(OBJ) \
-          outobj.$(OBJ) outas86.$(OBJ) outrdf.$(OBJ) outdbg.$(OBJ) \
-          preproc.$(OBJ) listing.$(OBJ) eval.$(OBJ) outrdf2.$(OBJ) \
-          zoutieee.$(OBJ)
+          output/outbin.$(OBJ) output/outaout.$(OBJ) output/outcoff.$(OBJ) output/outelf.$(OBJ) \
+          output/outobj.$(OBJ) output/outas86.$(OBJ) output/outrdf.$(OBJ) output/outdbg.$(OBJ) \
+          preproc.$(OBJ) listing.$(OBJ) eval.$(OBJ) output/outrdf2.$(OBJ) \
+          output/outieee.$(OBJ)
 
 NDISASMOBJS = ndisasm.$(OBJ) disasm.$(OBJ) sync.$(OBJ) nasmlib.$(OBJ) \
               insnsd.$(OBJ)
@@ -51,15 +51,15 @@ nasm.$(OBJ): nasm.c nasm.h insnsi.h nasmlib.h parser.h assemble.h labels.h \
        listing.h outform.h
 nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
 ndisasm.$(OBJ): ndisasm.c nasm.h insnsi.h sync.h disasm.h
-outas86.$(OBJ): outas86.c nasm.h insnsi.h nasmlib.h
-outaout.$(OBJ): outaout.c nasm.h insnsi.h nasmlib.h
-outbin.$(OBJ): outbin.c nasm.h insnsi.h nasmlib.h
-outcoff.$(OBJ): outcoff.c nasm.h insnsi.h nasmlib.h
-outdbg.$(OBJ): outdbg.c nasm.h insnsi.h nasmlib.h
-outelf.$(OBJ): outelf.c nasm.h insnsi.h nasmlib.h
-outobj.$(OBJ): outobj.c nasm.h insnsi.h nasmlib.h
-outrdf2.$(OBJ): outrdf2.c nasm.h insnsi.h nasmlib.h
-zoutieee.$(OBJ): zoutieee.c nasm.h insnsi.h nasmlib.h
+output/outas86.$(OBJ): output/outas86.c nasm.h insnsi.h nasmlib.h
+output/outaout.$(OBJ): output/outaout.c nasm.h insnsi.h nasmlib.h
+output/outbin.$(OBJ): output/outbin.c nasm.h insnsi.h nasmlib.h
+output/outcoff.$(OBJ): output/outcoff.c nasm.h insnsi.h nasmlib.h
+output/outdbg.$(OBJ): output/outdbg.c nasm.h insnsi.h nasmlib.h
+output/outelf.$(OBJ): output/outelf.c nasm.h insnsi.h nasmlib.h
+output/outobj.$(OBJ): output/outobj.c nasm.h insnsi.h nasmlib.h
+output/outrdf2.$(OBJ): output/outrdf2.c nasm.h insnsi.h nasmlib.h
+output/outieee.$(OBJ): output/outieee.c nasm.h insnsi.h nasmlib.h
 outform.$(OBJ): outform.c outform.h nasm.h insnsi.h
 parser.$(OBJ): parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
 preproc.$(OBJ): preproc.c macros.c preproc.h nasm.h insnsi.h nasmlib.h
index 3feb860557d26d319bd2b94dd78ed618e08f956c..6dbbd5386678db500908677fae64d0ac10aa64aa 100644 (file)
@@ -40,10 +40,10 @@ OBJ = obj
 
 NASMOBJS = nasm.$(OBJ) nasmlib.$(OBJ) float.$(OBJ) insnsa.$(OBJ) \
            assemble.$(OBJ) labels.$(OBJ) parser.$(OBJ) outform.$(OBJ) \
-          outbin.$(OBJ) outaout.$(OBJ) outcoff.$(OBJ) outelf.$(OBJ) \
-          outobj.$(OBJ) outas86.$(OBJ) outrdf.$(OBJ) outdbg.$(OBJ) \
-          preproc.$(OBJ) listing.$(OBJ) eval.$(OBJ) outrdf2.$(OBJ) \
-          zoutieee.$(OBJ)
+          output/outbin.$(OBJ) output/outaout.$(OBJ) output/outcoff.$(OBJ) output/outelf.$(OBJ) \
+          output/outobj.$(OBJ) output/outas86.$(OBJ) output/outrdf.$(OBJ) output/outdbg.$(OBJ) \
+          preproc.$(OBJ) listing.$(OBJ) eval.$(OBJ) output/outrdf2.$(OBJ) \
+          output/outieee.$(OBJ)
 
 NDISASMOBJS = ndisasm.$(OBJ) disasm.$(OBJ) sync.$(OBJ) nasmlib.$(OBJ) \
              insnsd.$(OBJ)
@@ -70,18 +70,18 @@ NASM.LNK: makefile.wc
         echo F labels.$(OBJ) >> NASM.LNK
         echo F listing.$(OBJ) >> NASM.LNK
         echo F parser.$(OBJ) >> NASM.LNK
-       echo F preproc.$(OBJ) >> NASM.LNK
+        echo F preproc.$(OBJ) >> NASM.LNK
         echo F outform.$(OBJ) >> NASM.LNK
-        echo F outbin.$(OBJ) >> NASM.LNK
-        echo F outaout.$(OBJ) >> NASM.LNK
-        echo F outcoff.$(OBJ) >> NASM.LNK
-        echo F outelf.$(OBJ) >> NASM.LNK
-        echo F outobj.$(OBJ) >> NASM.LNK
-        echo F outas86.$(OBJ) >> NASM.LNK
-        echo F outrdf.$(OBJ) >> NASM.LNK
-        echo F outrdf2.$(OBJ) >> NASM.LNK
-        echo F zoutieee.$(OBJ) >> NASM.LNK
-        echo F outdbg.$(OBJ) >> NASM.LNK
+        echo F output/outbin.$(OBJ) >> NASM.LNK
+        echo F output/outaout.$(OBJ) >> NASM.LNK
+        echo F output/outcoff.$(OBJ) >> NASM.LNK
+        echo F output/outelf.$(OBJ) >> NASM.LNK
+        echo F output/outobj.$(OBJ) >> NASM.LNK
+        echo F output/outas86.$(OBJ) >> NASM.LNK
+        echo F output/outrdf.$(OBJ) >> NASM.LNK
+        echo F output/outrdf2.$(OBJ) >> NASM.LNK
+        echo F output/outieee.$(OBJ) >> NASM.LNK
+        echo F output/outdbg.$(OBJ) >> NASM.LNK
 
 NDISASM.LNK: makefile.wc
         echo N ndisasm.exe > NDISASM.LNK
@@ -103,14 +103,14 @@ nasm.$(OBJ): nasm.c nasm.h insnsi.h nasmlib.h parser.h assemble.h labels.h \
        listing.h outform.h
 nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h
 ndisasm.$(OBJ): ndisasm.c nasm.h insnsi.h sync.h disasm.h
-outas86.$(OBJ): outas86.c nasm.h insnsi.h nasmlib.h
-outaout.$(OBJ): outaout.c nasm.h insnsi.h nasmlib.h
-outbin.$(OBJ): outbin.c nasm.h insnsi.h nasmlib.h
-outcoff.$(OBJ): outcoff.c nasm.h insnsi.h nasmlib.h
-outelf.$(OBJ): outelf.c nasm.h insnsi.h nasmlib.h
-outobj.$(OBJ): outobj.c nasm.h insnsi.h nasmlib.h
-outrdf2.$(OBJ): outrdf2.c nasm.h insnsi.h nasmlib.h
-zoutieee.$(OBJ): zoutieee.c nasm.h insnsi.h nasmlib.h
+output/outas86.$(OBJ): output/outas86.c nasm.h insnsi.h nasmlib.h
+output/outaout.$(OBJ): output/outaout.c nasm.h insnsi.h nasmlib.h
+output/outbin.$(OBJ): output/outbin.c nasm.h insnsi.h nasmlib.h
+output/outcoff.$(OBJ): output/outcoff.c nasm.h insnsi.h nasmlib.h
+output/outelf.$(OBJ): output/outelf.c nasm.h insnsi.h nasmlib.h
+output/outobj.$(OBJ): output/outobj.c nasm.h insnsi.h nasmlib.h
+output/outrdf2.$(OBJ): output/outrdf2.c nasm.h insnsi.h nasmlib.h
+output/outieee.$(OBJ): output/outieee.c nasm.h insnsi.h nasmlib.h
 outform.$(OBJ): outform.c outform.h nasm.h insnsi.h
 parser.$(OBJ): parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
 preproc.$(OBJ): preproc.c macros.c preproc.h nasm.h insnsi.h nasmlib.h
index 81a96feea8dc36560948ddac4abf8d3ee099b4cf..256096cfb2c644bc1a730bd497f410ee60bffbd9 100644 (file)
@@ -40,10 +40,10 @@ OBJ = obj
 
 NASMOBJS = nasm.$(OBJ) nasmlib.$(OBJ) float.$(OBJ) insnsa.$(OBJ) \
            assemble.$(OBJ) labels.$(OBJ) parser.$(OBJ) outform.$(OBJ) \
-          outbin.$(OBJ) outaout.$(OBJ) outcoff.$(OBJ) outelf.$(OBJ) \
-          outobj.$(OBJ) outas86.$(OBJ) outrdf.$(OBJ) outdbg.$(OBJ) \
-          preproc.$(OBJ) listing.$(OBJ) eval.$(OBJ) outrdf2.$(OBJ) \
-          zoutieee.$(OBJ)
+          output/outbin.$(OBJ) output/outaout.$(OBJ) output/outcoff.$(OBJ) output/outelf.$(OBJ) \
+          output/outobj.$(OBJ) output/outas86.$(OBJ) output/outrdf.$(OBJ) output/outdbg.$(OBJ) \
+          preproc.$(OBJ) listing.$(OBJ) eval.$(OBJ) output/outrdf2.$(OBJ) \
+          output/outieee.$(OBJ)
 
 NDISASMOBJS = ndisasm.$(OBJ) disasm.$(OBJ) sync.$(OBJ) nasmlib.$(OBJ) \
              insnsd.$(OBJ)
@@ -70,18 +70,18 @@ NASM.LNK: makefile.wcw
         echo F labels.$(OBJ) >> NASM.LNK
         echo F listing.$(OBJ) >> NASM.LNK
         echo F parser.$(OBJ) >> NASM.LNK
-       echo F preproc.$(OBJ) >> NASM.LNK
+        echo F preproc.$(OBJ) >> NASM.LNK
         echo F outform.$(OBJ) >> NASM.LNK
-        echo F outbin.$(OBJ) >> NASM.LNK
-        echo F outaout.$(OBJ) >> NASM.LNK
-        echo F outcoff.$(OBJ) >> NASM.LNK
-        echo F outelf.$(OBJ) >> NASM.LNK
-        echo F outobj.$(OBJ) >> NASM.LNK
-        echo F outas86.$(OBJ) >> NASM.LNK
-        echo F outrdf.$(OBJ) >> NASM.LNK
-        echo F outrdf2.$(OBJ) >> NASM.LNK
-        echo F zoutieee.$(OBJ) >> NASM.LNK
-        echo F outdbg.$(OBJ) >> NASM.LNK
+        echo F output/outbin.$(OBJ) >> NASM.LNK
+        echo F output/outaout.$(OBJ) >> NASM.LNK
+        echo F output/outcoff.$(OBJ) >> NASM.LNK
+        echo F output/outelf.$(OBJ) >> NASM.LNK
+        echo F output/outobj.$(OBJ) >> NASM.LNK
+        echo F output/outas86.$(OBJ) >> NASM.LNK
+        echo F output/outrdf.$(OBJ) >> NASM.LNK
+        echo F output/outrdf2.$(OBJ) >> NASM.LNK
+        echo F output/outieee.$(OBJ) >> NASM.LNK
+        echo F output/outdbg.$(OBJ) >> NASM.LNK
 
 NDISASM.LNK: makefile.wcw
         echo N ndisasm.exe > NDISASM.LNK
@@ -103,14 +103,14 @@ nasm.$(OBJ): nasm.c nasm.h insnsi.h nasmlib.h parser.h assemble.h labels.h \
        listing.h outform.h
 nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
 ndisasm.$(OBJ): ndisasm.c nasm.h insnsi.h sync.h disasm.h
-outas86.$(OBJ): outas86.c nasm.h insnsi.h nasmlib.h
-outaout.$(OBJ): outaout.c nasm.h insnsi.h nasmlib.h
-outbin.$(OBJ): outbin.c nasm.h insnsi.h nasmlib.h
-outcoff.$(OBJ): outcoff.c nasm.h insnsi.h nasmlib.h
-outelf.$(OBJ): outelf.c nasm.h insnsi.h nasmlib.h
-outobj.$(OBJ): outobj.c nasm.h insnsi.h nasmlib.h
-outrdf2.$(OBJ): outrdf2.c nasm.h insnsi.h nasmlib.h
-zoutieee.$(OBJ): zoutieee.c nasm.h insnsi.h nasmlib.h
+output/outas86.$(OBJ): output/outas86.c nasm.h insnsi.h nasmlib.h
+output/outaout.$(OBJ): output/outaout.c nasm.h insnsi.h nasmlib.h
+output/outbin.$(OBJ): output/outbin.c nasm.h insnsi.h nasmlib.h
+output/outcoff.$(OBJ): output/outcoff.c nasm.h insnsi.h nasmlib.h
+output/outelf.$(OBJ): output/outelf.c nasm.h insnsi.h nasmlib.h
+output/outobj.$(OBJ): output/outobj.c nasm.h insnsi.h nasmlib.h
+output/outrdf2.$(OBJ): output/outrdf2.c nasm.h insnsi.h nasmlib.h
+output/outieee.$(OBJ): output/outieee.c nasm.h insnsi.h nasmlib.h
 outform.$(OBJ): outform.c outform.h nasm.h insnsi.h
 parser.$(OBJ): parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
 preproc.$(OBJ): preproc.c macros.c preproc.h nasm.h insnsi.h nasmlib.h
diff --git a/README b/README
index 755a4652d2aa37fa3f6cef893aef004343c42a09..29f076851153b6ebd41e88e61814ae8e9d80a463 100644 (file)
--- a/README
+++ b/README
@@ -1,5 +1,6 @@
               NASM, the Netwide Assembler.
-                     Version 0.98.26.
+                     Version 0.98.30.
+                        2002-04-29
 
 Many many developers all over the net respect NASM for what it is
 - a widespread (thus netwide), portable (thus netwide!), very
@@ -16,12 +17,5 @@ famous Open Source development center on The Net.
 Visit our development page at http://nasm.2y.net and our
 SF project at http://sf.net/projects/nasm
 
-The NASM documentation is in process of severe re-arrangement
-(especially the License issues with sourcecode, the old
-license can be found in doc/License), all files from previous
-releases that didn't go thru the process yet are placed in doc/
-subdirectory. Look there if you don't find a file you need here.
-
-
                                                    With best regards,
                                                            NASM crew.
diff --git a/Readme b/Readme
deleted file mode 100644 (file)
index dbbd18d..0000000
--- a/Readme
+++ /dev/null
@@ -1,49 +0,0 @@
-
-              NetWide Assembler for the SciTech MGL
-              -------------------------------------
-
-This is a modified distribution of NASM, the Netwide Assembler. NASM
-is a prototype general-purpose x86 assembler. It will currently output
-flat-form binary files, a.out, COFF and ELF Unix object files,
-Microsoft Win32 and 16-bit DOS object files, OS/2 object files, the
-as86 object format, and a home-grown format called RDF.
-
-This version of NASM has been modified by SciTech Software such that it
-can be used to assemble source code in the SciTech MGL graphics library,
-and understands enough of TASM assembler syntax such that both NASM
-and TASM can be used to generate assembler modules for the MGL graphics
-library. A complete macro package is provided as part of the SciTech
-MGL that provides macros to help in building modules that will work with
-either assembler.
-
-A pre-compiled binary of NASM is provided as part of the SciTech MGL
-graphics library, however you may re-build the assembler from the sources
-provided. To do so make sure you have the SciTech Makefile Utilties
-correctly configured for your compiler, and then simly type:
-
-    unset DBG
-    dmake OPT=1
-
-to build an optimised, non-debug version of the assembler. If you wish
-to rebuild for a different OS other than DOS or Win32, you will need to
-first compile the DMAKE make program for your OS. See the DMAKE source
-code for more information.
-
-Licensing issues:
------------------
-
-For information about how you can distribute and use NASM, see the
-file Licence.
-
-The NASM web page is at http://www.cryogen.com/Nasm/
-
-Bug reports specific to the SciTech MGL should be posted to SciTech
-Software MGL newsgroups:
-
-    news://news.scitechsoft.com/scitech.mgl.developer
-
-Bug reports (and patches if you can) for NASM itself that are not SciTech
-MGL related should be sent to the authors at:
-
-    Julian Hall <jules@earthcorp.com>
-    Simon Tatham <anakin@pobox.com>
diff --git a/TODO b/TODO
index ab8bbdbfa3223fc5a482359eb04b68341af29e17..790544376c333209944e839cd2dfe2fb38d70fc3 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,8 +1,339 @@
-Things to do (incorporate with doc/Wishlist):
-
-1. i18n via gettext
-2. Convert shallow code model to deep code model. Tired of messing between
-lots of unrelated files (especially .c/.h stuff).
-3. Automated dependency generation for Makefile. Current looks awful and will break
-if anything changes.
-4. (as result of 2) Move output modules out*.c to output/ subdir. (?)
+NASM TODO list
+==============
+
+This, like the AUTHORS file, is intended for easy readability by both human 
+and machine, thus the format.
+
+  F: feature
+  V: version you should expect it by
+  R: responsible person or - if unassigned
+  C: % complete
+  D: description
+  D: maybe on multiple lines
+  
+Anything that doesn't start with /^[FVRCD]:/ should be ignored.
+
+  F:-line triggers new entry.
+  Empty V,R,C assume: V: ?, R: -, C: 0%
+
+=============
+
+F: i18n via gettext
+
+F: Convert shallow code model to deep code model
+D: Tired of messing between lots of unrelated files (especially .c/.h stuff)
+
+F: Automated dependency generation for Makefile
+D: Current looks awful and will break if anything changes.
+
+F: Move output modules out*.c to output/ subdir
+R: madfire
+C: 10%
+
+== THESE ARE FROM old NASM's Wishlist
+== THEY NEED SEVERE REVISING (seems they weren't updated for a couple of years or so)
+
+F: Check misc/ide.cfg into RCS as Watcom IDE enhancement thingy
+V: 0.98
+D: (nop@dlc.fi)
+
+F: Package the Linux Assembler HOWTO
+V: 0.98
+
+F: 3DNow!, SSE and other extensions need documenting
+V: 0.98
+D: hpa: Does it really make sense to have a whole instruction set
+D: reference packaged with the assembler?
+
+F: prototypes of lrotate don't match in test/*. Fix.
+V: 0.98
+
+F: Build djgpp binaries for 0.98 onwards. Look into PMODE/W as a stub
+V: 0.98
+D: it might be a lot better than CWSDPMI. It's in PMW133.ZIP.
+
+F: %undef operator that goes along with %define
+V: ?
+C: 100%
+
+F: Fix `%error' giving error messages twice.
+V: 0.99
+D: Not especially important, as changes planned for 1.1x below will make
+D: the preprocessor be only called once.
+
+F: Sort out problems with OBJ
+V: 0.99
+D: * TLINK32 doesn't seem to like SEGDEF32 et al. So for that, we
+D:   should avoid xxx32 records wherever we can.
+D: * However, didn't we change _to_ using xxx32 at some stage? Try
+D:   to remember why and when.
+D: * Apparently Delphi's linker has trouble with two or more
+D:   globals being defined inside a PUBDEF32. Don't even know if it
+D:   _can_ cope with a PUBDEF16.
+D: * Might need extra flags. *sigh*
+
+F: Symbol table output may possibly be useful.
+V: 0.99
+D: Ken Martwick (kenm@efn.org) wants the following format:
+D:     labelname       type    offset(hex)     repetition count
+D: Possibly include xref addresses after repetition count?
+
+F: ELF fixes
+V: 0.99
+D: There are various other bugs in outelf.c that make certain kinds
+D: of relocation not work. See zbrown.asm. Looks like we may have to do
+D: a major rewrite of parts of it. Compare some NASM code output with
+D: equivalent GAS code output. Look at the ELF spec. Generally fix things.
+
+F: ELF fixes
+V: 0.99
+D: NASM is currently using a kludge in ELF that involves defining
+D: a symbol at a zero absolute offset. This isn't needed, as the
+D: documented solution to the problem that this solves is to use
+D: SHN_UNDEF.
+
+F: Debug information, in all formats it can be usefully done in.
+V: 0.99
+D: * including line-number record support.
+D: * "George C. Lindauer" <gclind01@starbase.spd.louisville.edu>
+D:   wants to have some say in how this goes through.
+D: * Andrew Crabtree <andrewc@rosemail.rose.hp.com> wants to help out.
+
+F: Think about a line-continuation character.
+V: 0.99
+
+F: Consider allowing declaration of two labels on the same line,
+V: 0.99
+D: syntax 'label1[:] label2[:] ... instruction'.
+D: Need to investigate feasibility.
+
+F: Quoting of quotes by doubling them, in string and char constants.
+V: 0.99
+
+F: Two-operand syntax for SEGMENT/SECTION macro to avoid warnings
+D: of ignored section parameters on reissue of __SECT__.
+D: Or maybe skip the warning if the given parameters are identical to
+D: what was actually stored. Investigate.                              
+V: 0.99
+
+F: Apparently we are not missing a PSRAQ instruction, because it
+D: doesn't exist.  Check that it doesn't exist as an undocumented
+D: instruction, or something stupid like that.
+V: 0.99
+
+F: Any assembled form starting 0x80 can also start 0x82.
+V: 1.00
+D: ndisasm should know this. New special code in instruction encodings, probably.
+
+F: Pointing an EQU at an external symbol now generates an error.
+V: 1.05
+D: There may be a better way of handling this; we should look into it.
+D: Ideally, the label mechanism should be changed to cope with one
+D: label being declared relative to another - that may work, but could be
+D: a pain to implement (or is it? it may be easy enough that you just
+D: need to declare a new offset in the same segment...) This should be done
+D: before v1.0 is released. There is a comment regarding this in labels.c,
+D: towards the end of the file, which discusses ways of fixing this.
+
+F: nested %rep used to cause a panic.
+V: 1.10
+D: Now a more informative error message is produced. This problem whould
+D: be fixed before v1.0.
+D: See comment in switch() statement block for PP_REP in do_directive()
+D: in preproc.c (line 1585, or thereabouts)
+
+F: Contribution
+D: zgraeme.tar contains improved hash table routines
+D: contributed by Graeme Defty <graeme@HK.Super.NET> for use in the
+D: label manager.
+
+F: Contribution
+D: zsyntax.zip contains a syntax-highlighting mode for
+D: NASM, for use with the Aurora text editor (??).
+
+F: Contribution
+D: zvim.zip contains a syntax-highlighting mode for NASM, for use with vim.
+
+F: Contribution
+D: zkendal1.zip and zkendal2.zip contain Kendall
+D: Bennett's (<KendallB@scitechsoft.com>) alternative syntax stuff,
+D: providing an alternative syntax mode for NASM which allows a macro
+D: set to be written that allows the same source files to be
+D: assembled with NASM and TASM.
+R: Kendall Bennett
+C: 100%
+
+F: Add the UD2 instruction.
+C: 100%
+
+F: Add the four instructions documented in 24368901.pdf (Intel's own document).
+C: 100%
+
+F: Some means of avoiding MOV memoffs,EAX which apparently the
+D: Pentium pairing detector thinks modifies EAX. Similar means of
+D: choosing instruction encodings where necessary.
+V: 1.10?
+
+F: The example of ..@ makes it clear that a ..@ label isn't just
+D: local, but doesn't make it clear that it isn't just global either.
+
+F: hpa wants an evaluator operator for ceil(log2(x)).
+
+F: Extra reloc types in ELF
+D: R_386_16 type 20, PC16 is 21, 8 is 22, PC8 is 23.
+D: Add support for the 16s at least.
+
+F: Lazy section creation or selective section output
+D: in COFF/win32 at least and probably other formats: don't bother to emit a section
+D: if it contains no data. Particularly the default auto-created
+D: section. We believe zero-length sections crash at least WLINK (in win32).
+
+F: Make the flags field in `struct itemplate' in insns.h a long instead of an int.
+C: 100%?
+
+F: Implement %ifref to check whether a single-line macro has ever been expanded since (last re) definition. Or maybe not. We'll see.
+
+F: add pointer to \k{insLEAVE} and \k{insENTER} in chapters about      mixed-language programming.
+
+F: Some equivalent to TASM's GLOBAL directive
+D: ie something which defines a symbol as external if it doesn't end up being defined
+D: but defines it as public if it does end up being defined.
+
+F: Documentation doesn't explain about C++ name mangling.
+
+F: see if BITS can be made to do anything sensible in obj (eg set the default new-segment property to Use32).
+
+F: OBJ: coalesce consecutive offset and segment fixups for the same location into full-32bit-pointer fixups.
+D: This is apparently necessary because some twazzock in the PowerBASIC development
+D: team didn't design to support the OMF spec the way the rest of the
+D: world sees it.
+
+F: Allow % to be separated from the rest of a preproc directive, for   alternative directive indentation styles.
+
+F: __DATE__, __TIME__, and text variants of __NASM_MAJOR__ and __NASM_MINOR__.
+
+F: Warn on TIMES combined with multi-line macros.
+V: 1.00
+D: TIMES gets applied to first line only - should bring to users' attention.
+
+F: Re-work the evaluator, again, with a per-object-format fixup
+D: routine, so as to be able to cope with section offsets "really"
+D: being pure numbers; should be able to allow at _least_ the two
+D: common idioms
+D:   TIMES 510-$ DB 0            ; bootsector
+D:   MOV AX,(PROG_END-100H)/16   ; .COM TSR
+D: Would need to call the fixup throughout the evaluator, and the
+D: fixup would have to be allowed to return UNKNOWN on pass one if it
+D: had to. (_Always_ returning UNKNOWN on pass one, though a lovely
+D: clean design, breaks the first of the above examples.)
+V: 1.10
+
+F: Preprocessor identifier concatenation?
+V: 1.10
+
+F: Arbitrary section names in `bin'.
+V: 0.98.09
+D: Is this necessary? Is it even desirable?
+D: hpa: Desirable, yes.  Necessary?  Probably not, but there are definitely cases where it becomes quite useful.
+R: madfire
+C: 100%
+
+F: Ability to read from a pipe.
+V: 1.10
+D: Obviously not useful under dos, so memory problems with storing
+D: entire input file aren't a problem either.
+
+F: File caching under DOS/32 bit...
+V: 1.10?
+D: maybe even implement discardable buffers that get thrown away
+D: when we get a NULL returned from malloc(). Only really useful under
+D: DOS. Think about it.
+
+F: possibly spool out the pre-processed stuff to a file, to avoid having to re-process it.
+V: 1.10?
+D: Possible problems with preprocessor values not known on pass 1? Have a look...
+
+F: Or maybe we can spool out a pre-parsed version...?
+V: 1.10
+D: Need to investigate feasibility. Does the results from the parser
+D: change from pass 1 to pass 2? Would it be feasible to alter it so that
+D: the parser returns an invariant result, and this is then processed
+D: afterwards to resolve label references, etc?
+
+F: Subsection support?
+
+F: A good ALIGN mechanism, similar to GAS's.
+V: 0.98p1
+D: GAS pads out space by means of the following (32-bit) instructions:
+D:         8DB42600000000    lea esi,[esi+0x0]
+D:         8DB600000000      lea esi,[esi+0x0]
+D:         8D742600          lea esi,[esi+0x0]
+D:         8D7600            lea esi,[esi+0x0]
+D:         8D36              lea esi,[esi]
+D:         90                nop
+D: It uses up to two of these instructions to do up to 14-byte pads;
+D: when more than 14 bytes are needed, it issues a (short) jump to
+D: the end of the padded section and then NOPs the rest. Come up with
+D: a similar scheme for 16 bit mode, and also come up with a way to
+D: use it - internal to the assembler, so that programs using ALIGN
+D: don't knock over preprocess-only mode.
+D:   Also re-work the macro form so that when given one argument in a
+D: code section it calls this feature.
+R: Panos Minos
+C: 100%?
+
+F: Possibly a means whereby FP constants can be specified as immediate operands to non-FP instructions.
+D: * Possible syntax: MOV EAX,FLOAT 1.2 to get a single-precision FP
+D:   constant. Then maybe MOV EAX,HI_FLOAT 1.2 and MOV EAX,LO_FLOAT
+D:   1.2 to get the two halves of a double-precision one. Best to
+D:   ignore extended-precision in case it bites.
+D: * Alternatively, maybe MOV EAX,FLOAT(4,0-4,1.2) to get bytes 0-4
+D:   (ie 0-3) of a 4-byte constant. Then HI_FLOAT is FLOAT(8,4-8,x)
+D:   and LO_FLOAT is FLOAT(8,0-4,x). But this version allows two-byte
+D:   chunks, one-byte chunks, even stranger chunks, and pieces of
+D:   ten-byte reals to be bandied around as well.
+
+F: A UNION macro might be quite cool
+D: now that ABSOLUTE is sane enough to be able to handle it.
+
+F: An equivalent to gcc's ## stringify operator, plus string concatenation
+D: somehow implemented without undue ugliness, so as
+D: to be able to do `%include "/my/path/%1"' in a macro, or something
+D: similar...
+
+F: Actually _do_ something with the processor, privileged and
+D: undocumented flags in the instruction table. When this happens,
+D: consider allowing PMULHRW to map to either of the Cyrix or AMD
+D: versions?
+D: hpa: The -p option to ndisasm now uses this to some extent.
+V: 1.10
+
+F: Maybe NEC V20/V30 instructions?                                     ?
+D: hpa: What are they?  Should be trivial to implement.
+
+F: Yet more object formats.
+D: * Possibly direct support for .EXE files?
+V: 1.10
+
+F: Symbol map in binary format. Format-specific options...
+V: 1.10?
+
+F: REDESIGN: Think about EQU dependency, and about start-point specification in OBJ. Possibly re-think directive support.
+V: 1.20?
+
+F: Think about a wrapper program like gcc?
+V: 2.00?
+D: Possibly invent a _patch_ for gcc so that it can take .asm files on the command line?
+D: If a wrapper happens, think about adding an option to cause the
+D: resulting executable file to be executed immediately, thus
+D: allowing NASM source files to have #!... (probably silly)
+
+F: Multi-platform support?
+D: If so: definitely Alpha; possibly Java byte code;
+D: probably ARM/StrongARM; maybe Sparc; maybe Mips; maybe
+D: Vax. Perhaps Z80 and 6502, just for a laugh?
+
+F: Consider a 'verbose' option that prints information about the resulting object file onto stdout.
+
+F: Line numbers in the .lst file don't match the line numbers in the input.
+D: They probably should, rather than the current matching of the post-preprocessor line numbers.
diff --git a/Wishlist b/Wishlist
deleted file mode 100644 (file)
index ccf7760..0000000
--- a/Wishlist
+++ /dev/null
@@ -1,276 +0,0 @@
-NASM Wishlist
-=============
-
-Numbers on right hand side are version numbers that it would be nice to
-have this done by. ? means I haven't looked at it yet.
-
-- Check misc/ide.cfg into RCS as Watcom IDE enhancement thingy.                0.98
-  (nop@dlc.fi)
-
-- Package the Linux Assembler HOWTO.                                   0.98
-
-- 3DNow!, SSE and other extensions need documenting.                   0.98
-  hpa: Does it really make sense to have a whole instruction set
-  reference packaged with the assembler?
-
-- prototypes of lrotate don't match in test/*. Fix.                    0.98
-
-- Build djgpp binaries for 0.98 onwards. Look into PMODE/W as a stub   0.98
-  - it might be a lot better than CWSDPMI. It's in PMW133.ZIP.
-
-- %undef operator that goes along with %define                         DONE
-
-- Fix `%error' giving error messages twice.                            0.99
-  Not especially important, as changes planned for 1.1x below will make
-  the preprocessor be only called once.
-
-- Sort out problems with OBJ:                                          0.99
-  * TLINK32 doesn't seem to like SEGDEF32 et al. So for that, we
-    should avoid xxx32 records wherever we can.
-  * However, didn't we change _to_ using xxx32 at some stage? Try
-    to remember why and when.
-  * Apparently Delphi's linker has trouble with two or more
-    globals being defined inside a PUBDEF32. Don't even know if it
-    _can_ cope with a PUBDEF16.
-  * Might need extra flags. *sigh*
-
-- Symbol table output may possibly be useful.                          0.99
-  Ken Martwick (kenm@efn.org) wants the following format:
-       labelname       type    offset(hex)     repetition count
-  Possibly include xref addresses after repetition count?
-
-- There are various other bugs in outelf.c that make certain kinds     0.99
-  of relocation not work. See zbrown.asm. Looks like we may have to do
-  a major rewrite of parts of it. Compare some NASM code output with
-  equivalent GAS code output. Look at the ELF spec. Generally fix things.
-
-- NASM is currently using a kludge in ELF that involves defining       0.99
-  a symbol at a zero absolute offset. This isn't needed, as the
-  documented solution to the problem that this solves is to use
-  SHN_UNDEF.
-
-- Debug information, in all formats it can be usefully done in.                0.99
-  * including line-number record support.
-  * "George C. Lindauer" <gclind01@starbase.spd.louisville.edu>
-    wants to have some say in how this goes through.
-  * Andrew Crabtree <andrewc@rosemail.rose.hp.com> wants to help out.
-
-- Think about a line-continuation character.                           0.99
-
-- Consider allowing declaration of two labels on the same line,
-  syntax 'label1[:] label2[:] ... instruction'. Need to investigate
-  feasibility.                                                         0.99
-
-- Quoting of quotes by doubling them, in string and char constants.    0.99
-
-- Two-operand syntax for SEGMENT/SECTION macro to avoid warnings       0.99
-  of ignored section parameters on reissue of __SECT__.
-  Or maybe skip the warning if the given parameters are identical to
-  what was actually stored. Investigate.                               
-
-- Apparently we are not missing a PSRAQ instruction, because it
-  doesn't exist.  Check that it doesn't exist as an undocumented
-  instruction, or something stupid like that.                          0.99
-
-- Any assembled form starting 0x80 can also start 0x82. ndisasm                1.00
-  should know this. New special code in instruction encodings,
-  probably.
-
-- Pointing an EQU at an external symbol now generates an error. There  1.05
-  may be a better way of handling this; we should look into it.
-  Ideally, the label mechanism should be changed to cope with one
-  label being declared relative to another - that may work, but could be
-  a pain to implement (or is it? it may be easy enough that you just
-  need to declare a new offset in the same segment...) This should be done
-  before v1.0 is released. There is a comment regarding this in labels.c,
-  towards the end of the file, which discusses ways of fixing this.
-
-- nested %rep used to cause a panic. Now a more informative error      1.10
-  message is produced. This problem whould be fixed before v1.0.
-  See comment in switch() statement block for PP_REP in do_directive()
-  in preproc.c (line 1585, or thereabouts)
-
-- Contribution: zgraeme.tar contains improved hash table routines      ?
-  contributed by Graeme Defty <graeme@HK.Super.NET> for use in the
-  label manager.
-
-- Contribution: zsyntax.zip contains a syntax-highlighting mode for    ?
-  NASM, for use with the Aurora text editor (??).
-
-- Contribution: zvim.zip contains a syntax-highlighting mode for       ?
-  NASM, for use with vim.
-
-- Contribution: zkendal1.zip and zkendal2.zip contain Kendall          ?
-  Bennett's (<KendallB@scitechsoft.com>) alternative syntax stuff,
-  providing an alternative syntax mode for NASM which allows a macro
-  set to be written that allows the same source files to be
-  assembled with NASM and TASM.
-
-- Add the UD2 instruction.                                             DONE
-
-- Add the four instructions documented in 24368901.pdf (Intel's own    DONE
-  document).
-
-- Some means of avoiding MOV memoffs,EAX which apparently the          1.10?
-  Pentium pairing detector thinks modifies EAX. Similar means of
-  choosing instruction encodings where necessary.
-
-- The example of ..@ makes it clear that a ..@ label isn't just                ?
-  local, but doesn't make it clear that it isn't just global either.
-
-- hpa wants an evaluator operator for ceil(log2(x)).                   ?
-
-- Extra reloc types in ELF: R_386_16 type 20, PC16 is 21, 8 is 22, PC8 is 23.
-  Add support for the 16s at least.                                    ?
-
-
-- Lazy section creation or selective section output, in COFF/win32     ?
-  at least and probably other formats: don't bother to emit a section
-  if it contains no data. Particularly the default auto-created
-  section. We believe zero-length sections crash at least WLINK (in
-  win32).
-
-- Make the flags field in `struct itemplate' in insns.h a long         ?
-  instead of an int.
-
-- Implement %ifref to check whether a single-line macro has ever been  ?
-  expanded since (last re) definition. Or maybe not. We'll see.
-
-- add pointer to \k{insLEAVE} and \k{insENTER} in chapters about       ?
-  mixed-language programming.
-
-- Some equivalent to TASM's GLOBAL directive, ie something which       ?
-  defines a symbol as external if it doesn't end up being defined
-  but defines it as public if it does end up being defined.
-
-- Documentation doesn't explain about C++ name mangling.               ?
-
-- see if BITS can be made to do anything sensible in obj (eg set the   ?
-  default new-segment property to Use32).
-
-- OBJ: coalesce consecutive offset and segment fixups for the same     ?
-  location into full-32bit-pointer fixups. This is apparently
-  necessary because some twazzock in the PowerBASIC development
-  team didn't deign to support the OMF spec the way the rest of the
-  world sees it.
-
-- Allow % to be separated from the rest of a preproc directive, for    ?
-  alternative directive indentation styles.
-
-- __DATE__, __TIME__, and text variants of __NASM_MAJOR__ and          ?
-  __NASM_MINOR__.
-
-- Warn on TIMES combined with multi-line macros. TIMES gets applied    1.00
-  to first line only - should bring to users' attention.
-
-- Re-work the evaluator, again, with a per-object-format fixup         1.10
-  routine, so as to be able to cope with section offsets "really"
-  being pure numbers; should be able to allow at _least_ the two
-  common idioms
-     TIMES 510-$ DB 0            ; bootsector
-     MOV AX,(PROG_END-100H)/16   ; .COM TSR
-  Would need to call the fixup throughout the evaluator, and the
-  fixup would have to be allowed to return UNKNOWN on pass one if it
-  had to. (_Always_ returning UNKNOWN on pass one, though a lovely
-  clean design, breaks the first of the above examples.)
-
-- Preprocessor identifier concatenation?                               1.10
-
-- Arbitrary section names in `bin'.                                    ?
-  Is this necessary? Is it even desirable?
-  hpa: Desirable, yes.  Necessary?  Probably not, but there are
-  definitely cases where it becomes quite useful.
-
-- Ability to read from a pipe. Obviously not useful under dos, so      1.10
-  memory problems with storing entire input file aren't a problem
-  either.
-
-  Related topic: file caching under DOS/32 bit...                      1.10?
-  maybe even implement discardable buffers that get thrown away
-  when we get a NULL returned from malloc(). Only really useful under
-  DOS. Think about it.
-
-  Another related topic: possibly spool out the pre-processed          1.10?
-  stuff to a file, to avoid having to re-process it. Possible problems
-  with preprocessor values not known on pass 1? Have a look...
-
-  Or maybe we can spool out a pre-parsed version...?                   1.10
-  Need to investigate feasibility. Does the results from the parser
-  change from pass 1 to pass 2? Would it be feasible to alter it so that
-  the parser returns an invariant result, and this is then processed
-  afterwards to resolve label references, etc?
-
-- Subsection support?                                                  ?
-
-- A good ALIGN mechanism, similar to GAS's. GAS pads out space by      1.10?
-  means of the following (32-bit) instructions:
-          8DB42600000000    lea esi,[esi+0x0]
-          8DB600000000      lea esi,[esi+0x0]
-          8D742600          lea esi,[esi+0x0]
-          8D7600            lea esi,[esi+0x0]
-          8D36              lea esi,[esi]
-          90                nop
-  It uses up to two of these instructions to do up to 14-byte pads;
-  when more than 14 bytes are needed, it issues a (short) jump to
-  the end of the padded section and then NOPs the rest. Come up with
-  a similar scheme for 16 bit mode, and also come up with a way to
-  use it - internal to the assembler, so that programs using ALIGN
-  don't knock over preprocess-only mode.
-    Also re-work the macro form so that when given one argument in a
-  code section it calls this feature.
-
-- Possibly a means whereby FP constants can be specified as            ?
-  immediate operands to non-FP instructions.
-  * Possible syntax: MOV EAX,FLOAT 1.2 to get a single-precision FP
-    constant. Then maybe MOV EAX,HI_FLOAT 1.2 and MOV EAX,LO_FLOAT
-    1.2 to get the two halves of a double-precision one. Best to
-    ignore extended-precision in case it bites.
-  * Alternatively, maybe MOV EAX,FLOAT(4,0-4,1.2) to get bytes 0-4
-    (ie 0-3) of a 4-byte constant. Then HI_FLOAT is FLOAT(8,4-8,x)
-    and LO_FLOAT is FLOAT(8,0-4,x). But this version allows two-byte
-    chunks, one-byte chunks, even stranger chunks, and pieces of
-    ten-byte reals to be bandied around as well.
-
-- A UNION macro might be quite cool, now that ABSOLUTE is sane         ?
-  enough to be able to handle it.
-
-- An equivalent to gcc's ## stringify operator, plus string            ?
-  concatenation, somehow implemented without undue ugliness, so as
-  to be able to do `%include "/my/path/%1"' in a macro, or something
-  similar...
-
-- Actually _do_ something with the processor, privileged and           1.10
-  undocumented flags in the instruction table. When this happens,
-  consider allowing PMULHRW to map to either of the Cyrix or AMD
-  versions?
-  hpa: The -p option to ndisasm now uses this to some extent.
-
-- Maybe NEC V20/V30 instructions?                                      ?
-  hpa: What are they?  Should be trivial to implement.
-
-- Yet more object formats.
-  * Possibly direct support for .EXE files?                            1.10
-
-- Symbol map in binary format. Format-specific options...              1.10?
-
-- REDESIGN: Think about EQU dependency, and about start-point          1.20?
-  specification in OBJ. Possibly re-think directive support.
-
-- Think about a wrapper program like gcc? Possibly invent a _patch_    2.00?
-  for gcc so that it can take .asm files on the command line?
-
-- If a wrapper happens, think about adding an option to cause the      ?
-  resulting executable file to be executed immediately, thus
-  allowing NASM source files to have #!... (probably silly)
-
-- Multi-platform support? If so: definitely Alpha; possibly Java       ?
-  byte code; probably ARM/StrongARM; maybe Sparc; maybe Mips; maybe
-  Vax. Perhaps Z80 and 6502, just for a laugh?
-
-- Consider a 'verbose' option that prints information about the                ?
-  resulting object file onto stdout.
-
-- Line numbers in the .lst file don't match the line numbers in the    ?
-  input.  They probably should, rather than the current matching
-  of the post-preprocessor line numbers.
-
diff --git a/doc/Changes b/doc/Changes
deleted file mode 100644 (file)
index f383182..0000000
+++ /dev/null
@@ -1,542 +0,0 @@
-Change log for NASM
-===================
-
-This is the Changelog for the official releases; this is a modified
-version.  For the changes from the official release, see the MODIFIED file.
-
-0.90 released October 1996
---------------------------
-
-First release version. First support for object file output. Other
-changes from previous version (0.3x) too numerous to document.
-
-0.91 released November 1996
----------------------------
-
-Loads of bug fixes.
-Support for RDF added.
-Support for DBG debugging format added.
-Support for 32-bit extensions to Microsoft OBJ format added.
-Revised for Borland C: some variable names changed, makefile added.
-LCC support revised to actually work.
-JMP/CALL NEAR/FAR notation added.
-`a16', `o16', `a32' and `o32' prefixes added.
-Range checking on short jumps implemented.
-MMX instruction support added.
-Negative floating point constant support added.
-Memory handling improved to bypass 64K barrier under DOS.
-$ prefix to force treatment of reserved words as identifiers added.
-Default-size mechanism for object formats added.
-Compile-time configurability added.
-`#', `@', `~' and `?' are now valid characters in labels.
-`-e' and `-k' options in NDISASM added.
-
-0.92 released January 1997
---------------------------
-
-The FDIVP/FDIVRP and FSUBP/FSUBRP pairs had been inverted: this was
-fixed. This also affected the LCC driver.
-
-Fixed a bug regarding 32-bit effective addresses of the form
-[other_register+ESP].
-
-Documentary changes, notably documentation of the fact that Borland
-Win32 compilers use `obj' rather than `win32' object format.
-
-Fixed the COMENT record in OBJ files, which was formatted
-incorrectly.
-
-Fixed a bug causing segfaults in large RDF files.
-
-OBJ format now strips initial periods from segment and group
-definitions, in order to avoid complications with the local label
-syntax.
-
-Fixed a bug in disassembling far calls and jumps in NDISASM.
-
-Added support for user-defined sections in COFF and ELF files.
-
-Compiled the DOS binaries with a sensible amount of stack, to
-prevent stack overflows on any arithmetic expression containing
-parentheses.
-
-Fixed a bug in handling of files that do not terminate in a newline.
-
-0.93 released January 1997
---------------------------
-
-This release went out in a great hurry after semi-crippling bugs
-were found in 0.92.
-
-Really _did_ fix the stack overflows this time. *blush*
-
-Had problems with EA instruction sizes changing between passes, when
-an offset contained a forward reference and so 4 bytes were
-allocated for the offset in pass one; by pass two the symbol had
-been defined and happened to be a small absolute value, so only 1
-byte got allocated, causing instruction size mismatch between passes
-and hence incorrect address calculations. Fixed.
-
-Stupid bug in the revised ELF section generation fixed (associated
-string-table section for .symtab was hard-coded as 7, even when this
-didn't fit with the real section table). Was causing `ld' to
-seg-fault under Linux.
-
-Included a new Borland C makefile, Makefile.bc2, donated by Fox
-Cutter <lmb@comtch.iea.com>.
-
-0.94 released April 1997
-------------------------
-
-Major item: added the macro processor.
-
-Added undocumented instructions SMI, IBTS, XBTS and LOADALL286. Also
-reorganised CMPXCHG instruction into early-486 and Pentium forms.
-Thanks to Thobias Jones for the information.
-
-Fixed two more stupid bugs in ELF, which were causing `ld' to
-continue to seg-fault in a lot of non-trivial cases.
-
-Fixed a seg-fault in the label manager.
-
-Stopped FBLD and FBSTP from _requiring_ the TWORD keyword, which is
-the only option for BCD loads/stores in any case.
-
-Ensured FLDCW, FSTCW and FSTSW can cope with the WORD keyword, if
-anyone bothers to provide it. Previously they complained unless no
-keyword at all was present.
-
-Some forms of FDIV/FDIVR and FSUB/FSUBR were still inverted: a
-vestige of a bug that I thought had been fixed in 0.92. This was
-fixed, hopefully for good this time...
-
-Another minor phase error (insofar as a phase error can _ever_ be
-minor) fixed, this one occurring in code of the form
-   rol ax,forward_reference
-   forward_reference equ 1
-
-The number supplied to TIMES is now sanity-checked for positivity,
-and also may be greater than 64K (which previously didn't work on
-16-bit systems).
-
-Added Watcom C makefiles, and misc/pmw.bat, donated by Dominik Behr.
-
-Added the INCBIN pseudo-opcode.
-
-Due to the advent of the preprocessor, the [INCLUDE] and [INC]
-directives have become obsolete. They are still supported in this
-version, with a warning, but won't be in the next.
-
-Fixed a bug in OBJ format, which caused incorrect object records to
-be output when absolute labels were made global.
-
-Updates to RDOFF subdirectory, and changes to outrdf.c.
-
-0.95 released July 1997
------------------------
-
-Fixed yet another ELF bug. This one manifested if the user relied on
-the default segment, and attempted to define global symbols without
-first explicitly declaring the target segment.
-
-Added makefiles (for NASM and the RDF tools) to build Win32 console
-apps under Symantec C++. Donated by Mark Junker.
-
-Added `macros.bas' and `insns.bas', QBasic versions of the Perl
-scripts that convert `standard.mac' to `macros.c' and convert
-`insns.dat' to `insnsa.c' and `insnsd.c'. Also thanks to Mark
-Junker.
-
-Changed the diassembled forms of the conditional instructions so
-that JB is now emitted as JC, and other similar changes. Suggested
-list by Ulrich Doewich.
-
-Added `@' to the list of valid characters to begin an identifier
-with.
-
-Documentary changes, notably the addition of the `Common Problems'
-section in nasm.doc.
-
-Fixed a bug relating to 32-bit PC-relative fixups in OBJ.
-
-Fixed a bug in perm_copy() in labels.c which was causing exceptions
-in cleanup_labels() on some systems.
-
-Positivity sanity check in TIMES argument changed from a warning to
-an error following a further complaint.
-
-Changed the acceptable limits on byte and word operands to allow
-things like `~10111001b' to work.
-
-Fixed a major problem in the preprocessor which caused seg-faults if
-macro definitions contained blank lines or comment-only lines.
-
-Fixed inadequate error checking on the commas separating the
-arguments to `db', `dw' etc.
-
-Fixed a crippling bug in the handling of macros with operand counts
-defined with a `+' modifier.
-
-Fixed a bug whereby object file formats which stored the input file
-name in the output file (such as OBJ and COFF) weren't doing so
-correctly when the output file name was specified on the command
-line.
-
-Removed [INC] and [INCLUDE] support for good, since they were
-obsolete anyway.
-
-Fixed a bug in OBJ which caused all fixups to be output in 16-bit
-(old-format) FIXUPP records, rather than putting the 32-bit ones in
-FIXUPP32 (new-format) records.
-
-Added, tentatively, OS/2 object file support (as a minor variant on
-OBJ).
-
-Updates to Fox Cutter's Borland C makefile, Makefile.bc2.
-
-Removed a spurious second fclose() on the output file.
-
-Added the `-s' command line option to redirect all messages which
-would go to stderr (errors, help text) to stdout instead.
-
-Added the `-w' command line option to selectively suppress some
-classes of assembly warning messages.
-
-Added the `-p' pre-include and `-d' pre-define command-line options.
-
-Added an include file search path: the `-i' command line option.
-
-Fixed a silly little preprocessor bug whereby starting a line with a
-`%!' environment-variable reference caused an `unknown directive'
-error.
-
-Added the long-awaited listing file support: the `-l' command line
-option.
-
-Fixed a problem with OBJ format whereby, in the absence of any
-explicit segment definition, non-global symbols declared in the
-implicit default segment generated spurious EXTDEF records in the
-output.
-
-Added the NASM environment variable.
-
-From this version forward, Win32 console-mode binaries will be
-included in the DOS distribution in addition to the 16-bit binaries.
-Added Makefile.vc for this purpose.
-
-Added `return 0;' to test/objlink.c to prevent compiler warnings.
-
-Added the __NASM_MAJOR__ and __NASM_MINOR__ standard defines.
-
-Added an alternative memory-reference syntax in which prefixing an
-operand with `&' is equivalent to enclosing it in square brackets,
-at the request of Fox Cutter.
-
-Errors in pass two now cause the program to return a non-zero error
-code, which they didn't before.
-
-Fixed the single-line macro cycle detection, which didn't work at
-all on macros with no parameters (caused an infinite loop). Also
-changed the behaviour of single-line macro cycle detection to work
-like cpp, so that macros like `extrn' as given in the documentation
-can be implemented.
-
-Fixed the implementation of WRT, which was too restrictive in that
-you couldn't do `mov ax,[di+abc wrt dgroup]' because (di+abc) wasn't
-a relocatable reference.
-
-0.96 released November 1997
----------------------------
-
-Fixed a bug whereby, if `nasm sourcefile' would cause a filename
-collision warning and put output into `nasm.out', then `nasm
-sourcefile -o outputfile' still gave the warning even though the
-`-o' was honoured.
-
-Fixed name pollution under Digital UNIX: one of its header files
-defined R_SP, which broke the enum in nasm.h.
-
-Fixed minor instruction table problems: FUCOM and FUCOMP didn't have
-two-operand forms; NDISASM didn't recognise the longer register
-forms of PUSH and POP (eg FF F3 for PUSH BX); TEST mem,imm32 was
-flagged as undocumented; the 32-bit forms of CMOV had 16-bit operand
-size prefixes; `AAD imm' and `AAM imm' are no longer flagged as
-undocumented because the Intel Architecture reference documents
-them.
-
-Fixed a problem with the local-label mechanism, whereby strange
-types of symbol (EQUs, auto-defined OBJ segment base symbols)
-interfered with the `previous global label' value and screwed up
-local labels.
-
-Fixed a bug whereby the stub preprocessor didn't communicate with
-the listing file generator, so that the -a and -l options in
-conjunction would produce a useless listing file.
-
-Merged `os2' object file format back into `obj', after discovering
-that `obj' _also_ shouldn't have a link pass separator in a module
-containing a non-trivial MODEND. Flat segments are now declared
-using the FLAT attribute. `os2' is no longer a valid object format
-name: use `obj'.
-
-Removed the fixed-size temporary storage in the evaluator. Very very
-long expressions (like `mov ax,1+1+1+1+...' for two hundred 1s or
-so) should now no longer crash NASM.
-
-Fixed a bug involving segfaults on disassembly of MMX instructions,
-by changing the meaning of one of the operand-type flags in nasm.h.
-This may cause other apparently unrelated MMX problems; it needs to
-be tested thoroughly.
-
-Fixed some buffer overrun problems with large OBJ output files.
-Thanks to DJ Delorie for the bug report and fix.
-
-Made preprocess-only mode actually listen to the %line markers as it
-prints them, so that it can report errors more sanely.
-
-Re-designed the evaluator to keep more sensible track of expressions
-involving forward references: can now cope with previously-nightmare
-situations such as
-   mov ax,foo | bar
-   foo equ 1
-   bar equ 2
-
-Added the ALIGN and ALIGNB standard macros.
-
-Added PIC support in ELF: use of WRT to obtain the four extra
-relocation types needed.
-
-Added the ability for output file formats to define their own
-extensions to the GLOBAL, COMMON and EXTERN directives.
-
-Implemented common-variable alignment, and global-symbol type and
-size declarations, in ELF.
-
-Implemented NEAR and FAR keywords for common variables, plus
-far-common element size specification, in OBJ.
-
-Added a feature whereby EXTERNs and COMMONs in OBJ can be given a
-default WRT specification (either a segment or a group).
-
-Transformed the Unix NASM archive into an auto-configuring package.
-
-Added a sanity-check for people applying SEG to things which are
-already segment bases: this previously went unnoticed by the SEG
-processing and caused OBJ-driver panics later.
-
-Added the ability, in OBJ format, to deal with `MOV EAX,<segment>'
-type references: OBJ doesn't directly support dword-size segment
-base fixups, but as long as the low two bytes of the constant term
-are zero, a word-size fixup can be generated instead and it will
-work.
-
-Added the ability to specify sections' alignment requirements in
-Win32 object files and pure binary files.
-
-Added preprocess-time expression evaluation: the %assign (and
-%iassign) directive and the bare %if (and %elif) conditional. Added
-relational operators to the evaluator, for use only in %if
-constructs: the standard relationals = < > <= >= <> (and C-like
-synonyms == and !=) plus low-precedence logical operators &&, ^^ and
-||.
-
-Added a preprocessor repeat construct: %rep / %exitrep / %endrep.
-
-Added the __FILE__ and __LINE__ standard macros.
-
-Added a sanity check for number constants being greater than
-0xFFFFFFFF. The warning can be disabled.
-
-Added the %0 token whereby a variadic multi-line macro can tell how
-many parameters it's been given in a specific invocation.
-
-Added %rotate, allowing multi-line macro parameters to be cycled.
-
-Added the `*' option for the maximum parameter count on multi-line
-macros, allowing them to take arbitrarily many parameters.
-
-Added the ability for the user-level forms of EXTERN, GLOBAL and
-COMMON to take more than one argument.
-
-Added the IMPORT and EXPORT directives in OBJ format, to deal with
-Windows DLLs.
-
-Added some more preprocessor %if constructs: %ifidn / %ifidni (exact
-textual identity), and %ifid / %ifnum / %ifstr (token type testing).
-
-Added the ability to distinguish SHL AX,1 (the 8086 version) from
-SHL AX,BYTE 1 (the 286-and-upwards version whose constant happens to
-be 1).
-
-Added NetBSD/FreeBSD/OpenBSD's variant of a.out format, complete
-with PIC shared library features.
-
-Changed NASM's idiosyncratic handling of FCLEX, FDISI, FENI, FINIT,
-FSAVE, FSTCW, FSTENV, and FSTSW to bring it into line with the
-otherwise accepted standard. The previous behaviour, though it was a
-deliberate feature, was a deliberate feature based on a
-misunderstanding. Apologies for the inconvenience.
-
-Improved the flexibility of ABSOLUTE: you can now give it an
-expression rather than being restricted to a constant, and it can
-take relocatable arguments as well.
-
-Added the ability for a variable to be declared as EXTERN multiple
-times, and the subsequent definitions are just ignored.
-
-We now allow instruction prefixes (CS, DS, LOCK, REPZ etc) to be
-alone on a line (without a following instruction).
-
-Improved sanity checks on whether the arguments to EXTERN, GLOBAL
-and COMMON are valid identifiers.
-
-Added misc/exebin.mac to allow direct generation of .EXE files by
-hacking up an EXE header using DB and DW; also added test/binexe.asm
-to demonstrate the use of this. Thanks to Yann Guidon for
-contributing the EXE header code.
-
-ndisasm forgot to check whether the input file had been successfully
-opened. Now it does. Doh!
-
-Added the Cyrix extensions to the MMX instruction set.
-
-Added a hinting mechanism to allow [EAX+EBX] and [EBX+EAX] to be
-assembled differently. This is important since [ESI+EBP] and
-[EBP+ESI] have different default base segment registers.
-
-Added support for the PharLap OMF extension for 4096-byte segment
-alignment.
-
-0.97 released December 1997
----------------------------
-
-This was entirely a bug-fix release to 0.96, which seems to have got
-cursed. Silly me.
-
-Fixed stupid mistake in OBJ which caused `MOV EAX,<constant>' to
-fail. Caused by an error in the `MOV EAX,<segment>' support.
-
-ndisasm hung at EOF when compiled with lcc on Linux because lcc on
-Linux somehow breaks feof(). ndisasm now does not rely on feof().
-
-A heading in the documentation was missing due to a markup error in
-the indexing. Fixed.
-
-Fixed failure to update all pointers on realloc() within extended-
-operand code in parser.c. Was causing wrong behaviour and seg faults
-on lines such as `dd 0.0,0.0,0.0,0.0,...'
-
-Fixed a subtle preprocessor bug whereby invoking one multi-line
-macro on the first line of the expansion of another, when the second
-had been invoked with a label defined before it, didn't expand the
-inner macro. 
-
-Added internal.doc back in to the distribution archives - it was
-missing in 0.96 *blush*
-
-Fixed bug causing 0.96 to be unable to assemble its own test files,
-specifically objtest.asm. *blush again*
-
-Fixed seg-faults and bogus error messages caused by mismatching
-%rep and %endrep within multi-line macro definitions.
-
-Fixed a problem with buffer overrun in OBJ, which was causing
-corruption at ends of long PUBDEF records.
-
-Separated DOS archives into main-program and documentation to reduce
-download size.
-
-0.98 released May 1999
-----------------------
-
-Fixed a bug whereby STRUC didn't work at all in RDF.
-
-Fixed a problem with group specification in PUBDEFs in OBJ.
-
-Improved ease of adding new output formats. Contribution due to
-Fox Cutter.
-
-Fixed a bug in relocations in the `bin' format: was showing up when
-a relocatable reference crossed an 8192-byte boundary in any output
-section.
-
-Fixed a bug in local labels: local-label lookups were inconsistent
-between passes one and two if an EQU occurred between the definition
-of a global label and the subsequent use of a local label local to
-that global.
-
-Fixed a seg-fault in the preprocessor (again) which happened when
-you use a blank line as the first line of a multi-line macro
-definition and then defined a label on the same line as a call to
-that macro.
-
-Fixed a stale-pointer bug in the handling of the NASM environment
-variable. Thanks to Thomas McWilliams.
-
-ELF had a hard limit on the number of sections which caused
-segfaults when transgressed. Fixed.
-
-Added ability for ndisasm to read from stdin by using `-' as the
-filename.
-
-ndisasm wasn't outputting the TO keyword. Fixed.
-
-Fixed error cascade on bogus expression in %if - an error in
-evaluation was causing the entire %if to be discarded, thus creating
-trouble later when the %else or %endif was encountered.
-
-Forward reference tracking was instruction-granular not operand-
-granular, which was causing 286-specific code to be generated
-needlessly on code of the form `shr word [forwardref],1'. Thanks to
-Jim Hague for sending a patch.
-
-All messages now appear on stdout, as sending them to stderr serves
-no useful purpose other than to make redirection difficult.
-
-Fixed the problem with EQUs pointing to an external symbol - this
-now generates an error message.
-
-Allowed multiple size prefixes to an operand, of which only the first
-is taken into account.
-
-Incorporated John Fine's changes, including fixes of a large number
-of preprocessor bugs, some small problems in OBJ, and a reworking of
-label handling to define labels before their line is assembled, rather
-than after.
-
-Reformatted a lot of the source code to be more readable. Included
-'coding.txt' as a guideline for how to format code for contributors.
-
-Stopped nested %reps causing a panic - they now cause a slightly more
-friendly error message instead.
-
-Fixed floating point constant problems (patch by Pedro Gimeno)
-
-Fixed the return value of insn_size() not being checked for -1, indicating
-an error.
-
-Incorporated 3D now instructions.
-
-Fixed the 'mov eax, eax + ebx' bug.
-
-Fixed the GLOBAL EQU bug in ELF. Released developers release 3.
-
-Incorporated John Fine's command line parsing changes
-
-Incorporated David Lindauer's OMF debug support
-
-Made changes for LCC 4.0 support (__NASM_CDecl__, removed register size
-specification warning when sizes agree).
-
-Released NASM 0.98 Pre-release 1
-
-fixed bug in outcoff.c to do with truncating section names longer
-than 8 characters, referencing beyond end of string; 0.98 pre-release 2
-
-added response file support, improved command line handling, new layout
-help screen
-
-fixed limit checking bug, 'OUT byte nn, reg' bug, and a couple of rdoff
-related bugs, updated Wishlist; 0.98 Prerelease 3.
-
-See the file "MODIFIED" for changes after 0.98p3.
diff --git a/doc/License b/doc/License
deleted file mode 100644 (file)
index c85c212..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-
-Terms and Conditions for the use of the Netwide Assembler
-=========================================================
-
-Can I have the gist without reading the legalese?
--------------------------------------------------
-
-Basically, NASM is free. You can't charge for it. You can copy it as
-much as you like. You can incorporate it, or bits of it, into other
-free programs if you want. (But we want to know about it if you do,
-and we want to be mentioned in the credits.) We may well allow you
-to incorporate it into commercial software too, but we'll probably
-demand some money for it, and we'll certainly demand to be given
-credit. And in extreme cases (although I can't immediately think of
-a reason we might actually want to do this) we may refuse to let you
-do it at all.
-
-NASM LICENCE AGREEMENT
-======================
-
-By "the Software" this licence refers to the complete contents of
-the NASM archive, excluding this licence document itself, and
-excluding the contents of the `test' directory. The Netwide
-Disassembler, NDISASM, is specifically included under this licence.
-
-I. The Software is freely redistributable; anyone may copy the
-Software, or parts of the Software, and give away as many copies as
-they like to anyone, as long as this licence document is kept with
-the Software. Charging a fee for the Software is prohibited,
-although a fee may be charged for the act of transferring a copy,
-and you can offer warranty protection and charge a fee for that.
-
-II. The Software, or parts thereof, may be incorporated into other
-freely redistributable software (by which we mean software that may
-be obtained free of charge) without requiring permission from the
-authors, as long as due credit is given to the authors of the
-Software in the resulting work, as long as the authors are informed
-of this action if possible, and as long as those parts of the
-Software that are used remain under this licence.
-
-III. Modified forms of the Software may be created and distributed
-as long as the authors are informed of this action if possible, as
-long as the resulting work remains under this licence, as long as
-the modified form of the Software is distributed with documentation
-which still gives credit to the original authors of the Software,
-and as long as the modified form of the Software is distributed with
-a clear statement that it is not the original form of the Software
-in the form that it was distributed by the authors.
-
-IV. The Software, or parts thereof, may be incorporated into other
-software which is not freely redistributable (i.e. software for
-which a fee is charged), as long as permission is granted from the
-authors of the Software. The authors reserve the right to grant this
-permission only for a fee, which may at our option take the form of
-royalty payments. The authors also reserve the right to refuse to
-grant permission if they deem it necessary. For further information
-about who exactly the authors are, see clause XI below.
-
-V. The Software may be incorporated, in its original archive form,
-into software collections or archives which are not freely
-redistributable, as long as it is clearly stated that the Software
-itself remains freely redistributable and remains under this licence
-and no other. Such collections are deemed not to fall under article
-IV of this licence.
-
-VI. Object files or programs generated by the Software as output do
-not fall under this licence at all, and may be placed under any
-licence the author wishes. The authors explicitly lay no claim to,
-and assert no rights over, any programs written by other people and
-assembled into object form by the Software.
-
-VII. You may not copy, modify or distribute the Software except
-under the terms given in this licence document. You may not
-sublicense the Software or in any way place it under any other
-licence than this one. Since you have not signed this licence, you
-are not of course required to accept it; however, no other licence
-applies to the Software, and nothing else grants you any permission
-to copy, modify, sublicense or distribute the Software in any way.
-These actions are therefore prohibited if you do not accept this
-licence.
-
-VIII. There is no warranty for the Software, to the extent permitted
-by applicable law. The authors provide the Software "as is" without
-warranty of any kind, either expressed or implied, including but not
-limited to the implied warranties of merchantability and fitness for
-a particular purpose. The entire risk as to the quality and
-performance of the Software is with you. Should the Software prove
-defective, you assume the cost of all necessary servicing, repair or
-correction.
-
-IX. In no event, unless required by applicable law or agreed to in
-writing, will any of the authors be liable to you for damages,
-including any general, special, incidental or consequential damages,
-arising out of the use or the inability to use the Software,
-including but not limited to loss of data or data being rendered
-inaccurate or a failure of the Software to operate with any other
-programs, even if you have been advised of the possibility of such
-damages.
-
-X. In addition to what this Licence otherwise provides, the Software
-may be distributed in such a way as to be compliant with the GNU
-General Public Licence, as published by the Free Software Foundation,
-Cambridge, MA, USA; version 2, or, at your option, any later version;
-incorporated herein by reference.  You must include a copy of this
-Licence with such distribution.  Furthermore, patches sent to the
-authors for the purpose of inclusion in the official release version
-are considered cleared for release under the full terms of this
-Licence.
-
-XI. The authors of NASM are the original authors (Simon Tatham and
-Julian Hall) and all those who the original authors feel have
-contributed significantly to the overall project.  If you wish to
-contact the authors, Julian Hall (jules@earthcorp.com) should be your
-first port of call.
-
-XII. Should any part of this agreement be deemed unenforcable, it is
-intended that the remainder of the agreement be held in force.
-
-END OF LICENCE AGREEMENT
diff --git a/doc/Readme b/doc/Readme
deleted file mode 100644 (file)
index dbbd18d..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-
-              NetWide Assembler for the SciTech MGL
-              -------------------------------------
-
-This is a modified distribution of NASM, the Netwide Assembler. NASM
-is a prototype general-purpose x86 assembler. It will currently output
-flat-form binary files, a.out, COFF and ELF Unix object files,
-Microsoft Win32 and 16-bit DOS object files, OS/2 object files, the
-as86 object format, and a home-grown format called RDF.
-
-This version of NASM has been modified by SciTech Software such that it
-can be used to assemble source code in the SciTech MGL graphics library,
-and understands enough of TASM assembler syntax such that both NASM
-and TASM can be used to generate assembler modules for the MGL graphics
-library. A complete macro package is provided as part of the SciTech
-MGL that provides macros to help in building modules that will work with
-either assembler.
-
-A pre-compiled binary of NASM is provided as part of the SciTech MGL
-graphics library, however you may re-build the assembler from the sources
-provided. To do so make sure you have the SciTech Makefile Utilties
-correctly configured for your compiler, and then simly type:
-
-    unset DBG
-    dmake OPT=1
-
-to build an optimised, non-debug version of the assembler. If you wish
-to rebuild for a different OS other than DOS or Win32, you will need to
-first compile the DMAKE make program for your OS. See the DMAKE source
-code for more information.
-
-Licensing issues:
------------------
-
-For information about how you can distribute and use NASM, see the
-file Licence.
-
-The NASM web page is at http://www.cryogen.com/Nasm/
-
-Bug reports specific to the SciTech MGL should be posted to SciTech
-Software MGL newsgroups:
-
-    news://news.scitechsoft.com/scitech.mgl.developer
-
-Bug reports (and patches if you can) for NASM itself that are not SciTech
-MGL related should be sent to the authors at:
-
-    Julian Hall <jules@earthcorp.com>
-    Simon Tatham <anakin@pobox.com>
diff --git a/doc/Wishlist b/doc/Wishlist
deleted file mode 100644 (file)
index ccf7760..0000000
+++ /dev/null
@@ -1,276 +0,0 @@
-NASM Wishlist
-=============
-
-Numbers on right hand side are version numbers that it would be nice to
-have this done by. ? means I haven't looked at it yet.
-
-- Check misc/ide.cfg into RCS as Watcom IDE enhancement thingy.                0.98
-  (nop@dlc.fi)
-
-- Package the Linux Assembler HOWTO.                                   0.98
-
-- 3DNow!, SSE and other extensions need documenting.                   0.98
-  hpa: Does it really make sense to have a whole instruction set
-  reference packaged with the assembler?
-
-- prototypes of lrotate don't match in test/*. Fix.                    0.98
-
-- Build djgpp binaries for 0.98 onwards. Look into PMODE/W as a stub   0.98
-  - it might be a lot better than CWSDPMI. It's in PMW133.ZIP.
-
-- %undef operator that goes along with %define                         DONE
-
-- Fix `%error' giving error messages twice.                            0.99
-  Not especially important, as changes planned for 1.1x below will make
-  the preprocessor be only called once.
-
-- Sort out problems with OBJ:                                          0.99
-  * TLINK32 doesn't seem to like SEGDEF32 et al. So for that, we
-    should avoid xxx32 records wherever we can.
-  * However, didn't we change _to_ using xxx32 at some stage? Try
-    to remember why and when.
-  * Apparently Delphi's linker has trouble with two or more
-    globals being defined inside a PUBDEF32. Don't even know if it
-    _can_ cope with a PUBDEF16.
-  * Might need extra flags. *sigh*
-
-- Symbol table output may possibly be useful.                          0.99
-  Ken Martwick (kenm@efn.org) wants the following format:
-       labelname       type    offset(hex)     repetition count
-  Possibly include xref addresses after repetition count?
-
-- There are various other bugs in outelf.c that make certain kinds     0.99
-  of relocation not work. See zbrown.asm. Looks like we may have to do
-  a major rewrite of parts of it. Compare some NASM code output with
-  equivalent GAS code output. Look at the ELF spec. Generally fix things.
-
-- NASM is currently using a kludge in ELF that involves defining       0.99
-  a symbol at a zero absolute offset. This isn't needed, as the
-  documented solution to the problem that this solves is to use
-  SHN_UNDEF.
-
-- Debug information, in all formats it can be usefully done in.                0.99
-  * including line-number record support.
-  * "George C. Lindauer" <gclind01@starbase.spd.louisville.edu>
-    wants to have some say in how this goes through.
-  * Andrew Crabtree <andrewc@rosemail.rose.hp.com> wants to help out.
-
-- Think about a line-continuation character.                           0.99
-
-- Consider allowing declaration of two labels on the same line,
-  syntax 'label1[:] label2[:] ... instruction'. Need to investigate
-  feasibility.                                                         0.99
-
-- Quoting of quotes by doubling them, in string and char constants.    0.99
-
-- Two-operand syntax for SEGMENT/SECTION macro to avoid warnings       0.99
-  of ignored section parameters on reissue of __SECT__.
-  Or maybe skip the warning if the given parameters are identical to
-  what was actually stored. Investigate.                               
-
-- Apparently we are not missing a PSRAQ instruction, because it
-  doesn't exist.  Check that it doesn't exist as an undocumented
-  instruction, or something stupid like that.                          0.99
-
-- Any assembled form starting 0x80 can also start 0x82. ndisasm                1.00
-  should know this. New special code in instruction encodings,
-  probably.
-
-- Pointing an EQU at an external symbol now generates an error. There  1.05
-  may be a better way of handling this; we should look into it.
-  Ideally, the label mechanism should be changed to cope with one
-  label being declared relative to another - that may work, but could be
-  a pain to implement (or is it? it may be easy enough that you just
-  need to declare a new offset in the same segment...) This should be done
-  before v1.0 is released. There is a comment regarding this in labels.c,
-  towards the end of the file, which discusses ways of fixing this.
-
-- nested %rep used to cause a panic. Now a more informative error      1.10
-  message is produced. This problem whould be fixed before v1.0.
-  See comment in switch() statement block for PP_REP in do_directive()
-  in preproc.c (line 1585, or thereabouts)
-
-- Contribution: zgraeme.tar contains improved hash table routines      ?
-  contributed by Graeme Defty <graeme@HK.Super.NET> for use in the
-  label manager.
-
-- Contribution: zsyntax.zip contains a syntax-highlighting mode for    ?
-  NASM, for use with the Aurora text editor (??).
-
-- Contribution: zvim.zip contains a syntax-highlighting mode for       ?
-  NASM, for use with vim.
-
-- Contribution: zkendal1.zip and zkendal2.zip contain Kendall          ?
-  Bennett's (<KendallB@scitechsoft.com>) alternative syntax stuff,
-  providing an alternative syntax mode for NASM which allows a macro
-  set to be written that allows the same source files to be
-  assembled with NASM and TASM.
-
-- Add the UD2 instruction.                                             DONE
-
-- Add the four instructions documented in 24368901.pdf (Intel's own    DONE
-  document).
-
-- Some means of avoiding MOV memoffs,EAX which apparently the          1.10?
-  Pentium pairing detector thinks modifies EAX. Similar means of
-  choosing instruction encodings where necessary.
-
-- The example of ..@ makes it clear that a ..@ label isn't just                ?
-  local, but doesn't make it clear that it isn't just global either.
-
-- hpa wants an evaluator operator for ceil(log2(x)).                   ?
-
-- Extra reloc types in ELF: R_386_16 type 20, PC16 is 21, 8 is 22, PC8 is 23.
-  Add support for the 16s at least.                                    ?
-
-
-- Lazy section creation or selective section output, in COFF/win32     ?
-  at least and probably other formats: don't bother to emit a section
-  if it contains no data. Particularly the default auto-created
-  section. We believe zero-length sections crash at least WLINK (in
-  win32).
-
-- Make the flags field in `struct itemplate' in insns.h a long         ?
-  instead of an int.
-
-- Implement %ifref to check whether a single-line macro has ever been  ?
-  expanded since (last re) definition. Or maybe not. We'll see.
-
-- add pointer to \k{insLEAVE} and \k{insENTER} in chapters about       ?
-  mixed-language programming.
-
-- Some equivalent to TASM's GLOBAL directive, ie something which       ?
-  defines a symbol as external if it doesn't end up being defined
-  but defines it as public if it does end up being defined.
-
-- Documentation doesn't explain about C++ name mangling.               ?
-
-- see if BITS can be made to do anything sensible in obj (eg set the   ?
-  default new-segment property to Use32).
-
-- OBJ: coalesce consecutive offset and segment fixups for the same     ?
-  location into full-32bit-pointer fixups. This is apparently
-  necessary because some twazzock in the PowerBASIC development
-  team didn't deign to support the OMF spec the way the rest of the
-  world sees it.
-
-- Allow % to be separated from the rest of a preproc directive, for    ?
-  alternative directive indentation styles.
-
-- __DATE__, __TIME__, and text variants of __NASM_MAJOR__ and          ?
-  __NASM_MINOR__.
-
-- Warn on TIMES combined with multi-line macros. TIMES gets applied    1.00
-  to first line only - should bring to users' attention.
-
-- Re-work the evaluator, again, with a per-object-format fixup         1.10
-  routine, so as to be able to cope with section offsets "really"
-  being pure numbers; should be able to allow at _least_ the two
-  common idioms
-     TIMES 510-$ DB 0            ; bootsector
-     MOV AX,(PROG_END-100H)/16   ; .COM TSR
-  Would need to call the fixup throughout the evaluator, and the
-  fixup would have to be allowed to return UNKNOWN on pass one if it
-  had to. (_Always_ returning UNKNOWN on pass one, though a lovely
-  clean design, breaks the first of the above examples.)
-
-- Preprocessor identifier concatenation?                               1.10
-
-- Arbitrary section names in `bin'.                                    ?
-  Is this necessary? Is it even desirable?
-  hpa: Desirable, yes.  Necessary?  Probably not, but there are
-  definitely cases where it becomes quite useful.
-
-- Ability to read from a pipe. Obviously not useful under dos, so      1.10
-  memory problems with storing entire input file aren't a problem
-  either.
-
-  Related topic: file caching under DOS/32 bit...                      1.10?
-  maybe even implement discardable buffers that get thrown away
-  when we get a NULL returned from malloc(). Only really useful under
-  DOS. Think about it.
-
-  Another related topic: possibly spool out the pre-processed          1.10?
-  stuff to a file, to avoid having to re-process it. Possible problems
-  with preprocessor values not known on pass 1? Have a look...
-
-  Or maybe we can spool out a pre-parsed version...?                   1.10
-  Need to investigate feasibility. Does the results from the parser
-  change from pass 1 to pass 2? Would it be feasible to alter it so that
-  the parser returns an invariant result, and this is then processed
-  afterwards to resolve label references, etc?
-
-- Subsection support?                                                  ?
-
-- A good ALIGN mechanism, similar to GAS's. GAS pads out space by      1.10?
-  means of the following (32-bit) instructions:
-          8DB42600000000    lea esi,[esi+0x0]
-          8DB600000000      lea esi,[esi+0x0]
-          8D742600          lea esi,[esi+0x0]
-          8D7600            lea esi,[esi+0x0]
-          8D36              lea esi,[esi]
-          90                nop
-  It uses up to two of these instructions to do up to 14-byte pads;
-  when more than 14 bytes are needed, it issues a (short) jump to
-  the end of the padded section and then NOPs the rest. Come up with
-  a similar scheme for 16 bit mode, and also come up with a way to
-  use it - internal to the assembler, so that programs using ALIGN
-  don't knock over preprocess-only mode.
-    Also re-work the macro form so that when given one argument in a
-  code section it calls this feature.
-
-- Possibly a means whereby FP constants can be specified as            ?
-  immediate operands to non-FP instructions.
-  * Possible syntax: MOV EAX,FLOAT 1.2 to get a single-precision FP
-    constant. Then maybe MOV EAX,HI_FLOAT 1.2 and MOV EAX,LO_FLOAT
-    1.2 to get the two halves of a double-precision one. Best to
-    ignore extended-precision in case it bites.
-  * Alternatively, maybe MOV EAX,FLOAT(4,0-4,1.2) to get bytes 0-4
-    (ie 0-3) of a 4-byte constant. Then HI_FLOAT is FLOAT(8,4-8,x)
-    and LO_FLOAT is FLOAT(8,0-4,x). But this version allows two-byte
-    chunks, one-byte chunks, even stranger chunks, and pieces of
-    ten-byte reals to be bandied around as well.
-
-- A UNION macro might be quite cool, now that ABSOLUTE is sane         ?
-  enough to be able to handle it.
-
-- An equivalent to gcc's ## stringify operator, plus string            ?
-  concatenation, somehow implemented without undue ugliness, so as
-  to be able to do `%include "/my/path/%1"' in a macro, or something
-  similar...
-
-- Actually _do_ something with the processor, privileged and           1.10
-  undocumented flags in the instruction table. When this happens,
-  consider allowing PMULHRW to map to either of the Cyrix or AMD
-  versions?
-  hpa: The -p option to ndisasm now uses this to some extent.
-
-- Maybe NEC V20/V30 instructions?                                      ?
-  hpa: What are they?  Should be trivial to implement.
-
-- Yet more object formats.
-  * Possibly direct support for .EXE files?                            1.10
-
-- Symbol map in binary format. Format-specific options...              1.10?
-
-- REDESIGN: Think about EQU dependency, and about start-point          1.20?
-  specification in OBJ. Possibly re-think directive support.
-
-- Think about a wrapper program like gcc? Possibly invent a _patch_    2.00?
-  for gcc so that it can take .asm files on the command line?
-
-- If a wrapper happens, think about adding an option to cause the      ?
-  resulting executable file to be executed immediately, thus
-  allowing NASM source files to have #!... (probably silly)
-
-- Multi-platform support? If so: definitely Alpha; possibly Java       ?
-  byte code; probably ARM/StrongARM; maybe Sparc; maybe Mips; maybe
-  Vax. Perhaps Z80 and 6502, just for a laugh?
-
-- Consider a 'verbose' option that prints information about the                ?
-  resulting object file onto stdout.
-
-- Line numbers in the .lst file don't match the line numbers in the    ?
-  input.  They probably should, rather than the current matching
-  of the post-preprocessor line numbers.
-
index 353aa80febd31a3dc736526e23b688b405c5f521..c82ad168bcba93983c4caaf05c081004bb824af1 100644 (file)
--- a/insns.dat
+++ b/insns.dat
@@ -830,11 +830,11 @@ PUNPCKHDQ mmxreg,mem          \301\2\x0F\x6A\110            PENT,MMX,SM
 PUNPCKHDQ mmxreg,mmxreg       \2\x0F\x6A\110                PENT,MMX
 PUNPCKHWD mmxreg,mem          \301\2\x0F\x69\110            PENT,MMX,SM
 PUNPCKHWD mmxreg,mmxreg       \2\x0F\x69\110                PENT,MMX
-PUNPCKLBW mmxreg,mem32        \301\2\x0F\x60\110            PENT,MMX
+PUNPCKLBW mmxreg,mem          \301\2\x0F\x60\110            PENT,MMX,SM
 PUNPCKLBW mmxreg,mmxreg       \2\x0F\x60\110                PENT,MMX
-PUNPCKLDQ mmxreg,mem32        \301\2\x0F\x62\110            PENT,MMX
+PUNPCKLDQ mmxreg,mem          \301\2\x0F\x62\110            PENT,MMX,SM
 PUNPCKLDQ mmxreg,mmxreg       \2\x0F\x62\110                PENT,MMX
-PUNPCKLWD mmxreg,mem32        \301\2\x0F\x61\110            PENT,MMX
+PUNPCKLWD mmxreg,mem          \301\2\x0F\x61\110            PENT,MMX,SM
 PUNPCKLWD mmxreg,mmxreg       \2\x0F\x61\110                PENT,MMX
 PUSH      reg16               \320\10\x50                   8086
 PUSH      reg32               \321\10\x50                   386
index c1eacb17e527d13164f8322e013548a79161baaf..914f84c4aa4a75e6ccbd81cbc494fa7c08cd1f94 100644 (file)
--- a/insns.pl
+++ b/insns.pl
@@ -1,5 +1,5 @@
 #!/usr/bin/perl
-#
+# 
 # insns.pl   produce insnsa.c, insnsd.c, insnsi.h, insnsn.c from insns.dat
 #
 # The Netwide Assembler is copyright (C) 1996 Simon Tatham and
index ebc66913e94018bd82ce82789525e7f67ff340b8..f39433a7fc45405640769427f56f188d1aee113a 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-#
+# 
 # install - install a program, script, or datafile
 # This comes from X11R5 (mit/util/scripts/install.sh).
 #
diff --git a/lcc/Readme b/lcc/Readme
deleted file mode 100644 (file)
index 569b9be..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-This directory contains the necessary files to port the C compiler
-``LCC'' (available by FTP from sunsite.doc.ic.ac.uk in the directory
-/computing/programming/languages/c/lcc) to compile for Linux (a.out
-or ELF) by using NASM as a back-end code generator.
-
-This patch has been tested on lcc version 3.6.
-
-To install:
-
-- Copy `x86nasm.md' into the `src' directory of the lcc tree.
-
-- Copy either `lin-elf.c' or `lin-aout.c' into the `etc' directory.
-
-- If you're installing for a.out, edit `x86nasm.md' and change the
-  conditional after the comment reading "CHANGE THIS FOR a.out" in
-  the `defsymbol' function from `#if 0' to `#if 1'.
-
-- Make the following changes to `bind.c' in the `src' directory:
-
-  - Near the top of the file, add a line that reads
-       extern Interface x86nasmIR;
-
-  - In the `bindings' array, add the lines
-        "x86-nasm",      &x86nasmIR,
-        "x86/nasm",      &x86nasmIR,
-    (in sensible looking places...)
-
-  A sample `bind.c' has been provided to show what the result of
-  this might look like. You might be able to get away with using it
-  directly...
-
-- Modify the lcc makefile to include rules for x86nasm.o: this will
-  have to be done in about three places. Just copy any line with
-  `x86' on it and modify it to read `x86nasm' everywhere. (Except
-  that in the list of object files that rcc is made up from, do
-  remember to ensure that every line but the last has a trailing
-  backslash...)
-
-- You may have to modify the contents of `lin-elf.c' or `lin-aout.c'
-  to reflect the true locations of files such as crt0.o, crt1.o,
-  ld-linux.so and so forth. If you don't know where to find these,
-  compile a short C program with `gcc -v' and see what command line
-  gcc feeds to `ld'.
-
-- You should now be able to build lcc, using `lin-elf.c' or
-  `lin-aout.c' as the system-dependent part of the `lcc' wrapper
-  program.
-
-- Symlink x86nasm.c into the `src' directory before attempting the
-  triple test, or the compile will fail.
-
-- Now it should pass the triple test, on either ELF or a.out. Voila!
diff --git a/macros.c b/macros.c
deleted file mode 100644 (file)
index ed70a75..0000000
--- a/macros.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/* This file auto-generated from standard.mac by macros.pl - don't edit it */
-
-static char *stdmac[] = {
-    "%define __NASM_MAJOR__ 0",
-    "%define __NASM_MINOR__ 98",
-    "%define __FILE__",
-    "%define __LINE__",
-    "%define __SECT__",
-    "%imacro section 1+.nolist",
-    "%define __SECT__ [section %1]",
-    "__SECT__",
-    "%endmacro",
-    "%imacro segment 1+.nolist",
-    "%define __SECT__ [segment %1]",
-    "__SECT__",
-    "%endmacro",
-    "%imacro absolute 1+.nolist",
-    "%define __SECT__ [absolute %1]",
-    "__SECT__",
-    "%endmacro",
-    "%imacro struc 1.nolist",
-    "%push struc",
-    "%define %$strucname %1",
-    "[absolute 0]",
-    "%$strucname:",
-    "%endmacro",
-    "%imacro endstruc 0.nolist",
-    "%{$strucname}_size:",
-    "%pop",
-    "__SECT__",
-    "%endmacro",
-    "%imacro istruc 1.nolist",
-    "%push istruc",
-    "%define %$strucname %1",
-    "%$strucstart:",
-    "%endmacro",
-    "%imacro at 1-2+.nolist",
-    "times %1-($-%$strucstart) db 0",
-    "%2",
-    "%endmacro",
-    "%imacro iend 0.nolist",
-    "times %{$strucname}_size-($-%$strucstart) db 0",
-    "%pop",
-    "%endmacro",
-    "%imacro align 1-2+.nolist nop",
-    "times ($$-$) & ((%1)-1) %2",
-    "%endmacro",
-    "%imacro alignb 1-2+.nolist resb 1",
-    "times ($$-$) & ((%1)-1) %2",
-    "%endmacro",
-    "%imacro extern 1-*.nolist",
-    "%rep %0",
-    "[extern %1]",
-    "%rotate 1",
-    "%endrep",
-    "%endmacro",
-    "%imacro bits 1+.nolist",
-    "[bits %1]",
-    "%endmacro",
-    "%imacro global 1-*.nolist",
-    "%rep %0",
-    "[global %1]",
-    "%rotate 1",
-    "%endrep",
-    "%endmacro",
-    "%imacro common 1-*.nolist",
-    "%rep %0",
-    "[common %1]",
-    "%rotate 1",
-    "%endrep",
-    "%endmacro",
-    NULL
-};
index 097cb71286ff4ec51861f693776ea66988f2cd2a..15739f5c9ff4f319eb0221a553c754431b8a5f88 100644 (file)
--- a/macros.pl
+++ b/macros.pl
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-#
+# 
 # macros.pl   produce macros.c from standard.mac
 #
 # The Netwide Assembler is copyright (C) 1996 Simon Tatham and
index 78f078a99160068284014bd957fcf50b6743c6cb..aadd671ecf85890be489c978b6ba0eb6ded5cf55 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
-
 MAJORVER=`grep NASM_MAJOR_VER nasm.h | head -1 | cut -f3 -d' '`
 MINORVER=`grep NASM_MINOR_VER nasm.h | head -1 | cut -f3 -d' '`
 VERSION=`grep NASM_VER nasm.h | head -1 | cut -f3 -d' ' | sed s/\"//g`
index 727628b44aaf365b7bfe77680b86315c854600f2..dbb33671f877428c7af476df59db9b5688efb5e8 100644 (file)
@@ -1,4 +1,6 @@
 #!/usr/bin/perl
+# From: Ed Beroset <beroset@mindspring.com>
+
 my %mem = {};
 my %alloc = {};
 while(<>)
@@ -38,4 +40,3 @@ foreach $goo (sort keys %mem)
                 print "$mem{$goo} $alloc{$goo}";
         }
 }
-# From: Ed Beroset <beroset@mindspring.com>
index d61d88a8fc6482accda0075d2402e6dda1a5888e..32ef67e01590f45be6a3a8aa2dd9c1272ac9bd17 100644 (file)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl
-
 sub StabLine  ($ $ $ $ $ $) {
         local ($comment,$n_strx,$type,$other,$desc,$value) = @_;
         print $comment;
index 8ed2beff942198c70670e2b37e93515e3adcc7e3..88b67a599b4982f57f3c73bb02c3282d1378b160 100644 (file)
@@ -1,7 +1,7 @@
 @echo off
 rem some batch file to bind nasm and ndisasm with pmode/w
 rem a mega cool dos extender for watcom done by tran
-rem
+rem 
 rem max 8 megs, dpmi stack 256*16=4096, no banner
 pmwlite.exe nasm.exe
 pmwsetup.exe /X8388608 /P256 /B0 nasm.exe
diff --git a/misc/simon.jpg b/misc/simon.jpg
new file mode 100644 (file)
index 0000000..574fcb4
Binary files /dev/null and b/misc/simon.jpg differ
diff --git a/nasm-dir b/nasm-dir
new file mode 100755 (executable)
index 0000000..6643851
--- /dev/null
+++ b/nasm-dir
@@ -0,0 +1,5 @@
+#!/bin/sh
+# returns nasm directory
+# used for dist building
+
+basename `pwd`
diff --git a/nasm-version b/nasm-version
new file mode 100755 (executable)
index 0000000..e6de6b9
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+# returns nasm version from nasm.h
+# used for dist building
+
+grep NASM_VER nasm.h | awk -F " " -F "\"" '{print $2}'
diff --git a/nasm.1 b/nasm.1
index 1e68239195624790f11b5189f46204b8dd60d0fa..198a2495ba89aedbbabc0a8ec3a79ffc18d99e55 100644 (file)
--- a/nasm.1
+++ b/nasm.1
@@ -71,6 +71,12 @@ easily redirected.
 Causes
 .B nasm
 to exit immediately, after displaying its version number.
+.I (obsolete)
+.TP
+.BI \-v
+Causes
+.B nasm
+to exit immediately, after displaying its version number.
 .TP
 .BI \-f " format"
 Specifies the output file format. Formats include
diff --git a/nasm.c b/nasm.c
index 14ef45bcbecf446d5cc85805324cc46824ca182c..a0446d839c38f952569e2cefcab5c9f2cbfb5beb 100644 (file)
--- a/nasm.c
+++ b/nasm.c
@@ -80,7 +80,7 @@ static enum op_type operating_mode;
  * doesn't do anything. Initial defaults are given here.
  */
 static char suppressed[1+ERR_WARN_MAX] = {
-    0, TRUE, TRUE, TRUE, FALSE
+  0, TRUE, TRUE, TRUE, FALSE, TRUE
 };
 
 /*
@@ -89,6 +89,7 @@ static char suppressed[1+ERR_WARN_MAX] = {
  */
 static char *suppressed_names[1+ERR_WARN_MAX] = {
     NULL, "macro-params", "macro-selfref", "orphan-labels", "number-overflow",
+    "gnu-elf-extensions"
 };
 
 /*
@@ -100,7 +101,8 @@ static char *suppressed_what[1+ERR_WARN_MAX] = {
     "macro calls with wrong no. of params",
     "cyclic macro self-references",
     "labels alone on lines without trailing `:'",
-    "numeric constants greater than 0xFFFFFFFF"
+    "numeric constants greater than 0xFFFFFFFF",
+    "using 8- or 16-bit relocation in ELF, a GNU extension"
 };
 
 /*
@@ -446,7 +448,7 @@ static int process_arg (char *p, char *q)
                   "    -w+foo      enables warnings about foo; -w-foo disables them\n"
                   "where foo can be:\n");
            for (i=1; i<=ERR_WARN_MAX; i++)
-               printf("    %-16s%s (default %s)\n",
+               printf("    %-23s %s (default %s)\n",
                       suppressed_names[i], suppressed_what[i],
                       suppressed[i] ? "off" : "on");
            printf ("\nresponse files should contain command line parameters"
diff --git a/nasm.h b/nasm.h
index 63400b2c0ba5280487116b9545a4235631de5a7d..ca2c6aaef80c1c830a5c99b3419be946b22da35e 100644 (file)
--- a/nasm.h
+++ b/nasm.h
@@ -13,7 +13,7 @@
 
 #define NASM_MAJOR_VER 0
 #define NASM_MINOR_VER 98
-#define NASM_VER "0.98.26"
+#define NASM_VER "0.98.30"
 
 #ifndef NULL
 #define NULL 0
@@ -97,7 +97,8 @@ typedef void (*efunc) (int severity, char *fmt, ...);
 #define ERR_WARN_OL    0x00000300      /* orphan label (no colon, and
                                        * alone on line) */
 #define ERR_WARN_NOV   0x00000400      /* numeric overflow */
-#define ERR_WARN_MAX   4               /* the highest numbered one */
+#define ERR_WARN_GNUELF        0x00000500      /* using GNU ELF extensions */
+#define ERR_WARN_MAX   5               /* the highest numbered one */
 
 /*
  * -----------------------
diff --git a/outaout.c b/outaout.c
deleted file mode 100644 (file)
index b8e74be..0000000
--- a/outaout.c
+++ /dev/null
@@ -1,933 +0,0 @@
-/* outaout.c   output routines for the Netwide Assembler to produce
- *             Linux a.out object files
- *
- * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
- * Julian Hall. All rights reserved. The software is
- * redistributable under the licence given in the file "Licence"
- * distributed in the NASM archive.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "nasm.h"
-#include "nasmlib.h"
-#include "outform.h"
-
-#if defined OF_AOUT || defined OF_AOUTB
-
-#define RELTYPE_ABSOLUTE 0x00
-#define RELTYPE_RELATIVE 0x01
-#define RELTYPE_GOTPC    0x01   /* no explicit GOTPC in a.out */
-#define RELTYPE_GOTOFF   0x10
-#define RELTYPE_GOT      0x10   /* distinct from GOTOFF bcos sym not sect */
-#define RELTYPE_PLT      0x21
-#define RELTYPE_SYMFLAG  0x08
-
-struct Reloc {
-    struct Reloc *next;
-    long address;                     /* relative to _start_ of section */
-    long symbol;                      /* symbol number or -ve section id */
-    int bytes;                        /* 2 or 4 */
-    int reltype;                      /* see above */
-};
-
-struct Symbol {
-    long strpos;                      /* string table position of name */
-    int type;                         /* symbol type - see flags below */
-    long value;                               /* address, or COMMON variable size */
-    long size;                        /* size for data or function exports */
-    long segment;                     /* back-reference used by gsym_reloc */
-    struct Symbol *next;              /* list of globals in each section */
-    struct Symbol *nextfwd;           /* list of unresolved-size symbols */
-    char *name;                               /* for unresolved-size symbols */
-    long symnum;                      /* index into symbol table */
-};
-
-/*
- * Section IDs - used in Reloc.symbol when negative, and in
- * Symbol.type when positive.
- */
-#define SECT_ABS 2                    /* absolute value */
-#define SECT_TEXT 4                   /* text section */
-#define SECT_DATA 6                   /* data section */
-#define SECT_BSS 8                    /* bss section */
-#define SECT_MASK 0xE                 /* mask out any of the above */
-
-/*
- * More flags used in Symbol.type.
- */
-#define SYM_GLOBAL 1                  /* it's a global symbol */
-#define SYM_DATA 0x100                /* used for shared libs */
-#define SYM_FUNCTION 0x200            /* used for shared libs */
-#define SYM_WITH_SIZE 0x4000          /* not output; internal only */
-
-/*
- * Bit more explanation of symbol types: SECT_xxx denotes a local
- * symbol. SECT_xxx|SYM_GLOBAL denotes a global symbol, defined in
- * this module. Just SYM_GLOBAL, with zero value, denotes an
- * external symbol referenced in this module. And just SYM_GLOBAL,
- * but with a non-zero value, declares a C `common' variable, of
- * size `value'.
- */
-
-struct Section {
-    struct SAA *data;
-    unsigned long len, size, nrelocs;
-    long index;
-    struct Reloc *head, **tail;
-    struct Symbol *gsyms, *asym;
-};
-
-static struct Section stext, sdata, sbss;
-
-static struct SAA *syms;
-static unsigned long nsyms;
-
-static struct RAA *bsym;
-
-static struct SAA *strs;
-static unsigned long strslen;
-
-static struct Symbol *fwds;
-
-static FILE *aoutfp;
-static efunc error;
-static evalfunc evaluate;
-
-static int bsd;
-static int is_pic;
-
-static void aout_write(void);
-static void aout_write_relocs(struct Reloc *);
-static void aout_write_syms(void);
-static void aout_sect_write(struct Section *, unsigned char *, unsigned long);
-static void aout_pad_sections(void);
-static void aout_fixup_relocs(struct Section *);
-
-/*
- * Special section numbers which are used to define special
- * symbols, which can be used with WRT to provide PIC relocation
- * types.
- */
-static long aout_gotpc_sect, aout_gotoff_sect;
-static long aout_got_sect, aout_plt_sect;
-static long aout_sym_sect;
-
-static void aoutg_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
-{
-    aoutfp = fp;
-    error = errfunc;
-    evaluate = eval;
-    (void) ldef;                      /* placate optimisers */
-    stext.data = saa_init(1L); stext.head = NULL; stext.tail = &stext.head;
-    sdata.data = saa_init(1L); sdata.head = NULL; sdata.tail = &sdata.head;
-    stext.len = stext.size = sdata.len = sdata.size = sbss.len = 0;
-    stext.nrelocs = sdata.nrelocs = 0;
-    stext.gsyms = sdata.gsyms = sbss.gsyms = NULL;
-    stext.index = seg_alloc();
-    sdata.index = seg_alloc();
-    sbss.index = seg_alloc();
-    stext.asym = sdata.asym = sbss.asym = NULL;
-    syms = saa_init((long)sizeof(struct Symbol));
-    nsyms = 0;
-    bsym = raa_init();
-    strs = saa_init(1L);
-    strslen = 0;
-    fwds = NULL;
-}
-
-#ifdef OF_AOUT
-
-static void aout_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
-{
-    bsd = FALSE;
-    aoutg_init (fp, errfunc, ldef, eval);
-
-    aout_gotpc_sect = aout_gotoff_sect = aout_got_sect =
-       aout_plt_sect = aout_sym_sect = NO_SEG;
-}
-
-#endif
-
-#ifdef OF_AOUTB
-
-extern struct ofmt of_aoutb;
-
-static void aoutb_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
-{
-    bsd = TRUE;
-    aoutg_init (fp, errfunc, ldef, eval);
-
-    is_pic = 0x00;                    /* may become 0x40 */
-
-    aout_gotpc_sect = seg_alloc();
-    ldef("..gotpc", aout_gotpc_sect+1, 0L, NULL, FALSE,FALSE,&of_aoutb,error);
-    aout_gotoff_sect = seg_alloc();
-    ldef("..gotoff", aout_gotoff_sect+1, 0L,NULL,FALSE,FALSE,&of_aoutb,error);
-    aout_got_sect = seg_alloc();
-    ldef("..got", aout_got_sect+1, 0L, NULL, FALSE,FALSE,&of_aoutb,error);
-    aout_plt_sect = seg_alloc();
-    ldef("..plt", aout_plt_sect+1, 0L, NULL, FALSE,FALSE,&of_aoutb,error);
-    aout_sym_sect = seg_alloc();
-    ldef("..sym", aout_sym_sect+1, 0L, NULL, FALSE,FALSE,&of_aoutb,error);
-}
-
-#endif
-
-static void aout_cleanup(int debuginfo) 
-{
-    struct Reloc *r;
-
-    (void) debuginfo;
-
-    aout_pad_sections();
-    aout_fixup_relocs(&stext);
-    aout_fixup_relocs(&sdata);
-    aout_write();
-    fclose (aoutfp);
-    saa_free (stext.data);
-    while (stext.head) {
-       r = stext.head;
-       stext.head = stext.head->next;
-       nasm_free (r);
-    }
-    saa_free (sdata.data);
-    while (sdata.head) {
-       r = sdata.head;
-       sdata.head = sdata.head->next;
-       nasm_free (r);
-    }
-    saa_free (syms);
-    raa_free (bsym);
-    saa_free (strs);
-}
-
-static long aout_section_names (char *name, int pass, int *bits) 
-{
-    /*
-     * Default to 32 bits.
-     */
-    if (!name)
-       *bits = 32;
-
-    if (!name)
-       return stext.index;
-
-    if (!strcmp(name, ".text"))
-       return stext.index;
-    else if (!strcmp(name, ".data"))
-       return sdata.index;
-    else if (!strcmp(name, ".bss"))
-       return sbss.index;
-    else
-       return NO_SEG;
-}
-
-static void aout_deflabel (char *name, long segment, long offset,
-                          int is_global, char *special) 
-{
-    int pos = strslen+4;
-    struct Symbol *sym;
-    int special_used = FALSE;
-
-    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
-       /*
-        * This is a NASM special symbol. We never allow it into
-        * the a.out symbol table, even if it's a valid one. If it
-        * _isn't_ a valid one, we should barf immediately.
-        */
-       if (strcmp(name, "..gotpc") && strcmp(name, "..gotoff") &&
-           strcmp(name, "..got") && strcmp(name, "..plt") &&
-           strcmp(name, "..sym"))
-           error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
-       return;
-    }
-
-    if (is_global == 3) {
-       struct Symbol **s;
-       /*
-        * Fix up a forward-reference symbol size from the first
-        * pass.
-        */
-       for (s = &fwds; *s; s = &(*s)->nextfwd)
-           if (!strcmp((*s)->name, name)) {
-               struct tokenval tokval;
-               expr *e;
-               char *p = special;
-
-               while (*p && !isspace(*p)) p++;
-               while (*p && isspace(*p)) p++;
-               stdscan_reset();
-               stdscan_bufptr = p;
-               tokval.t_type = TOKEN_INVALID;
-               e = evaluate(stdscan, NULL, &tokval, NULL, 1, error, NULL);
-               if (e) {
-                   if (!is_simple(e))
-                       error (ERR_NONFATAL, "cannot use relocatable"
-                              " expression as symbol size");
-                   else
-                       (*s)->size = reloc_value(e);
-               }
-
-               /*
-                * Remove it from the list of unresolved sizes.
-                */
-               nasm_free ((*s)->name);
-               *s = (*s)->nextfwd;
-               return;
-           }
-       return;                        /* it wasn't an important one */
-    }
-
-    saa_wbytes (strs, name, (long)(1+strlen(name)));
-    strslen += 1+strlen(name);
-
-    sym = saa_wstruct (syms);
-
-    sym->strpos = pos;
-    sym->type = is_global ? SYM_GLOBAL : 0;
-    sym->segment = segment;
-    if (segment == NO_SEG)
-       sym->type |= SECT_ABS;
-    else if (segment == stext.index) {
-       sym->type |= SECT_TEXT;
-       if (is_global) {
-           sym->next = stext.gsyms;
-           stext.gsyms = sym;
-       } else if (!stext.asym)
-           stext.asym = sym;
-    } else if (segment == sdata.index) {
-       sym->type |= SECT_DATA;
-       if (is_global) {
-           sym->next = sdata.gsyms;
-           sdata.gsyms = sym;
-       } else if (!sdata.asym)
-           sdata.asym = sym;
-    } else if (segment == sbss.index) {
-       sym->type |= SECT_BSS;
-       if (is_global) {
-           sym->next = sbss.gsyms;
-           sbss.gsyms = sym;
-       } else if (!sbss.asym)
-           sbss.asym = sym;
-    } else
-       sym->type = SYM_GLOBAL;
-    if (is_global == 2)
-       sym->value = offset;
-    else
-       sym->value = (sym->type == SYM_GLOBAL ? 0 : offset);
-
-    if (is_global && sym->type != SYM_GLOBAL) {
-       /*
-        * Global symbol exported _from_ this module. We must check
-        * the special text for type information.
-        */
-
-       if (special) {
-           int n = strcspn(special, " ");
-
-           if (!nasm_strnicmp(special, "function", n))
-               sym->type |= SYM_FUNCTION;
-           else if (!nasm_strnicmp(special, "data", n) ||
-                    !nasm_strnicmp(special, "object", n))
-               sym->type |= SYM_DATA;
-           else
-               error(ERR_NONFATAL, "unrecognised symbol type `%.*s'",
-                     n, special);
-           if (special[n]) {
-               struct tokenval tokval;
-               expr *e;
-               int fwd = FALSE;
-               char *saveme=stdscan_bufptr;  /* bugfix? fbk 8/10/00 */
-
-               if (!bsd) {
-                   error(ERR_NONFATAL, "Linux a.out does not support"
-                         " symbol size information");
-               } else {
-                   while (special[n] && isspace(special[n]))
-                       n++;
-                   /*
-                    * We have a size expression; attempt to
-                    * evaluate it.
-                    */
-                   sym->type |= SYM_WITH_SIZE;
-                   stdscan_reset();
-                   stdscan_bufptr = special+n;
-                   tokval.t_type = TOKEN_INVALID;
-                   e = evaluate(stdscan, NULL, &tokval, &fwd, 0, error, NULL);
-                   if (fwd) {
-                       sym->nextfwd = fwds;
-                       fwds = sym;
-                       sym->name = nasm_strdup(name);
-                   } else if (e) {
-                       if (!is_simple(e))
-                           error (ERR_NONFATAL, "cannot use relocatable"
-                                  " expression as symbol size");
-                       else
-                           sym->size = reloc_value(e);
-                   }
-               }
-               stdscan_bufptr=saveme;     /* bugfix? fbk 8/10/00 */
-           }
-           special_used = TRUE;
-       }
-    }
-
-    /*
-     * define the references from external-symbol segment numbers
-     * to these symbol records.
-     */
-    if (segment != NO_SEG && segment != stext.index &&
-       segment != sdata.index && segment != sbss.index)
-       bsym = raa_write (bsym, segment, nsyms);
-    sym->symnum = nsyms;
-
-    nsyms++;
-    if (sym->type & SYM_WITH_SIZE)
-       nsyms++;                       /* and another for the size */
-
-    if (special && !special_used)
-       error(ERR_NONFATAL, "no special symbol features supported here");
-}
-
-static void aout_add_reloc (struct Section *sect, long segment,
-                           int reltype, int bytes) 
-{
-    struct Reloc *r;
-
-    r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
-    sect->tail = &r->next;
-    r->next = NULL;
-
-    r->address = sect->len;
-    r->symbol = (segment == NO_SEG ? -SECT_ABS :
-                segment == stext.index ? -SECT_TEXT :
-                segment == sdata.index ? -SECT_DATA :
-                segment == sbss.index ? -SECT_BSS :
-                raa_read(bsym, segment));
-    r->reltype = reltype;
-    if (r->symbol >= 0)
-       r->reltype |= RELTYPE_SYMFLAG;
-    r->bytes = bytes;
-
-    sect->nrelocs++;
-}
-
-/*
- * This routine deals with ..got and ..sym relocations: the more
- * complicated kinds. In shared-library writing, some relocations
- * with respect to global symbols must refer to the precise symbol
- * rather than referring to an offset from the base of the section
- * _containing_ the symbol. Such relocations call to this routine,
- * which searches the symbol list for the symbol in question.
- *
- * RELTYPE_GOT references require the _exact_ symbol address to be
- * used; RELTYPE_ABSOLUTE references can be at an offset from the
- * symbol. The boolean argument `exact' tells us this.
- *
- * Return value is the adjusted value of `addr', having become an
- * offset from the symbol rather than the section. Should always be
- * zero when returning from an exact call.
- *
- * Limitation: if you define two symbols at the same place,
- * confusion will occur.
- *
- * Inefficiency: we search, currently, using a linked list which
- * isn't even necessarily sorted.
- */
-static long aout_add_gsym_reloc (struct Section *sect,
-                                long segment, long offset,
-                                int type, int bytes, int exact) 
-{
-    struct Symbol *sym, *sm, *shead;
-    struct Reloc *r;
-
-    /*
-     * First look up the segment to find whether it's text, data,
-     * bss or an external symbol.
-     */
-    shead = NULL;
-    if (segment == stext.index)
-       shead = stext.gsyms;
-    else if (segment == sdata.index)
-       shead = sdata.gsyms;
-    else if (segment == sbss.index)
-       shead = sbss.gsyms;
-    if (!shead) {
-       if (exact && offset != 0)
-           error (ERR_NONFATAL, "unable to find a suitable global symbol"
-                  " for this reference");
-       else
-           aout_add_reloc (sect, segment, type, bytes);
-       return offset;
-    }
-
-    if (exact) {
-       /*
-        * Find a symbol pointing _exactly_ at this one.
-        */
-       for (sym = shead; sym; sym = sym->next)
-           if (sym->value == offset)
-               break;
-    } else {
-       /*
-        * Find the nearest symbol below this one.
-        */
-       sym = NULL;
-       for (sm = shead; sm; sm = sm->next)
-           if (sm->value <= offset && (!sym || sm->value > sym->value))
-               sym = sm;
-    }
-    if (!sym && exact) {
-       error (ERR_NONFATAL, "unable to find a suitable global symbol"
-              " for this reference");
-       return 0;
-    }
-
-    r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
-    sect->tail = &r->next;
-    r->next = NULL;
-
-    r->address = sect->len;
-    r->symbol = sym->symnum;
-    r->reltype = type | RELTYPE_SYMFLAG;
-    r->bytes = bytes;
-
-    sect->nrelocs++;
-
-    return offset - sym->value;
-}
-
-/*
- * This routine deals with ..gotoff relocations. These _must_ refer
- * to a symbol, due to a perversity of *BSD's PIC implementation,
- * and it must be a non-global one as well; so we store `asym', the
- * first nonglobal symbol defined in each section, and always work
- * from that. Relocation type is always RELTYPE_GOTOFF.
- *
- * Return value is the adjusted value of `addr', having become an
- * offset from the `asym' symbol rather than the section.
- */
-static long aout_add_gotoff_reloc (struct Section *sect, long segment,
-                                  long offset, int bytes) 
-{
-    struct Reloc *r;
-    struct Symbol *asym;
-
-    /*
-     * First look up the segment to find whether it's text, data,
-     * bss or an external symbol.
-     */
-    asym = NULL;
-    if (segment == stext.index)
-       asym = stext.asym;
-    else if (segment == sdata.index)
-       asym = sdata.asym;
-    else if (segment == sbss.index)
-       asym = sbss.asym;
-    if (!asym)
-       error (ERR_NONFATAL, "`..gotoff' relocations require a non-global"
-              " symbol in the section");
-
-    r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
-    sect->tail = &r->next;
-    r->next = NULL;
-
-    r->address = sect->len;
-    r->symbol = asym->symnum;
-    r->reltype = RELTYPE_GOTOFF;
-    r->bytes = bytes;
-
-    sect->nrelocs++;
-
-    return offset - asym->value;
-}
-
-static void aout_out (long segto, void *data, unsigned long type,
-                     long segment, long wrt) 
-{
-    struct Section *s;
-    long realbytes = type & OUT_SIZMASK;
-    long addr;
-    unsigned char mydata[4], *p;
-
-    type &= OUT_TYPMASK;
-
-    /*
-     * handle absolute-assembly (structure definitions)
-     */
-    if (segto == NO_SEG) {
-       if (type != OUT_RESERVE)
-           error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
-                  " space");
-       return;
-    }
-
-    if (segto == stext.index)
-       s = &stext;
-    else if (segto == sdata.index)
-       s = &sdata;
-    else if (segto == sbss.index)
-       s = NULL;
-    else {
-       error(ERR_WARNING, "attempt to assemble code in"
-             " segment %d: defaulting to `.text'", segto);
-       s = &stext;
-    }
-
-    if (!s && type != OUT_RESERVE) {
-       error(ERR_WARNING, "attempt to initialise memory in the"
-             " BSS section: ignored");
-       if (type == OUT_REL2ADR)
-           realbytes = 2;
-       else if (type == OUT_REL4ADR)
-           realbytes = 4;
-       sbss.len += realbytes;
-       return;
-    }
-
-    if (type == OUT_RESERVE) {
-       if (s) {
-           error(ERR_WARNING, "uninitialised space declared in"
-                 " %s section: zeroing",
-                 (segto == stext.index ? "code" : "data"));
-           aout_sect_write (s, NULL, realbytes);
-       } else
-           sbss.len += realbytes;
-    } else if (type == OUT_RAWDATA) {
-       if (segment != NO_SEG)
-           error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
-       aout_sect_write (s, data, realbytes);
-    } else if (type == OUT_ADDRESS) {
-       addr = *(long *)data;
-       if (segment != NO_SEG) {
-           if (segment % 2) {
-               error(ERR_NONFATAL, "a.out format does not support"
-                     " segment base references");
-           } else {
-               if (wrt == NO_SEG) {
-                   aout_add_reloc (s, segment, RELTYPE_ABSOLUTE, realbytes);
-               } else if (!bsd) {
-                   error (ERR_NONFATAL, "Linux a.out format does not support"
-                          " any use of WRT");
-                   wrt = NO_SEG;      /* we can at least _try_ to continue */
-               } else if (wrt == aout_gotpc_sect+1) {
-                   is_pic = 0x40;
-                   aout_add_reloc (s, segment, RELTYPE_GOTPC, realbytes);
-               } else if (wrt == aout_gotoff_sect+1) {
-                   is_pic = 0x40;
-                   addr = aout_add_gotoff_reloc (s, segment,
-                                                 addr, realbytes);
-               } else if (wrt == aout_got_sect+1) {
-                   is_pic = 0x40;
-                   addr = aout_add_gsym_reloc (s, segment, addr, RELTYPE_GOT,
-                                               realbytes, TRUE);
-               } else if (wrt == aout_sym_sect+1) {
-                   addr = aout_add_gsym_reloc (s, segment, addr,
-                                               RELTYPE_ABSOLUTE, realbytes,
-                                               FALSE);
-               } else if (wrt == aout_plt_sect+1) {
-                   is_pic = 0x40;
-                   error(ERR_NONFATAL, "a.out format cannot produce non-PC-"
-                         "relative PLT references");
-               } else {
-                   error (ERR_NONFATAL, "a.out format does not support this"
-                          " use of WRT");
-                   wrt = NO_SEG;      /* we can at least _try_ to continue */
-               }
-           }
-       }
-       p = mydata;
-       if (realbytes == 2)
-           WRITESHORT (p, addr);
-       else
-           WRITELONG (p, addr);
-       aout_sect_write (s, mydata, realbytes);
-    } else if (type == OUT_REL2ADR) {
-       if (segment == segto)
-           error(ERR_PANIC, "intra-segment OUT_REL2ADR");
-       if (segment != NO_SEG && segment % 2) {
-           error(ERR_NONFATAL, "a.out format does not support"
-                 " segment base references");
-       } else {
-           if (wrt == NO_SEG) {
-               aout_add_reloc (s, segment, RELTYPE_RELATIVE, 2);
-           } else if (!bsd) {
-               error (ERR_NONFATAL, "Linux a.out format does not support"
-                      " any use of WRT");
-               wrt = NO_SEG;      /* we can at least _try_ to continue */
-           } else if (wrt == aout_plt_sect+1) {
-               is_pic = 0x40;
-               aout_add_reloc (s, segment, RELTYPE_PLT, 2);
-           } else if (wrt == aout_gotpc_sect+1 ||
-                      wrt == aout_gotoff_sect+1 ||
-                      wrt == aout_got_sect+1) {
-               error(ERR_NONFATAL, "a.out format cannot produce PC-"
-                     "relative GOT references");
-           } else {
-               error (ERR_NONFATAL, "a.out format does not support this"
-                      " use of WRT");
-               wrt = NO_SEG;      /* we can at least _try_ to continue */
-           }
-       }
-       p = mydata;
-       WRITESHORT (p, *(long*)data-(realbytes + s->len));
-       aout_sect_write (s, mydata, 2L);
-    } else if (type == OUT_REL4ADR) {
-       if (segment == segto)
-           error(ERR_PANIC, "intra-segment OUT_REL4ADR");
-       if (segment != NO_SEG && segment % 2) {
-           error(ERR_NONFATAL, "a.out format does not support"
-                 " segment base references");
-       } else {
-           if (wrt == NO_SEG) {
-               aout_add_reloc (s, segment, RELTYPE_RELATIVE, 4);
-           } else if (!bsd) {
-               error (ERR_NONFATAL, "Linux a.out format does not support"
-                      " any use of WRT");
-               wrt = NO_SEG;      /* we can at least _try_ to continue */
-           } else if (wrt == aout_plt_sect+1) {
-               is_pic = 0x40;
-               aout_add_reloc (s, segment, RELTYPE_PLT, 4);
-           } else if (wrt == aout_gotpc_sect+1 ||
-                      wrt == aout_gotoff_sect+1 ||
-                      wrt == aout_got_sect+1) {
-               error(ERR_NONFATAL, "a.out format cannot produce PC-"
-                     "relative GOT references");
-           } else {
-               error (ERR_NONFATAL, "a.out format does not support this"
-                      " use of WRT");
-               wrt = NO_SEG;      /* we can at least _try_ to continue */
-           }
-       }
-       p = mydata;
-       WRITELONG (p, *(long*)data-(realbytes + s->len));
-       aout_sect_write (s, mydata, 4L);
-    }
-}
-
-static void aout_pad_sections(void) 
-{
-    static unsigned char pad[] = { 0x90, 0x90, 0x90, 0x90 };
-    /*
-     * Pad each of the text and data sections with NOPs until their
-     * length is a multiple of four. (NOP == 0x90.) Also increase
-     * the length of the BSS section similarly.
-     */
-    aout_sect_write (&stext, pad, (-(long)stext.len) & 3);
-    aout_sect_write (&sdata, pad, (-(long)sdata.len) & 3);
-    sbss.len = (sbss.len + 3) & ~3;
-}
-
-/*
- * a.out files have the curious property that all references to
- * things in the data or bss sections are done by addresses which
- * are actually relative to the start of the _text_ section, in the
- * _file_. (No relation to what happens after linking. No idea why
- * this should be so. It's very strange.) So we have to go through
- * the relocation table, _after_ the final size of each section is
- * known, and fix up the relocations pointed to.
- */
-static void aout_fixup_relocs(struct Section *sect) 
-{
-    struct Reloc *r;
-
-    saa_rewind (sect->data);
-    for (r = sect->head; r; r = r->next) {
-       unsigned char *p, *q, blk[4];
-       long l;
-
-       saa_fread (sect->data, r->address, blk, (long)r->bytes);
-       p = q = blk;
-       l = *p++;
-       if (r->bytes > 1) {
-           l += ((long)*p++) << 8;
-           if (r->bytes == 4) {
-               l += ((long)*p++) << 16;
-               l += ((long)*p++) << 24;
-           }
-       }
-       if (r->symbol == -SECT_DATA)
-           l += stext.len;
-       else if (r->symbol == -SECT_BSS)
-           l += stext.len + sdata.len;
-       if (r->bytes == 4)
-           WRITELONG(q, l);
-       else if (r->bytes == 2)
-           WRITESHORT(q, l);
-       else
-           *q++ = l & 0xFF;
-       saa_fwrite (sect->data, r->address, blk, (long)r->bytes);
-    }
-}
-
-static void aout_write(void) 
-{
-    /*
-     * Emit the a.out header.
-     */
-    /* OMAGIC, M_386 or MID_I386, no flags */
-    fwritelong (bsd ? 0x07018600 | is_pic : 0x640107L, aoutfp);
-    fwritelong (stext.len, aoutfp);
-    fwritelong (sdata.len, aoutfp);
-    fwritelong (sbss.len, aoutfp);
-    fwritelong (nsyms * 12, aoutfp);   /* length of symbol table */
-    fwritelong (0L, aoutfp);          /* object files have no entry point */
-    fwritelong (stext.nrelocs * 8, aoutfp);   /* size of text relocs */
-    fwritelong (sdata.nrelocs * 8, aoutfp);   /* size of data relocs */
-
-    /*
-     * Write out the code section and the data section.
-     */
-    saa_fpwrite (stext.data, aoutfp);
-    saa_fpwrite (sdata.data, aoutfp);
-
-    /*
-     * Write out the relocations.
-     */
-    aout_write_relocs (stext.head);
-    aout_write_relocs (sdata.head);
-
-    /*
-     * Write the symbol table.
-     */
-    aout_write_syms ();
-
-    /*
-     * And the string table.
-     */
-    fwritelong (strslen+4, aoutfp);    /* length includes length count */
-    saa_fpwrite (strs, aoutfp);
-}
-
-static void aout_write_relocs (struct Reloc *r) 
-{
-    while (r) {
-       unsigned long word2;
-
-       fwritelong (r->address, aoutfp);
-
-       if (r->symbol >= 0)
-           word2 = r->symbol;
-       else
-           word2 = -r->symbol;
-       word2 |= r->reltype << 24;
-       word2 |= (r->bytes == 1 ? 0 :
-                 r->bytes == 2 ? 0x2000000L : 0x4000000L);
-       fwritelong (word2, aoutfp);
-
-       r = r->next;
-    }
-}
-
-static void aout_write_syms (void) 
-{
-    unsigned long i;
-
-    saa_rewind (syms);
-    for (i = 0; i < nsyms; i++) {
-       struct Symbol *sym = saa_rstruct(syms);
-       fwritelong (sym->strpos, aoutfp);
-       fwritelong ((long)sym->type & ~SYM_WITH_SIZE, aoutfp);
-       /*
-        * Fix up the symbol value now we know the final section
-        * sizes.
-        */
-       if ((sym->type & SECT_MASK) == SECT_DATA)
-           sym->value += stext.len;
-       if ((sym->type & SECT_MASK) == SECT_BSS)
-           sym->value += stext.len + sdata.len;
-       fwritelong (sym->value, aoutfp);
-       /*
-        * Output a size record if necessary.
-        */
-       if (sym->type & SYM_WITH_SIZE) {
-           fwritelong(sym->strpos, aoutfp);
-           fwritelong(0x0DL, aoutfp);  /* special value: means size */
-           fwritelong(sym->size, aoutfp);
-           i++;                       /* use up another of `nsyms' */
-       }
-    }
-}
-
-static void aout_sect_write (struct Section *sect,
-                            unsigned char *data, unsigned long len) 
-{
-    saa_wbytes (sect->data, data, len);
-    sect->len += len;
-}
-
-static long aout_segbase (long segment) 
-{
-    return segment;
-}
-
-static int aout_directive (char *directive, char *value, int pass) 
-{
-    return 0;
-}
-
-static void aout_filename (char *inname, char *outname, efunc error) 
-{
-    standard_extension (inname, outname, ".o", error);
-}
-
-static char *aout_stdmac[] = {
-    "%define __SECT__ [section .text]",
-    "%macro __NASM_CDecl__ 1",
-    "%endmacro",
-    NULL
-};
-
-static int aout_set_info(enum geninfo type, char **val)
-{
-    return 0;
-}
-#endif /* OF_AOUT || OF_AOUTB */
-
-#ifdef OF_AOUT
-
-struct ofmt of_aout = {
-    "Linux a.out object files",
-    "aout",
-    NULL,
-    null_debug_arr,
-    &null_debug_form,
-    aout_stdmac,
-    aout_init,
-    aout_set_info,
-    aout_out,
-    aout_deflabel,
-    aout_section_names,
-    aout_segbase,
-    aout_directive,
-    aout_filename,
-    aout_cleanup
-};
-
-#endif
-
-#ifdef OF_AOUTB
-
-struct ofmt of_aoutb = {
-    "NetBSD/FreeBSD a.out object files",
-    "aoutb",
-    NULL,
-    null_debug_arr,
-    &null_debug_form,
-    aout_stdmac,
-    aoutb_init,
-    aout_set_info,
-    aout_out,
-    aout_deflabel,
-    aout_section_names,
-    aout_segbase,
-    aout_directive,
-    aout_filename,
-    aout_cleanup
-};
-
-#endif
diff --git a/outas86.c b/outas86.c
deleted file mode 100644 (file)
index 8c69567..0000000
--- a/outas86.c
+++ /dev/null
@@ -1,589 +0,0 @@
-/* outas86.c   output routines for the Netwide Assembler to produce
- *             Linux as86 (bin86-0.3) object files
- *
- * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
- * Julian Hall. All rights reserved. The software is
- * redistributable under the licence given in the file "Licence"
- * distributed in the NASM archive.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "nasm.h"
-#include "nasmlib.h"
-#include "outform.h"
-
-#ifdef OF_AS86
-
-struct Piece {
-    struct Piece *next;
-    int type;                         /* 0 = absolute, 1 = seg, 2 = sym */
-    long offset;                      /* relative offset */
-    int number;                               /* symbol/segment number (4=bss) */
-    long bytes;                               /* size of reloc or of absolute data */
-    int relative;                     /* TRUE or FALSE */
-};
-
-struct Symbol {
-    long strpos;                      /* string table position of name */
-    int flags;                        /* symbol flags */
-    int segment;                      /* 4=bss at this point */
-    long value;                               /* address, or COMMON variable size */
-};
-
-/*
- * Section IDs - used in Piece.number and Symbol.segment.
- */
-#define SECT_TEXT 0                   /* text section */
-#define SECT_DATA 3                   /* data section */
-#define SECT_BSS 4                    /* bss section */
-
-/*
- * Flags used in Symbol.flags.
- */
-#define SYM_ENTRY (1<<8)
-#define SYM_EXPORT (1<<7)
-#define SYM_IMPORT (1<<6)
-#define SYM_ABSOLUTE (1<<4)
-
-struct Section {
-    struct SAA *data;
-    unsigned long datalen, size, len;
-    long index;
-    struct Piece *head, *last, **tail;
-};
-
-static char as86_module[FILENAME_MAX];
-
-static struct Section stext, sdata;
-static unsigned long bsslen;
-static long bssindex;
-
-static struct SAA *syms;
-static unsigned long nsyms;
-
-static struct RAA *bsym;
-
-static struct SAA *strs;
-static unsigned long strslen;
-
-static int as86_reloc_size;
-
-static FILE *as86fp;
-static efunc error;
-
-static void as86_write(void);
-static void as86_write_section (struct Section *, int);
-static int as86_add_string (char *name);
-static void as86_sect_write(struct Section *, unsigned char *, unsigned long);
-
-static void as86_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
-{
-    as86fp = fp;
-    error = errfunc;
-    (void) ldef;                      /* placate optimisers */
-    stext.data = saa_init(1L); stext.datalen = 0L;
-    stext.head = stext.last = NULL;
-    stext.tail = &stext.head;
-    sdata.data = saa_init(1L); sdata.datalen = 0L;
-    sdata.head = sdata.last = NULL;
-    sdata.tail = &sdata.head;
-    bsslen =
-       stext.len = stext.datalen = stext.size =
-       sdata.len = sdata.datalen = sdata.size = 0;
-    stext.index = seg_alloc();
-    sdata.index = seg_alloc();
-    bssindex = seg_alloc();
-    syms = saa_init((long)sizeof(struct Symbol));
-    nsyms = 0;
-    bsym = raa_init();
-    strs = saa_init(1L);
-    strslen = 0;
-
-    as86_add_string (as86_module);
-}
-
-static void as86_cleanup(int debuginfo) 
-{
-    struct Piece *p;
-
-    (void) debuginfo;
-
-    as86_write();
-    fclose (as86fp);
-    saa_free (stext.data);
-    while (stext.head) {
-       p = stext.head;
-       stext.head = stext.head->next;
-       nasm_free (p);
-    }
-    saa_free (sdata.data);
-    while (sdata.head) {
-       p = sdata.head;
-       sdata.head = sdata.head->next;
-       nasm_free (p);
-    }
-    saa_free (syms);
-    raa_free (bsym);
-    saa_free (strs);
-}
-
-static long as86_section_names (char *name, int pass, int *bits) 
-{
-    /*
-     * Default is 16 bits.
-     */
-    if (!name)
-       *bits = 16;
-
-    if (!name)
-       return stext.index;
-
-    if (!strcmp(name, ".text"))
-       return stext.index;
-    else if (!strcmp(name, ".data"))
-       return sdata.index;
-    else if (!strcmp(name, ".bss"))
-       return bssindex;
-    else
-       return NO_SEG;
-}
-
-static int as86_add_string (char *name) 
-{
-    int pos = strslen;
-    int length = strlen(name);
-
-    saa_wbytes (strs, name, (long)(length+1));
-    strslen += 1+length;
-
-    return pos;
-}
-
-static void as86_deflabel (char *name, long segment, long offset,
-                          int is_global, char *special) 
-{
-    struct Symbol *sym;
-
-    if (special)
-       error (ERR_NONFATAL, "as86 format does not support any"
-              " special symbol types");
-
-    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
-       error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
-       return;
-    }
-
-    sym = saa_wstruct (syms);
-
-    sym->strpos = as86_add_string (name);
-    sym->flags = 0;
-    if (segment == NO_SEG)
-       sym->flags |= SYM_ABSOLUTE, sym->segment = 0;
-    else if (segment == stext.index)
-       sym->segment = SECT_TEXT;
-    else if (segment == sdata.index)
-       sym->segment = SECT_DATA;
-    else if (segment == bssindex)
-       sym->segment = SECT_BSS;
-    else {
-       sym->flags |= SYM_IMPORT;
-       sym->segment = 15;
-    }
-
-    if (is_global == 2)
-       sym->segment = 3;       /* already have IMPORT */
-
-    if (is_global && !(sym->flags & SYM_IMPORT))
-       sym->flags |= SYM_EXPORT;
-
-    sym->value = offset;
-
-    /*
-     * define the references from external-symbol segment numbers
-     * to these symbol records.
-     */
-    if (segment != NO_SEG && segment != stext.index &&
-       segment != sdata.index && segment != bssindex)
-       bsym = raa_write (bsym, segment, nsyms);
-
-    nsyms++;
-}
-
-static void as86_add_piece (struct Section *sect, int type, long offset,
-                           long segment, long bytes, int relative) 
-{
-    struct Piece *p;
-
-    sect->len += bytes;
-
-    if (type == 0 && sect->last && sect->last->type == 0) {
-       sect->last->bytes += bytes;
-       return;
-    }
-
-    p = sect->last = *sect->tail = nasm_malloc(sizeof(struct Piece));
-    sect->tail = &p->next;
-    p->next = NULL;
-
-    p->type = type;
-    p->offset = offset;
-    p->bytes = bytes;
-    p->relative = relative;
-
-    if (type == 1 && segment == stext.index)
-       p->number = SECT_TEXT;
-    else if (type == 1 && segment == sdata.index)
-       p->number = SECT_DATA;
-    else if (type == 1 && segment == bssindex)
-       p->number = SECT_BSS;
-    else if (type == 1)
-       p->number = raa_read (bsym, segment), p->type = 2;
-}
-
-static void as86_out (long segto, void *data, unsigned long type,
-                     long segment, long wrt) 
-{
-    struct Section *s;
-    long realbytes = type & OUT_SIZMASK;
-    long offset;
-    unsigned char mydata[4], *p;
-
-    if (wrt != NO_SEG) {
-       wrt = NO_SEG;                  /* continue to do _something_ */
-       error (ERR_NONFATAL, "WRT not supported by as86 output format");
-    }
-
-    type &= OUT_TYPMASK;
-
-    /*
-     * handle absolute-assembly (structure definitions)
-     */
-    if (segto == NO_SEG) {
-       if (type != OUT_RESERVE)
-           error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
-                  " space");
-       return;
-    }
-
-    if (segto == stext.index)
-       s = &stext;
-    else if (segto == sdata.index)
-       s = &sdata;
-    else if (segto == bssindex)
-       s = NULL;
-    else {
-       error(ERR_WARNING, "attempt to assemble code in"
-             " segment %d: defaulting to `.text'", segto);
-       s = &stext;
-    }
-
-    if (!s && type != OUT_RESERVE) {
-       error(ERR_WARNING, "attempt to initialise memory in the"
-             " BSS section: ignored");
-       if (type == OUT_REL2ADR)
-           realbytes = 2;
-       else if (type == OUT_REL4ADR)
-           realbytes = 4;
-       bsslen += realbytes;
-       return;
-    }
-
-    if (type == OUT_RESERVE) {
-       if (s) {
-           error(ERR_WARNING, "uninitialised space declared in"
-                 " %s section: zeroing",
-                 (segto == stext.index ? "code" : "data"));
-           as86_sect_write (s, NULL, realbytes);
-           as86_add_piece (s, 0, 0L, 0L, realbytes, 0);
-       } else
-           bsslen += realbytes;
-    } else if (type == OUT_RAWDATA) {
-       if (segment != NO_SEG)
-           error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
-       as86_sect_write (s, data, realbytes);
-       as86_add_piece (s, 0, 0L, 0L, realbytes, 0);
-    } else if (type == OUT_ADDRESS) {
-       if (segment != NO_SEG) {
-           if (segment % 2) {
-               error(ERR_NONFATAL, "as86 format does not support"
-                     " segment base references");
-           } else{
-               offset = * (long *) data;
-               as86_add_piece (s, 1, offset, segment, realbytes, 0);
-           }
-       } else {
-           p = mydata;
-           WRITELONG (p, * (long *) data);
-           as86_sect_write (s, data, realbytes);
-           as86_add_piece (s, 0, 0L, 0L, realbytes, 0);
-       }
-    } else if (type == OUT_REL2ADR) {
-       if (segment == segto)
-           error(ERR_PANIC, "intra-segment OUT_REL2ADR");
-       if (segment != NO_SEG) {
-           if (segment % 2) {
-               error(ERR_NONFATAL, "as86 format does not support"
-                     " segment base references");
-           } else {
-               offset = * (long *) data;
-               as86_add_piece (s, 1, offset-realbytes+2, segment, 2L, 1);
-           }
-       }
-    } else if (type == OUT_REL4ADR) {
-       if (segment == segto)
-           error(ERR_PANIC, "intra-segment OUT_REL4ADR");
-       if (segment != NO_SEG) {
-           if (segment % 2) {
-               error(ERR_NONFATAL, "as86 format does not support"
-                     " segment base references");
-           } else {
-               offset = * (long *) data;
-               as86_add_piece (s, 1, offset-realbytes+4, segment, 4L, 1);
-           }
-       }
-    }
-}
-
-static void as86_write(void) 
-{
-    unsigned long i;
-    long symlen, seglen, segsize;
-
-    /*
-     * First, go through the symbol records working out how big
-     * each will be. Also fix up BSS references at this time, and
-     * set the flags words up completely.
-     */
-    symlen = 0;
-    saa_rewind (syms);
-    for (i = 0; i < nsyms; i++) {
-       struct Symbol *sym = saa_rstruct (syms);
-       if (sym->segment == SECT_BSS)
-           sym->segment = SECT_DATA, sym->value += sdata.len;
-       sym->flags |= sym->segment;
-       if (sym->value == 0)
-           sym->flags |= 0 << 14, symlen += 4;
-       else if (sym->value >= 0 && sym->value <= 255)
-           sym->flags |= 1 << 14, symlen += 5;
-       else if (sym->value >= 0 && sym->value <= 65535L)
-           sym->flags |= 2 << 14, symlen += 6;
-       else
-           sym->flags |= 3 << 14, symlen += 8;
-    }
-
-    /*
-     * Now do the same for the segments, and get the segment size
-     * descriptor word at the same time.
-     */
-    seglen = segsize = 0;
-    if ((unsigned long) stext.len > 65535L)
-       segsize |= 0x03000000L, seglen += 4;
-    else
-       segsize |= 0x02000000L, seglen += 2;
-    if ((unsigned long) sdata.len > 65535L)
-       segsize |= 0xC0000000L, seglen += 4;
-    else
-       segsize |= 0x80000000L, seglen += 2;
-
-    /*
-     * Emit the as86 header.
-     */
-    fwritelong (0x000186A3L, as86fp);
-    fputc (0x2A, as86fp);
-    fwritelong (27+symlen+seglen+strslen, as86fp);   /* header length */
-    fwritelong (stext.len+sdata.len, as86fp);
-    fwriteshort (strslen, as86fp);
-    fwriteshort (0, as86fp);          /* class = revision = 0 */
-    fwritelong (0x55555555L, as86fp);   /* segment max sizes: always this */
-    fwritelong (segsize, as86fp);      /* segment size descriptors */
-    if (segsize & 0x01000000L)
-       fwritelong (stext.len, as86fp);
-    else
-       fwriteshort (stext.len, as86fp);
-    if (segsize & 0x40000000L)
-       fwritelong (sdata.len, as86fp);
-    else
-       fwriteshort (sdata.len, as86fp);
-    fwriteshort (nsyms, as86fp);
-
-    /*
-     * Write the symbol table.
-     */
-    saa_rewind (syms);
-    for (i = 0; i < nsyms; i++) {
-       struct Symbol *sym = saa_rstruct (syms);
-       fwriteshort (sym->strpos, as86fp);
-       fwriteshort (sym->flags, as86fp);
-       switch (sym->flags & (3<<14)) {
-         case 0<<14: break;
-         case 1<<14: fputc (sym->value, as86fp); break;
-         case 2<<14: fwriteshort (sym->value, as86fp); break;
-         case 3<<14: fwritelong (sym->value, as86fp); break;
-       }
-    }
-
-    /*
-     * Write out the string table.
-     */
-    saa_fpwrite (strs, as86fp);
-
-    /*
-     * Write the program text.
-     */
-    as86_reloc_size = -1;
-    as86_write_section (&stext, SECT_TEXT);
-    as86_write_section (&sdata, SECT_DATA);
-    fputc (0, as86fp);                /* termination */
-}
-
-static void as86_set_rsize (int size) 
-{
-    if (as86_reloc_size != size) {
-       switch (as86_reloc_size = size) {
-         case 1: fputc (0x01, as86fp); break;
-         case 2: fputc (0x02, as86fp); break;
-         case 4: fputc (0x03, as86fp); break;
-         default: error (ERR_PANIC, "bizarre relocation size %d", size);
-       }
-    }
-}
-
-static void as86_write_section (struct Section *sect, int index) 
-{
-    struct Piece *p;
-    unsigned long s;
-    long length;
-
-    fputc (0x20+index, as86fp);               /* select the right section */
-
-    saa_rewind (sect->data);
-
-    for (p = sect->head; p; p = p->next)
-       switch (p->type) {
-         case 0:
-           /*
-            * Absolute data. Emit it in chunks of at most 64
-            * bytes.
-            */
-           length = p->bytes;
-           do {
-               char buf[64];
-               long tmplen = (length > 64 ? 64 : length);
-               fputc (0x40 | (tmplen & 0x3F), as86fp);
-               saa_rnbytes (sect->data, buf, tmplen);
-               fwrite (buf, 1, tmplen, as86fp);
-               length -= tmplen;
-           } while (length > 0);
-           break;
-         case 1:
-           /*
-            * A segment-type relocation. First fix up the BSS.
-            */
-           if (p->number == SECT_BSS)
-               p->number = SECT_DATA, p->offset += sdata.len;
-           as86_set_rsize (p->bytes);
-           fputc (0x80 | (p->relative ? 0x20 : 0) | p->number, as86fp);
-           if (as86_reloc_size == 2)
-               fwriteshort (p->offset, as86fp);
-           else
-               fwritelong (p->offset, as86fp);
-           break;
-         case 2:
-           /*
-            * A symbol-type relocation.
-            */
-           as86_set_rsize (p->bytes);
-           s = p->offset;
-           if (s > 65535L)
-               s = 3;
-           else if (s > 255)
-               s = 2;
-           else if (s > 0)
-               s = 1;
-           else
-               s = 0;
-           fputc (0xC0 |
-                  (p->relative ? 0x20 : 0) |
-                  (p->number > 255 ? 0x04 : 0) | s, as86fp);
-           if (p->number > 255)
-               fwriteshort (p->number, as86fp);
-           else
-               fputc (p->number, as86fp);
-           switch ((int)s) {
-             case 0: break;
-             case 1: fputc (p->offset, as86fp); break;
-             case 2: fwriteshort (p->offset, as86fp); break;
-             case 3: fwritelong (p->offset, as86fp); break;
-           }
-           break;
-       }
-}
-
-static void as86_sect_write (struct Section *sect,
-                            unsigned char *data, unsigned long len) 
-{
-    saa_wbytes (sect->data, data, len);
-    sect->datalen += len;
-}
-
-static long as86_segbase (long segment) 
-{
-    return segment;
-}
-
-static int as86_directive (char *directive, char *value, int pass) 
-{
-    return 0;
-}
-
-static void as86_filename (char *inname, char *outname, efunc error) 
-{
-    char *p;
-
-    if ( (p = strrchr (inname, '.')) != NULL) {
-       strncpy (as86_module, inname, p-inname);
-       as86_module[p-inname] = '\0';
-    } else
-       strcpy (as86_module, inname);
-
-    standard_extension (inname, outname, ".o", error);
-}
-
-static char *as86_stdmac[] = {
-    "%define __SECT__ [section .text]",
-    "%macro __NASM_CDecl__ 1",
-    "%endmacro",
-    NULL
-};
-
-static int as86_set_info(enum geninfo type, char **val)
-{
-    return 0;
-}
-void as86_linenumber (char *name, long segment, long offset, int is_main,
-                    int lineno)
-{
-}
-struct ofmt of_as86 = {
-    "Linux as86 (bin86 version 0.3) object files",
-    "as86",
-    NULL,
-    null_debug_arr,
-    &null_debug_form,
-    as86_stdmac,
-    as86_init,
-    as86_set_info,
-    as86_out,
-    as86_deflabel, 
-    as86_section_names,
-    as86_segbase,
-    as86_directive,
-    as86_filename,
-    as86_cleanup
-};
-
-#endif /* OF_AS86 */
diff --git a/outbin.c b/outbin.c
deleted file mode 100644 (file)
index 95ac5da..0000000
--- a/outbin.c
+++ /dev/null
@@ -1,591 +0,0 @@
-/* outbin.c output routines for the Netwide Assembler to produce
- *    flat-form binary files
- *
- * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
- * Julian Hall. All rights reserved. The software is
- * redistributable under the licence given in the file "Licence"
- * distributed in the NASM archive.
- */
-
-/*
- * version with multiple sections support
- *
- * sections go in order defined by their org's if present
- * if no org present, sections go in sequence they appear.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "nasm.h"
-#include "nasmlib.h"
-#include "outform.h"
-
-#ifdef OF_BIN
-
-static FILE *fp;
-static efunc error;
-
-static struct Section {
-    struct Section *next;
-    struct SAA *contents;
-    long length;
-    long org;                  /* assigned org */
-    long pos;                  /* file position of section ?? */
-    long pad;                  /* padding bytes to next section in file */
-    long index;                /* the NASM section id */
-    long align;                /* section alignment, cannot be absolute addr */
-    char *name;
-} *sections, **sectail;
-
-static struct Reloc {
-    struct Reloc *next;
-    long posn;
-    long bytes;
-    long secref;
-    long secrel;
-    struct Section *target;
-} *relocs, **reloctail;
-
-static long current_section;
-
-static void add_reloc (struct Section *s, long bytes, long secref,
-             long secrel)
-{
-    struct Reloc *r;
-
-    r = *reloctail = nasm_malloc(sizeof(struct Reloc));
-    reloctail = &r->next;
-    r->next = NULL;
-    r->posn = s->length;
-    r->bytes = bytes;
-    r->secref = secref;
-    r->secrel = secrel;
-    r->target = s;
-}
-
-static struct Section *find_section_by_name(char *name)
-{
-   struct Section *s;
-
-   for (s = sections; s; s = s->next)
-      if (!strcmp(s->name,name))
-         break;
-
-   return s;
-}
-
-static struct Section *find_section_by_index(long index)
-{
-   struct Section *s;
-
-   for (s = sections; s; s = s->next)
-      if ( s->index == index )
-         break;
-
-   return s;
-}
-
-static struct Section *alloc_section(char *name)
-{
-   struct Section *s;
-
-   s = find_section_by_name(name);
-   if(s)
-      error(ERR_PANIC, "section %s re-defined", name);
-
-   s = nasm_malloc(sizeof(struct Section));
-   *sectail    = s;
-   sectail     = &s->next;
-   s->next     = NULL;
-
-   s->contents = saa_init(1L);
-   s->length   = 0;
-   s->pos      = 0;
-   s->org      = -1; /* default org is -1 because we want
-                      * to adjust sections one after another
-                      */
-   s->index    = seg_alloc();
-   s->align    = 4;
-   s->pad      = 0;
-   s->name     = nasm_strdup(name);
-
-   return s;
-}
-
-static void bin_init (FILE *afp, efunc errfunc, ldfunc ldef, evalfunc eval)
-{
-    fp = afp;
-    error = errfunc;
-
-    (void) eval;   /* Don't warn that this parameter is unused */
-    (void) ldef;            /* placate optimisers */
-
-    current_section = -1L;
-    relocs    = NULL;
-    reloctail = &relocs;
-    sections  = NULL;
-    sectail   = &sections;
-}
-
-static void bin_cleanup (int debuginfo)
-{
-   struct Section *outsections, **outstail;
-   struct Section *s, *o, *ls, *lo;
-   struct Reloc *r;
-   long least_org;
-
-   (void) debuginfo;
-
-   /* sort sections by their orgs
-    * sections without org follow their natural order
-    * after the org'd sections
-    */
-   outsections = NULL;
-   outstail = &outsections;
-
-   while( 1 )
-   {
-      least_org = 0x7fffffff;
-
-      ls = lo = NULL;
-      for( s = sections, o = NULL; s; o = s, s = s->next )
-         if( s->org != -1 && s->org < least_org )
-         {
-            least_org = s->org;
-            ls = s;
-            lo = o;
-         }
-
-      if(ls) /* relink to outsections */
-      {
-#ifdef DEBUG
-         fprintf(stdout, "bin_cleanup: relinking section %s org %ld\n", ls->name, ls->org);
-#endif
-         /* unlink from sections */
-         if(lo)
-            lo->next = ls->next;
-         else
-            if(ls == sections)
-               sections = ls->next;
-
-         /* link in to outsections */
-         if( ls->length > 0 )
-         {
-            *outstail   = ls;
-            outstail    = &ls->next;
-            ls->next    = NULL;
-         }
-      }
-      else
-         break;
-   }
-
-   /* link outsections at start of sections */
-   *outstail = sections;
-   sections = outsections;
-
-   /* calculate sections positions */
-   for(s = sections, o = NULL; s; s = s->next)
-   {
-      if(!strcmp(s->name,".bss")) continue; /* don't count .bss yet */
-
-      if(o)
-      {
-         /* if section doesn't have its
-          * own org, align from prev section
-          */
-         if( s->org == -1 )
-            s->org = o->org + o->length;
-
-         /* check orgs */
-         if( s->org - o->org < o->length )
-            error( ERR_PANIC, "sections %s and %s overlap!", o->name, s->name );
-
-         /* align previous section */
-         o->pad = ((o->pos + o->length + o->align-1) & ~(o->align-1)) - (o->pos + o->length);
-
-         if( s->org - o->org > o->length )
-         {
-#ifdef DEBUG
-            fprintf(stdout, "forced padding: %ld\n", s->org - o->org - o->length);
-#endif
-            o->pad = s->org - o->org - o->length;
-         }
-
-         s->pos += o->pos + o->length + o->pad;
-         s->org = s->pos + sections->org;
-      }
-
-#ifdef DEBUG
-      fprintf(stdout, "bin_cleanup: section %s at %ld(%lx) org %ld(%lx) prev <pos %ld(%lx)+size %ld(%lx)+pad %ld(%lx)> size %ld(%lx) align %ld(%lx)\n",
-              s->name, s->pos, s->pos, s->org, s->org, o?o->pos:0, o?o->pos:0,
-              o?o->length:0, o?o->length:0, o?o->pad:0, o?o->pad:0, s->length, s->length,
-              s->align, s->align);
-#endif
-
-      /* prepare for relocating by the way */
-      saa_rewind( s->contents );
-
-      o = s;
-   }
-
-   /* adjust .bss */
-   s = find_section_by_name(".bss");
-   if(s)
-   {
-      s->org = o->org + o->length + o->pad;
-
-#ifdef DEBUG
-      fprintf(stdout, "bin_cleanup: section %s at %ld org %ld prev (pos %ld+size %ld+pad %ld) size %ld align %ld\n",
-              s->name, s->pos, s->org, o?o->pos:0, o?o->length:0, o?o->pad:0, s->length, s->align);
-#endif
-   }
-
-   /* apply relocations */
-   for (r = relocs; r; r = r->next)
-   {
-      unsigned char *p, *q, mydata[4];
-      long l;
-
-      saa_fread (r->target->contents, r->posn, mydata, r->bytes);
-      p = q = mydata;
-      l = *p++;
-
-      if (r->bytes > 1) {
-         l += ((long)*p++) << 8;
-         if (r->bytes == 4) {
-            l += ((long)*p++) << 16;
-            l += ((long)*p++) << 24;
-         }
-      }
-
-      s = find_section_by_index(r->secref);
-      if(s)
-         l += s->org;
-
-      s = find_section_by_index(r->secrel);
-      if(s)
-         l -= s->org;
-
-      if (r->bytes == 4)
-          WRITELONG(q, l);
-      else if (r->bytes == 2)
-          WRITESHORT(q, l);
-      else
-          *q++ = l & 0xFF;
-      saa_fwrite (r->target->contents, r->posn, mydata, r->bytes);
-   }
-
-   /* write sections to file */
-   for(s = outsections; s; s = s->next)
-   {
-      if(s->length > 0 && strcmp(s->name,".bss"))
-      {
-#ifdef DEBUG
-         fprintf(stdout, "bin_cleanup: writing section %s\n", s->name);
-#endif
-         saa_fpwrite (s->contents, fp);
-         if( s->next )
-            while( s->pad-- > 0 )
-               fputc('\0', fp);
-               /* could pad with nops, since we don't
-                * know if this is code section or not
-                */
-      }
-   }
-
-   fclose (fp);
-
-   while (relocs) {
-      r = relocs->next;
-      nasm_free (relocs);
-      relocs = r;
-   }
-
-   while (outsections) {
-      s = outsections->next;
-      saa_free  (outsections->contents);
-      nasm_free (outsections->name);
-      nasm_free (outsections);
-      outsections = s;
-   }
-}
-
-static void bin_out (long segto, void *data, unsigned long type,
-           long segment, long wrt)
-{
-    unsigned char *p, mydata[4];
-    struct Section *s, *sec;
-    long realbytes;
-
-    if (wrt != NO_SEG) {
-   wrt = NO_SEG;            /* continue to do _something_ */
-   error (ERR_NONFATAL, "WRT not supported by binary output format");
-    }
-
-    /*
-     * handle absolute-assembly (structure definitions)
-     */
-    if (segto == NO_SEG) {
-   if ((type & OUT_TYPMASK) != OUT_RESERVE)
-       error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
-         " space");
-   return;
-    }
-
-    /*
-     * Find the segment we are targetting.
-     */
-    s = find_section_by_index(segto);
-    if (!s)
-   error (ERR_PANIC, "code directed to nonexistent segment?");
-
-    if (!strcmp(s->name, ".bss")) {         /* BSS */
-   if ((type & OUT_TYPMASK) != OUT_RESERVE)
-       error(ERR_WARNING, "attempt to initialise memory in the"
-        " BSS section: ignored");
-   s = NULL;
-    }
-
-   if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
-
-      if (segment != NO_SEG && !find_section_by_index(segment)) {
-          if (segment % 2)
-         error(ERR_NONFATAL, "binary output format does not support"
-               " segment base references");
-          else
-         error(ERR_NONFATAL, "binary output format does not support"
-               " external references");
-          segment = NO_SEG;
-      }
-
-      if (s) {
-         if (segment != NO_SEG)
-            add_reloc (s, type & OUT_SIZMASK, segment, -1L);
-         p = mydata;
-         if ((type & OUT_SIZMASK) == 4)
-            WRITELONG (p, *(long *)data);
-         else
-            WRITESHORT (p, *(long *)data);
-         saa_wbytes (s->contents, mydata, type & OUT_SIZMASK);
-         s->length += type & OUT_SIZMASK;
-      } else {
-         sec = find_section_by_name(".bss");
-         if(!sec)
-            error(ERR_PANIC, ".bss section is not present");
-         sec->length += type & OUT_SIZMASK;
-      }
-
-   } else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
-      type &= OUT_SIZMASK;
-      p = data;
-      if (s) {
-          saa_wbytes (s->contents, data, type);
-          s->length += type;
-      } else {
-         sec = find_section_by_name(".bss");
-         if(!sec)
-            error(ERR_PANIC, ".bss section is not present");
-         sec->length += type;
-      }
-
-   } else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
-      if (s) {
-          error(ERR_WARNING, "uninitialised space declared in"
-           " %s section: zeroing", s->name);
-      }
-      type &= OUT_SIZMASK;
-      if (s) {
-          saa_wbytes (s->contents, NULL, type);
-          s->length += type;
-      } else {
-         sec = find_section_by_name(".bss");
-         if(!sec)
-            error(ERR_PANIC, ".bss section is not present");
-         sec->length += type;
-      }
-   }
-   else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
-        (type & OUT_TYPMASK) == OUT_REL4ADR)
-   {
-      realbytes = ((type & OUT_TYPMASK) == OUT_REL4ADR ? 4 : 2);
-
-      if (segment != NO_SEG && !find_section_by_index(segment)) {
-          if (segment % 2)
-         error(ERR_NONFATAL, "binary output format does not support"
-               " segment base references");
-          else
-         error(ERR_NONFATAL, "binary output format does not support"
-               " external references");
-          segment = NO_SEG;
-      }
-
-      if (s) {
-         add_reloc (s, realbytes, segment, segto);
-         p = mydata;
-         if (realbytes == 4)
-            WRITELONG (p, *(long*)data - realbytes - s->length);
-         else
-            WRITESHORT (p, *(long*)data - realbytes - s->length);
-         saa_wbytes (s->contents, mydata, realbytes);
-         s->length += realbytes;
-      } else {
-         sec = find_section_by_name(".bss");
-         if(!sec)
-            error(ERR_PANIC, ".bss section is not present");
-         sec->length += realbytes;
-      }
-   }
-}
-
-static void bin_deflabel (char *name, long segment, long offset,
-           int is_global, char *special)
-{
-    (void) segment;   /* Don't warn that this parameter is unused */
-    (void) offset;    /* Don't warn that this parameter is unused */
-
-    if (special)
-   error (ERR_NONFATAL, "binary format does not support any"
-          " special symbol types");
-
-    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
-   error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
-   return;
-    }
-
-    if (is_global == 2) {
-   error (ERR_NONFATAL, "binary output format does not support common"
-          " variables");
-    }
-}
-
-static long bin_secname (char *name, int pass, int *bits)
-{
-    int sec_index;
-    long *sec_align;
-    char *p;
-    struct Section *sec;
-
-    (void) pass;   /* Don't warn that this parameter is unused */
-
-    /*
-     * Default is 16 bits .text segment
-     */
-   if (!name)
-   {
-      *bits = 16;
-      sec = find_section_by_name(".text");
-      if(!sec) sec = alloc_section(".text");
-      sec->org = 0; /* default .text org */
-      current_section = sec->index;
-      return sec->index;
-   }
-
-   p = name;
-   while (*p && !isspace(*p)) p++;
-   if (*p) *p++ = '\0';
-   if (!strcmp(name, ".text")) {
-      sec = find_section_by_name(".text");
-      if(!sec) sec = alloc_section(".text");
-      sec_index = sec->index;
-      sec_align = NULL;
-   } else {
-      sec = find_section_by_name(name);
-      if(!sec) sec = alloc_section(name);
-      sec_index = sec->index;
-      sec_align = &sec->align;
-   }
-
-    if (*p) {
-   if (!nasm_strnicmp(p,"align=",6)) {
-       if (sec_align == NULL)
-      error(ERR_NONFATAL, "cannot specify an alignment to"
-            " the .text section");
-       else if (p[6+strspn(p+6,"0123456789")])
-      error(ERR_NONFATAL, "argument to `align' is not numeric");
-       else {
-      unsigned int align = atoi(p+6);
-      if (!align || ((align-1) & align))
-          error(ERR_NONFATAL, "argument to `align' is not a"
-           " power of two");
-      else
-          *sec_align = align;
-       }
-    }
-   }
-
-   current_section = sec->index;
-   return sec_index;
-}
-
-static long bin_segbase (long segment)
-{
-    return segment;
-}
-
-static int bin_directive (char *directive, char *value, int pass)
-{
-   struct Section *s;
-   int rn_error;
-
-   (void) pass;   /* Don't warn that this parameter is unused */
-
-   if (!nasm_stricmp(directive, "org")) {
-      if(current_section == -1)
-         error(ERR_PANIC, "org of cosmic space specified");
-
-      s = find_section_by_index(current_section);
-      if(!s)
-         error(ERR_PANIC, "current_section points nowhere");
-
-      s->org = readnum (value, &rn_error);
-      if (rn_error)
-          error (ERR_NONFATAL, "argument to ORG should be numeric");
-      return 1;
-   }
-
-   return 0;
-}
-
-static void bin_filename (char *inname, char *outname, efunc error)
-{
-    standard_extension (inname, outname, "", error);
-}
-
-static char *bin_stdmac[] = {
-    "%define __SECT__ [section .text]",
-    "%imacro org 1+.nolist",
-    "[org %1]",
-    "%endmacro",
-    "%macro __NASM_CDecl__ 1",
-    "%endmacro",
-    NULL
-};
-
-static int bin_set_info(enum geninfo type, char **val)
-{
-    return 0;
-}
-
-struct ofmt of_bin = {
-    "flat-form binary files (e.g. DOS .COM, .SYS) multisection support test",
-    "bin",
-    NULL,
-    null_debug_arr,
-    &null_debug_form,
-    bin_stdmac,
-    bin_init,
-    bin_set_info,
-    bin_out,
-    bin_deflabel,
-    bin_secname,
-    bin_segbase,
-    bin_directive,
-    bin_filename,
-    bin_cleanup
-};
-
-#endif /* OF_BIN */
diff --git a/outcoff.c b/outcoff.c
deleted file mode 100644 (file)
index 973d9fe..0000000
--- a/outcoff.c
+++ /dev/null
@@ -1,779 +0,0 @@
-/* outcoff.c   output routines for the Netwide Assembler to produce
- *             COFF object files (for DJGPP and Win32)
- *
- * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
- * Julian Hall. All rights reserved. The software is
- * redistributable under the licence given in the file "Licence"
- * distributed in the NASM archive.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-
-#include "nasm.h"
-#include "nasmlib.h"
-#include "outform.h"
-
-#if defined(OF_COFF) || defined(OF_WIN32)
-
-/*
- * Notes on COFF:
- *
- * (0) When I say `standard COFF' below, I mean `COFF as output and
- * used by DJGPP'. I assume DJGPP gets it right.
- *
- * (1) Win32 appears to interpret the term `relative relocation'
- * differently from standard COFF. Standard COFF understands a
- * relative relocation to mean that during relocation you add the
- * address of the symbol you're referencing, and subtract the base
- * address of the section you're in. Win32 COFF, by contrast, seems
- * to add the address of the symbol and then subtract the address
- * of THE BYTE AFTER THE RELOCATED DWORD. Hence the two formats are
- * subtly incompatible.
- *
- * (2) Win32 doesn't bother putting any flags in the header flags
- * field (at offset 0x12 into the file).
- *
- * (3) Win32 uses some extra flags into the section header table:
- * it defines flags 0x80000000 (writable), 0x40000000 (readable)
- * and 0x20000000 (executable), and uses them in the expected
- * combinations. It also defines 0x00100000 through 0x00700000 for
- * section alignments of 1 through 64 bytes.
- *
- * (4) Both standard COFF and Win32 COFF seem to use the DWORD
- * field directly after the section name in the section header
- * table for something strange: they store what the address of the
- * section start point _would_ be, if you laid all the sections end
- * to end starting at zero. Dunno why. Microsoft's documentation
- * lists this field as "Virtual Size of Section", which doesn't
- * seem to fit at all. In fact, Win32 even includes non-linked
- * sections such as .drectve in this calculation.
- *
- * (5) Standard COFF does something very strange to common
- * variables: the relocation point for a common variable is as far
- * _before_ the variable as its size stretches out _after_ it. So
- * we must fix up common variable references. Win32 seems to be
- * sensible on this one.
- */
-
-/* Flag which version of COFF we are currently outputting. */
-static int win32;
-
-struct Reloc {
-    struct Reloc *next;
-    long address;                     /* relative to _start_ of section */
-    long symbol;                      /* symbol number */
-    enum {
-       SECT_SYMBOLS,
-       ABS_SYMBOL,
-       REAL_SYMBOLS
-    } symbase;                        /* relocation for symbol number :) */
-    int relative;                     /* TRUE or FALSE */
-};
-
-struct Symbol {
-    char name[9];
-    long strpos;                      /* string table position of name */
-    int section;                      /* section number where it's defined
-                                       * - in COFF codes, not NASM codes */
-    int is_global;                    /* is it a global symbol or not? */
-    long value;                               /* address, or COMMON variable size */
-};
-
-static FILE *coffp;
-static efunc error;
-static char coff_infile[FILENAME_MAX];
-
-struct Section {
-    struct SAA *data;
-    unsigned long len;
-    int nrelocs;
-    long index;
-    struct Reloc *head, **tail;
-    unsigned long flags;              /* section flags */
-    char name[9];
-    long pos, relpos;
-};
-
-#define TEXT_FLAGS (win32 ? 0x60500020L : 0x20L)
-#define DATA_FLAGS (win32 ? 0xC0300040L : 0x40L)
-#define BSS_FLAGS (win32 ? 0xC0300080L : 0x80L)
-#define INFO_FLAGS 0x00100A00L
-#define RDATA_FLAGS (win32 ? 0x40400040L : 0x40L)
-
-#define SECT_DELTA 32
-static struct Section **sects;
-static int nsects, sectlen;
-
-static struct SAA *syms;
-static unsigned long nsyms;
-
-static long def_seg;
-
-static int initsym;
-
-static struct RAA *bsym, *symval;
-
-static struct SAA *strs;
-static unsigned long strslen;
-
-static void coff_gen_init(FILE *, efunc);
-static void coff_sect_write (struct Section *, unsigned char *,
-                            unsigned long);
-static void coff_write (void);
-static void coff_section_header (char *, long, long, long, long, int, long);
-static void coff_write_relocs (struct Section *);
-static void coff_write_symbols (void);
-
-static void coff_win32_init(FILE *fp,  efunc errfunc,
-                           ldfunc ldef, evalfunc eval) 
-{
-    win32 = TRUE;
-    (void) ldef;                      /* placate optimisers */
-    coff_gen_init(fp, errfunc);
-}
-
-static void coff_std_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
-{
-    win32 = FALSE;
-    (void) ldef;                      /* placate optimisers */
-    coff_gen_init(fp, errfunc);
-}
-
-static void coff_gen_init(FILE *fp, efunc errfunc) 
-{
-
-    coffp = fp;
-    error = errfunc;
-    sects = NULL;
-    nsects = sectlen = 0;
-    syms = saa_init((long)sizeof(struct Symbol));
-    nsyms = 0;
-    bsym = raa_init();
-    symval = raa_init();
-    strs = saa_init(1L);
-    strslen = 0;
-    def_seg = seg_alloc();
-}
-
-static void coff_cleanup(int debuginfo) 
-{
-    struct Reloc *r;
-    int i;
-
-    (void) debuginfo;
-
-    coff_write();
-    fclose (coffp);
-    for (i=0; i<nsects; i++) {
-       if (sects[i]->data)
-           saa_free (sects[i]->data);
-       while (sects[i]->head) {
-           r = sects[i]->head;
-           sects[i]->head = sects[i]->head->next;
-           nasm_free (r);
-       }
-       nasm_free (sects[i]);
-    }
-    nasm_free (sects);
-    saa_free (syms);
-    raa_free (bsym);
-    raa_free (symval);
-    saa_free (strs);
-}
-
-static int coff_make_section (char *name, unsigned long flags) 
-{
-    struct Section *s;
-
-    s = nasm_malloc (sizeof(*s));
-
-    if (flags != BSS_FLAGS)
-       s->data = saa_init (1L);
-    else
-       s->data = NULL;
-    s->head = NULL;
-    s->tail = &s->head;
-    s->len = 0;
-    s->nrelocs = 0;
-    if (!strcmp(name, ".text"))
-       s->index = def_seg;
-    else
-       s->index = seg_alloc();
-    strncpy (s->name, name, 8);
-    s->name[8] = '\0';
-    s->flags = flags;
-
-    if (nsects >= sectlen)
-       sects = nasm_realloc (sects, (sectlen += SECT_DELTA)*sizeof(*sects));
-    sects[nsects++] = s;
-
-    return nsects-1;
-}
-
-static long coff_section_names (char *name, int pass, int *bits) 
-{
-    char *p;
-    unsigned long flags, align_and = ~0L, align_or = 0L;
-    int i;
-
-    /*
-     * Default is 32 bits.
-     */
-    if (!name)
-       *bits = 32;
-
-    if (!name)
-       return def_seg;
-
-    p = name;
-    while (*p && !isspace(*p)) p++;
-    if (*p) *p++ = '\0';
-    if (strlen(name) > 8) {
-       error (ERR_WARNING, "COFF section names limited to 8 characters:"
-              " truncating");
-       name[8] = '\0';
-    }
-    flags = 0;
-
-    while (*p && isspace(*p)) p++;
-    while (*p) {
-       char *q = p;
-       while (*p && !isspace(*p)) p++;
-       if (*p) *p++ = '\0';
-       while (*p && isspace(*p)) p++;
-
-       if (!nasm_stricmp(q, "code") || !nasm_stricmp(q, "text")) {
-           flags = TEXT_FLAGS;
-       } else if (!nasm_stricmp(q, "data")) {
-           flags = DATA_FLAGS;
-       } else if (!nasm_stricmp(q, "rdata")) {
-           if (win32)
-           flags = RDATA_FLAGS;
-           else {
-               flags = DATA_FLAGS;    /* gotta do something */
-               error (ERR_NONFATAL, "standard COFF does not support"
-                      " read-only data sections");
-           }
-       } else if (!nasm_stricmp(q, "bss")) {
-           flags = BSS_FLAGS;
-       } else if (!nasm_stricmp(q, "info")) {
-           if (win32)
-               flags = INFO_FLAGS;
-           else {
-               flags = DATA_FLAGS;    /* gotta do something */
-               error (ERR_NONFATAL, "standard COFF does not support"
-                      " informational sections");
-           }
-       } else if (!nasm_strnicmp(q,"align=",6)) {
-           if (!win32)
-               error (ERR_NONFATAL, "standard COFF does not support"
-                      " section alignment specification");
-           else {
-               if (q[6+strspn(q+6,"0123456789")])
-                   error(ERR_NONFATAL, "argument to `align' is not numeric");
-               else {
-                   unsigned int align = atoi(q+6);
-                   if (!align || ((align-1) & align))
-                       error(ERR_NONFATAL, "argument to `align' is not a"
-                             " power of two");
-                   else if (align > 64)
-                       error(ERR_NONFATAL, "Win32 cannot align sections"
-                             " to better than 64-byte boundaries");
-                   else {
-                       align_and = ~0x00F00000L;
-                       align_or = (align == 1 ? 0x00100000L :
-                                   align == 2 ? 0x00200000L :
-                                   align == 4 ? 0x00300000L :
-                                   align == 8 ? 0x00400000L :
-                                   align == 16 ? 0x00500000L :
-                                   align == 32 ? 0x00600000L : 0x00700000L);
-                   }
-               }
-           }
-       }
-    }
-
-    for (i=0; i<nsects; i++)
-       if (!strcmp(name, sects[i]->name))
-           break;
-    if (i == nsects) {
-       if (!flags) {
-           if (!strcmp(name, ".data"))
-               flags = DATA_FLAGS;
-           else if (!strcmp(name, ".rdata"))
-               flags = RDATA_FLAGS;
-           else if (!strcmp(name, ".bss"))
-               flags = BSS_FLAGS;
-           else
-               flags = TEXT_FLAGS;
-       }
-       i = coff_make_section (name, flags);
-       if (flags)
-           sects[i]->flags = flags;
-       sects[i]->flags &= align_and;
-       sects[i]->flags |= align_or;
-    } else if (pass == 1) {
-       if (flags)
-           error (ERR_WARNING, "section attributes ignored on"
-                  " redeclaration of section `%s'", name);
-    }
-
-    return sects[i]->index;
-}
-
-static void coff_deflabel (char *name, long segment, long offset,
-                          int is_global, char *special) 
-{
-    int pos = strslen+4;
-    struct Symbol *sym;
-
-    if (special)
-       error (ERR_NONFATAL, "binary format does not support any"
-              " special symbol types");
-
-    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
-       error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
-       return;
-    }
-
-    if (strlen(name) > 8) {
-       saa_wbytes (strs, name, (long)(1+strlen(name)));
-       strslen += 1+strlen(name);
-    } else
-       pos = -1;
-
-    sym = saa_wstruct (syms);
-
-    sym->strpos = pos;
-    if (pos == -1)
-       strcpy (sym->name, name);
-    sym->is_global = !!is_global;
-    if (segment == NO_SEG)
-       sym->section = -1;      /* absolute symbol */
-    else {
-       int i;
-       sym->section = 0;
-       for (i=0; i<nsects; i++)
-           if (segment == sects[i]->index) {
-               sym->section = i+1;
-               break;
-           }
-       if (!sym->section)
-           sym->is_global = TRUE;
-    }
-    if (is_global == 2)
-       sym->value = offset;
-    else
-       sym->value = (sym->section == 0 ? 0 : offset);
-
-    /*
-     * define the references from external-symbol segment numbers
-     * to these symbol records.
-     */
-    if (sym->section == 0)
-       bsym = raa_write (bsym, segment, nsyms);
-
-    if (segment != NO_SEG)
-       symval = raa_write (symval, segment, sym->section ? 0 : sym->value);
-
-    nsyms++;
-}
-
-static long coff_add_reloc (struct Section *sect, long segment,
-                           int relative) 
-{
-    struct Reloc *r;
-
-    r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
-    sect->tail = &r->next;
-    r->next = NULL;
-
-    r->address = sect->len;
-    if (segment == NO_SEG)
-       r->symbol = 0, r->symbase = ABS_SYMBOL;
-    else {
-       int i;
-       r->symbase = REAL_SYMBOLS;
-       for (i=0; i<nsects; i++)
-           if (segment == sects[i]->index) {
-               r->symbol = i*2;
-               r->symbase = SECT_SYMBOLS;
-               break;
-           }
-       if (r->symbase == REAL_SYMBOLS)
-           r->symbol = raa_read (bsym, segment);
-    }
-    r->relative = relative;
-
-    sect->nrelocs++;
-
-    /*
-     * Return the fixup for standard COFF common variables.
-     */
-    if (r->symbase == REAL_SYMBOLS && !win32)
-       return raa_read (symval, segment);
-    else
-       return 0;
-}
-
-static void coff_out (long segto, void *data, unsigned long type,
-                     long segment, long wrt) 
-{
-    struct Section *s;
-    long realbytes = type & OUT_SIZMASK;
-    unsigned char mydata[4], *p;
-    int i;
-
-    if (wrt != NO_SEG) {
-       wrt = NO_SEG;                  /* continue to do _something_ */
-       error (ERR_NONFATAL, "WRT not supported by COFF output formats");
-    }
-
-    type &= OUT_TYPMASK;
-
-    /*
-     * handle absolute-assembly (structure definitions)
-     */
-    if (segto == NO_SEG) {
-       if (type != OUT_RESERVE)
-           error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
-                  " space");
-       return;
-    }
-
-    s = NULL;
-    for (i=0; i<nsects; i++)
-       if (segto == sects[i]->index) {
-           s = sects[i];
-           break;
-       }
-    if (!s) {
-       int tempint;                   /* ignored */
-       if (segto != coff_section_names (".text", 2, &tempint))
-           error (ERR_PANIC, "strange segment conditions in COFF driver");
-       else
-           s = sects[nsects-1];
-    }
-
-    if (!s->data && type != OUT_RESERVE) {
-       error(ERR_WARNING, "attempt to initialise memory in"
-             " BSS section `%s': ignored", s->name);
-       if (type == OUT_REL2ADR)
-           realbytes = 2;
-       else if (type == OUT_REL4ADR)
-           realbytes = 4;
-       s->len += realbytes;
-       return;
-    }
-
-    if (type == OUT_RESERVE) {
-       if (s->data) {
-           error(ERR_WARNING, "uninitialised space declared in"
-                 " non-BSS section `%s': zeroing", s->name);
-           coff_sect_write (s, NULL, realbytes);
-       } else
-           s->len += realbytes;
-    } else if (type == OUT_RAWDATA) {
-       if (segment != NO_SEG)
-           error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
-       coff_sect_write (s, data, realbytes);
-    } else if (type == OUT_ADDRESS) {
-       if (realbytes != 4 && (segment != NO_SEG || wrt != NO_SEG))
-           error(ERR_NONFATAL, "COFF format does not support non-32-bit"
-                 " relocations");
-       else {
-           long fix = 0;
-           if (segment != NO_SEG || wrt != NO_SEG) {
-               if (wrt != NO_SEG) {
-                   error(ERR_NONFATAL, "COFF format does not support"
-                         " WRT types");
-               } else if (segment % 2) {
-                   error(ERR_NONFATAL, "COFF format does not support"
-                         " segment base references");
-               } else
-                   fix = coff_add_reloc (s, segment, FALSE);
-           }
-           p = mydata;
-           WRITELONG (p, *(long *)data + fix);
-           coff_sect_write (s, mydata, realbytes);
-       }
-    } else if (type == OUT_REL2ADR) {
-       error(ERR_NONFATAL, "COFF format does not support 16-bit"
-             " relocations");
-    } else if (type == OUT_REL4ADR) {
-       if (segment == segto)
-           error(ERR_PANIC, "intra-segment OUT_REL4ADR");
-       else if (segment == NO_SEG && win32)
-           error(ERR_NONFATAL, "Win32 COFF does not correctly support"
-                 " relative references to absolute addresses");
-       else {
-           long fix = 0;
-           if (segment != NO_SEG && segment % 2) {
-               error(ERR_NONFATAL, "COFF format does not support"
-                     " segment base references");
-           } else
-               fix = coff_add_reloc (s, segment, TRUE);
-           p = mydata;
-           if (win32) {
-               WRITELONG (p, *(long*)data + 4 - realbytes + fix);
-           } else {
-               WRITELONG (p, *(long*)data-(realbytes + s->len) + fix);
-           }
-           coff_sect_write (s, mydata, 4L);
-       }
-    }
-}
-
-static void coff_sect_write (struct Section *sect,
-                            unsigned char *data, unsigned long len) 
-{
-    saa_wbytes (sect->data, data, len);
-    sect->len += len;
-}
-
-static int coff_directives (char *directive, char *value, int pass) 
-{
-    return 0;
-}
-
-static void coff_write (void) 
-{
-    long pos, sympos, vsize;
-    int i;
-
-    /*
-     * Work out how big the file will get. Calculate the start of
-     * the `real' symbols at the same time.
-     */
-    pos = 0x14 + 0x28 * nsects;
-    initsym = 3;                      /* two for the file, one absolute */
-    for (i=0; i<nsects; i++) {
-       if (sects[i]->data) {
-           sects[i]->pos = pos;
-           pos += sects[i]->len;
-           sects[i]->relpos = pos;
-           pos += 10 * sects[i]->nrelocs;
-       } else
-           sects[i]->pos = sects[i]->relpos = 0L;
-       initsym += 2;                  /* two for each section */
-    }
-    sympos = pos;
-
-    /*
-     * Output the COFF header.
-     */
-    fwriteshort (0x14C, coffp);               /* MACHINE_i386 */
-    fwriteshort (nsects, coffp);       /* number of sections */
-    fwritelong (time(NULL), coffp);    /* time stamp */
-    fwritelong (sympos, coffp);
-    fwritelong (nsyms + initsym, coffp);
-    fwriteshort (0, coffp);           /* no optional header */
-    /* Flags: 32-bit, no line numbers. Win32 doesn't even bother with them. */
-    fwriteshort (win32 ? 0 : 0x104, coffp);
-
-    /*
-     * Output the section headers.
-     */
-    vsize = 0L;
-    for (i=0; i<nsects; i++) {
-       coff_section_header (sects[i]->name, vsize, sects[i]->len,
-                            sects[i]->pos, sects[i]->relpos,
-                            sects[i]->nrelocs, sects[i]->flags);
-       vsize += sects[i]->len;
-    }
-
-    /*
-     * Output the sections and their relocations.
-     */
-    for (i=0; i<nsects; i++)
-       if (sects[i]->data) {
-           saa_fpwrite (sects[i]->data, coffp);
-           coff_write_relocs (sects[i]);
-       }
-
-    /*
-     * Output the symbol and string tables.
-     */
-    coff_write_symbols();
-    fwritelong (strslen+4, coffp);     /* length includes length count */
-    saa_fpwrite (strs, coffp);
-}
-
-static void coff_section_header (char *name, long vsize,
-                                long datalen, long datapos,
-                                long relpos, int nrelocs, long flags) 
-{
-    char padname[8];
-
-    memset (padname, 0, 8);
-    strncpy (padname, name, 8);
-    fwrite (padname, 8, 1, coffp);
-    fwritelong (vsize, coffp);
-    fwritelong (0L, coffp);           /* RVA/offset - we ignore */
-    fwritelong (datalen, coffp);
-    fwritelong (datapos, coffp);
-    fwritelong (relpos, coffp);
-    fwritelong (0L, coffp);           /* no line numbers - we don't do 'em */
-    fwriteshort (nrelocs, coffp);
-    fwriteshort (0, coffp);           /* again, no line numbers */
-    fwritelong (flags, coffp);
-}
-
-static void coff_write_relocs (struct Section *s) 
-{
-    struct Reloc *r;
-
-    for (r = s->head; r; r = r->next) {
-       fwritelong (r->address, coffp);
-       fwritelong (r->symbol + (r->symbase == REAL_SYMBOLS ? initsym :
-                                r->symbase == ABS_SYMBOL ? initsym-1 :
-                                r->symbase == SECT_SYMBOLS ? 2 : 0), coffp);
-       /*
-        * Strange: Microsoft's COFF documentation says 0x03 for an
-        * absolute relocation, but both Visual C++ and DJGPP agree
-        * that in fact it's 0x06. I'll use 0x06 until someone
-        * argues.
-        */
-       fwriteshort (r->relative ? 0x14 : 0x06, coffp);
-    }
-}
-
-static void coff_symbol (char *name, long strpos, long value,
-                        int section, int type, int aux) 
-{
-    char padname[8];
-
-    if (name) {
-       memset (padname, 0, 8);
-       strncpy (padname, name, 8);
-       fwrite (padname, 8, 1, coffp);
-    } else {
-       fwritelong (0L, coffp);
-       fwritelong (strpos, coffp);
-    }
-    fwritelong (value, coffp);
-    fwriteshort (section, coffp);
-    fwriteshort (0, coffp);
-    fputc (type, coffp);
-    fputc (aux, coffp);
-}
-
-static void coff_write_symbols (void)
-{
-    char filename[18];
-    unsigned long i;
-
-    /*
-     * The `.file' record, and the file name auxiliary record.
-     */
-    coff_symbol (".file", 0L, 0L, -2, 0x67, 1);
-    memset (filename, 0, 18);
-    strncpy (filename, coff_infile, 18);
-    fwrite (filename, 18, 1, coffp);
-
-    /*
-     * The section records, with their auxiliaries.
-     */
-    memset (filename, 0, 18);         /* useful zeroed buffer */
-
-    for (i = 0; i < nsects; i++) {
-       coff_symbol (sects[i]->name, 0L, 0L, i+1, 3, 1);
-       fwritelong (sects[i]->len, coffp);
-       fwriteshort (sects[i]->nrelocs, coffp);
-       fwrite (filename, 12, 1, coffp);
-    }
-
-    /*
-     * The absolute symbol, for relative-to-absolute relocations.
-     */
-    coff_symbol (".absolut", 0L, 0L, -1, 3, 0);
-
-    /*
-     * The real symbols.
-     */
-    saa_rewind (syms);
-    for (i = 0; i < nsyms; i++) {
-       struct Symbol *sym = saa_rstruct (syms);
-       coff_symbol (sym->strpos == -1 ? sym->name : NULL,
-                    sym->strpos, sym->value, sym->section,
-                    sym->is_global ? 2 : 3, 0);
-    }
-}
-
-static long coff_segbase (long segment) 
-{
-    return segment;
-}
-
-static void coff_std_filename (char *inname, char *outname, efunc error) 
-{
-    strcpy(coff_infile, inname);
-    standard_extension (inname, outname, ".o", error);
-}
-
-static void coff_win32_filename (char *inname, char *outname, efunc error) 
-{
-    strcpy(coff_infile, inname);
-    standard_extension (inname, outname, ".obj", error);
-}
-
-static char *coff_stdmac[] = {
-    "%define __SECT__ [section .text]",
-    "%macro __NASM_CDecl__ 1",
-    "%endmacro",
-    NULL
-};
-
-static int coff_set_info(enum geninfo type, char **val)
-{
-    return 0;
-}
-#endif /* defined(OF_COFF) || defined(OF_WIN32) */
-
-#ifdef OF_COFF
-
-struct ofmt of_coff = {
-    "COFF (i386) object files (e.g. DJGPP for DOS)",
-    "coff",
-    NULL,
-    null_debug_arr,
-    &null_debug_form,
-    coff_stdmac,
-    coff_std_init,
-    coff_set_info,
-    coff_out,
-    coff_deflabel,
-    coff_section_names,
-    coff_segbase,
-    coff_directives,
-    coff_std_filename,
-    coff_cleanup
-};
-
-#endif
-
-#ifdef OF_WIN32
-
-struct ofmt of_win32 = {
-    "Microsoft Win32 (i386) object files",
-    "win32",
-    NULL,
-    null_debug_arr,
-    &null_debug_form,
-    coff_stdmac,
-    coff_win32_init,
-    coff_set_info,
-    coff_out,
-    coff_deflabel,
-    coff_section_names,
-    coff_segbase,
-    coff_directives,
-    coff_win32_filename,
-    coff_cleanup
-};
-
-#endif
diff --git a/outdbg.c b/outdbg.c
deleted file mode 100644 (file)
index 723e372..0000000
--- a/outdbg.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/* outdbg.c    output routines for the Netwide Assembler to produce
- *             a debugging trace
- *
- * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
- * Julian Hall. All rights reserved. The software is
- * redistributable under the licence given in the file "Licence"
- * distributed in the NASM archive.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "nasm.h"
-#include "nasmlib.h"
-#include "outform.h"
-
-#ifdef OF_DBG
-
-struct Section {
-    struct Section *next;
-    long number;
-    char *name;
-} *dbgsect;
-
-FILE *dbgf;
-efunc dbgef;
-
-struct ofmt of_dbg;
-static void dbg_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
-{
-    (void) eval;
-
-    dbgf = fp;
-    dbgef = errfunc;
-    dbgsect = NULL;
-    (void) ldef;
-    fprintf(fp,"NASM Output format debug dump\n");
-    of_dbg.current_dfmt->init(&of_dbg,0,fp,errfunc);
-    
-}
-
-static void dbg_cleanup(int debuginfo)
-{
-    (void) debuginfo;
-    of_dbg.current_dfmt->cleanup();
-    while (dbgsect) {
-       struct Section *tmp = dbgsect;
-       dbgsect = dbgsect->next;
-       nasm_free (tmp->name);
-       nasm_free (tmp);
-    }
-    fclose(dbgf);
-}
-
-static long dbg_section_names (char *name, int pass, int *bits)
-{
-    int seg;
-
-    /*
-     * We must have an initial default: let's make it 16.
-     */
-    if (!name)
-       *bits = 16;
-
-    if (!name)
-       fprintf(dbgf, "section_name on init: returning %d\n",
-               seg = seg_alloc());
-    else {
-       int n = strcspn(name, " \t");
-       char *sname = nasm_strndup(name, n);
-       struct Section *s;
-
-       seg = NO_SEG;
-       for (s = dbgsect; s; s = s->next)
-           if (!strcmp(s->name, sname))
-               seg = s->number;
-       
-       if (seg == NO_SEG) {
-           s = nasm_malloc(sizeof(*s));
-           s->name = sname;
-           s->number = seg = seg_alloc();
-           s->next = dbgsect;
-           dbgsect = s;
-           fprintf(dbgf, "section_name %s (pass %d): returning %d\n",
-                   name, pass, seg);
-       }
-    }
-    return seg;
-}
-
-static void dbg_deflabel (char *name, long segment, long offset,
-                         int is_global, char *special) 
-{
-    fprintf(dbgf,"deflabel %s := %08lx:%08lx %s (%d)%s%s\n",
-           name, segment, offset,
-           is_global == 2 ? "common" : is_global ? "global" : "local",
-           is_global,
-           special ? ": " : "", special);
-}
-
-static void dbg_out (long segto, void *data, unsigned long type,
-                    long segment, long wrt) 
-{
-    long realbytes = type & OUT_SIZMASK;
-    long ldata;
-    int id;
-
-    type &= OUT_TYPMASK;
-
-    fprintf(dbgf,"out to %lx, len = %ld: ",segto,realbytes);
-
-    switch(type) {
-      case OUT_RESERVE:
-       fprintf(dbgf,"reserved.\n"); break;
-      case OUT_RAWDATA:
-       fprintf(dbgf,"raw data = ");
-       while (realbytes--) {
-           id = *(unsigned char *)data;
-           data = (char *)data + 1;
-           fprintf(dbgf,"%02x ",id);
-       }
-       fprintf(dbgf,"\n"); break;
-      case OUT_ADDRESS:
-       ldata = 0; /* placate gcc */
-       if (realbytes == 1)
-           ldata = *((char *)data);
-       else if (realbytes == 2)
-           ldata = *((short *)data);
-       else if (realbytes == 4)
-           ldata = *((long *)data);
-       fprintf(dbgf,"addr %08lx (seg %08lx, wrt %08lx)\n",ldata,
-               segment,wrt);break;
-      case OUT_REL2ADR:
-       fprintf(dbgf,"rel2adr %04x (seg %08lx)\n",(int)*(short *)data,segment);
-       break;
-      case OUT_REL4ADR:
-       fprintf(dbgf,"rel4adr %08lx (seg %08lx)\n",*(long *)data,segment);
-       break;
-      default:
-       fprintf(dbgf,"unknown\n");
-       break;
-    }
-}
-
-static long dbg_segbase(long segment) 
-{
-    return segment;
-}
-
-static int dbg_directive (char *directive, char *value, int pass) 
-{
-    fprintf(dbgf, "directive [%s] value [%s] (pass %d)\n",
-           directive, value, pass);
-    return 1;
-}
-
-static void dbg_filename (char *inname, char *outname, efunc error) 
-{
-    standard_extension (inname, outname, ".dbg", error);
-}
-
-static int dbg_set_info(enum geninfo type, char **val)
-{
-    (void) type;
-    (void) val;
-    return 0;
-}
-char *types[] = { 
-       "unknown", "label", "byte","word","dword","float","qword","tbyte" 
-};
-void dbgdbg_init(struct ofmt * of, void * id, FILE * fp, efunc error)
-{
-    (void) of;
-    (void) id;
-    (void) fp;
-    (void) error;
-    fprintf(fp,"   With debug info\n");
-}
-static void dbgdbg_cleanup(void)
-{
-}
-
-static void dbgdbg_linnum (const char *lnfname, long lineno, long segto)
-{
-    fprintf(dbgf,"dbglinenum %s(%ld) := %08lx\n",
-       lnfname,lineno,segto);
-}
-static void dbgdbg_deflabel (char *name, long segment,
-                         long offset, int is_global, char *special) 
-{
-    fprintf(dbgf,"dbglabel %s := %08lx:%08lx %s (%d)%s%s\n",
-           name,
-            segment, offset,
-           is_global == 2 ? "common" : is_global ? "global" : "local",
-           is_global,
-           special ? ": " : "", special);
-}
-static void dbgdbg_define(const char *type, const char *params)
-{
-    fprintf(dbgf,"dbgdirective [%s] value [%s]\n",type, params);
-}
-static void dbgdbg_output (int output_type, void *param)
-{
-    (void) output_type;
-    (void) param;
-}
-static void dbgdbg_typevalue(long type)
-{
-       fprintf(dbgf,"new type: %s(%lX)\n",
-           types[TYM_TYPE(type) >> 3], TYM_ELEMENTS(type) );
-}
-static struct dfmt debug_debug_form = {
-    "Trace of all info passed to debug stage",
-    "debug",
-    dbgdbg_init,
-    dbgdbg_linnum,
-    dbgdbg_deflabel,
-    dbgdbg_define,
-    dbgdbg_typevalue,
-    dbgdbg_output,
-    dbgdbg_cleanup,
-};
-
-static struct dfmt *debug_debug_arr[3] = {
-       &debug_debug_form,
-       &null_debug_form,
-       NULL
-};
-struct ofmt of_dbg = {
-    "Trace of all info passed to output stage",
-    "dbg",
-    NULL,
-    debug_debug_arr,
-    &null_debug_form,
-    NULL,
-    dbg_init,
-    dbg_set_info,
-    dbg_out,
-    dbg_deflabel,
-    dbg_section_names,
-    dbg_segbase,
-    dbg_directive,
-    dbg_filename,
-    dbg_cleanup
-};
-
-#endif /* OF_DBG */
diff --git a/outelf.c b/outelf.c
deleted file mode 100644 (file)
index 38f4a56..0000000
--- a/outelf.c
+++ /dev/null
@@ -1,1101 +0,0 @@
-/* outelf.c    output routines for the Netwide Assembler to produce
- *             ELF32 (i386 of course) object file format
- *
- * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
- * Julian Hall. All rights reserved. The software is
- * redistributable under the licence given in the file "Licence"
- * distributed in the NASM archive.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "nasm.h"
-#include "nasmlib.h"
-#include "outform.h"
-
-#ifdef OF_ELF
-
-/*
- * Relocation types.
- */
-#define R_386_32 1                    /* ordinary absolute relocation */
-#define R_386_PC32 2                  /* PC-relative relocation */
-#define R_386_GOT32 3                 /* an offset into GOT */
-#define R_386_PLT32 4                 /* a PC-relative offset into PLT */
-#define R_386_GOTOFF 9                /* an offset from GOT base */
-#define R_386_GOTPC 10                /* a PC-relative offset _to_ GOT */
-
-struct Reloc {
-    struct Reloc *next;
-    long address;                     /* relative to _start_ of section */
-    long symbol;                      /* ELF symbol info thingy */
-    int type;                         /* type of relocation */
-};
-
-struct Symbol {
-    long strpos;                      /* string table position of name */
-    long section;                     /* section ID of the symbol */
-    int type;                         /* symbol type */
-    long value;                               /* address, or COMMON variable align */
-    long size;                        /* size of symbol */
-    long globnum;                     /* symbol table offset if global */
-    struct Symbol *next;              /* list of globals in each section */
-    struct Symbol *nextfwd;           /* list of unresolved-size symbols */
-    char *name;                               /* used temporarily if in above list */
-};
-
-#define SHT_PROGBITS 1
-#define SHT_NOBITS 8
-
-#define SHF_WRITE 1
-#define SHF_ALLOC 2
-#define SHF_EXECINSTR 4
-
-struct Section {
-    struct SAA *data;
-    unsigned long len, size, nrelocs;
-    long index;
-    int type;                         /* SHT_PROGBITS or SHT_NOBITS */
-    int align;                        /* alignment: power of two */
-    unsigned long flags;              /* section flags */
-    char *name;
-    struct SAA *rel;
-    long rellen;
-    struct Reloc *head, **tail;
-    struct Symbol *gsyms;             /* global symbols in section */
-};
-
-#define SECT_DELTA 32
-static struct Section **sects;
-static int nsects, sectlen;
-
-#define SHSTR_DELTA 256
-static char *shstrtab;
-static int shstrtablen, shstrtabsize;
-
-static struct SAA *syms;
-static unsigned long nlocals, nglobs;
-
-static long def_seg;
-
-static struct RAA *bsym;
-
-static struct SAA *strs;
-static unsigned long strslen;
-
-static FILE *elffp;
-static efunc error;
-static evalfunc evaluate;
-
-static struct Symbol *fwds;
-
-static char elf_module[FILENAME_MAX];
-
-extern struct ofmt of_elf;
-
-#define SHN_ABS 0xFFF1
-#define SHN_COMMON 0xFFF2
-#define SHN_UNDEF 0
-
-#define SYM_SECTION 0x04
-#define SYM_GLOBAL 0x10
-#define SYM_DATA 0x01
-#define SYM_FUNCTION 0x02
-
-#define GLOBAL_TEMP_BASE 15           /* bigger than any constant sym id */
-
-#define SEG_ALIGN 16                  /* alignment of sections in file */
-#define SEG_ALIGN_1 (SEG_ALIGN-1)
-
-static const char align_str[SEG_ALIGN] = ""; /* ANSI will pad this with 0s */
-
-#define ELF_MAX_SECTIONS 16           /* really 10, but let's play safe */
-static struct ELF_SECTDATA {
-    void *data;
-    long len;
-    int is_saa;
-} *elf_sects;
-static int elf_nsect;
-static long elf_foffs;
-
-static void elf_write(void);
-static void elf_sect_write(struct Section *, unsigned char *, unsigned long);
-static void elf_section_header (int, int, int, void *, int, long,
-                               int, int, int, int);
-static void elf_write_sections (void);
-static struct SAA *elf_build_symtab (long *, long *);
-static struct SAA *elf_build_reltab (long *, struct Reloc *);
-static void add_sectname (char *, char *);
-
-/*
- * Special section numbers which are used to define ELF special
- * symbols, which can be used with WRT to provide PIC relocation
- * types.
- */
-static long elf_gotpc_sect, elf_gotoff_sect;
-static long elf_got_sect, elf_plt_sect;
-static long elf_sym_sect;
-
-static void elf_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
-{
-    elffp = fp;
-    error = errfunc;
-    evaluate = eval;
-    (void) ldef;                      /* placate optimisers */
-    sects = NULL;
-    nsects = sectlen = 0;
-    syms = saa_init((long)sizeof(struct Symbol));
-    nlocals = nglobs = 0;
-    bsym = raa_init();
-    strs = saa_init(1L);
-    saa_wbytes (strs, "\0", 1L);
-    saa_wbytes (strs, elf_module, (long)(strlen(elf_module)+1));
-    strslen = 2+strlen(elf_module);
-    shstrtab = NULL;
-    shstrtablen = shstrtabsize = 0;;
-    add_sectname ("", "");
-
-    fwds = NULL;
-
-    elf_gotpc_sect = seg_alloc();
-    ldef("..gotpc", elf_gotpc_sect+1, 0L, NULL, FALSE, FALSE, &of_elf, error);
-    elf_gotoff_sect = seg_alloc();
-    ldef("..gotoff", elf_gotoff_sect+1, 0L, NULL, FALSE, FALSE,&of_elf,error);
-    elf_got_sect = seg_alloc();
-    ldef("..got", elf_got_sect+1, 0L, NULL, FALSE, FALSE, &of_elf, error);
-    elf_plt_sect = seg_alloc();
-    ldef("..plt", elf_plt_sect+1, 0L, NULL, FALSE, FALSE, &of_elf, error);
-    elf_sym_sect = seg_alloc();
-    ldef("..sym", elf_sym_sect+1, 0L, NULL, FALSE, FALSE, &of_elf, error);
-
-    def_seg = seg_alloc();
-}
-
-static void elf_cleanup(int debuginfo) 
-{
-    struct Reloc *r;
-    int i;
-
-    (void) debuginfo;
-
-    elf_write();
-    fclose (elffp);
-    for (i=0; i<nsects; i++) {
-       if (sects[i]->type != SHT_NOBITS)
-           saa_free (sects[i]->data);
-       if (sects[i]->head)
-           saa_free (sects[i]->rel);
-       while (sects[i]->head) {
-           r = sects[i]->head;
-           sects[i]->head = sects[i]->head->next;
-           nasm_free (r);
-       }
-    }
-    nasm_free (sects);
-    saa_free (syms);
-    raa_free (bsym);
-    saa_free (strs);
-}
-
-static void add_sectname (char *firsthalf, char *secondhalf) 
-{
-    int len = strlen(firsthalf)+strlen(secondhalf);
-    while (shstrtablen + len + 1 > shstrtabsize)
-       shstrtab = nasm_realloc (shstrtab, (shstrtabsize += SHSTR_DELTA));
-    strcpy (shstrtab+shstrtablen, firsthalf);
-    strcat (shstrtab+shstrtablen, secondhalf);
-    shstrtablen += len+1;
-}
-
-static int elf_make_section (char *name, int type, int flags, int align) 
-{
-    struct Section *s;
-
-    s = nasm_malloc (sizeof(*s));
-
-    if (type != SHT_NOBITS)
-       s->data = saa_init (1L);
-    s->head = NULL;
-    s->tail = &s->head;
-    s->len = s->size = 0;
-    s->nrelocs = 0;
-    if (!strcmp(name, ".text"))
-       s->index = def_seg;
-    else
-       s->index = seg_alloc();
-    add_sectname ("", name);
-    s->name = nasm_malloc (1+strlen(name));
-    strcpy (s->name, name);
-    s->type = type;
-    s->flags = flags;
-    s->align = align;
-    s->gsyms = NULL;
-
-    if (nsects >= sectlen)
-       sects = nasm_realloc (sects, (sectlen += SECT_DELTA)*sizeof(*sects));
-    sects[nsects++] = s;
-
-    return nsects-1;
-}
-
-static long elf_section_names (char *name, int pass, int *bits) 
-{
-    char *p;
-    int flags_and, flags_or, type, align, i;
-
-    /*
-     * Default is 32 bits.
-     */
-    if (!name) {
-       *bits = 32;
-       return def_seg;
-    }
-
-    p = name;
-    while (*p && !isspace(*p)) p++;
-    if (*p) *p++ = '\0';
-    flags_and = flags_or = type = align = 0;
-
-    while (*p && isspace(*p)) p++;
-    while (*p) {
-       char *q = p;
-       while (*p && !isspace(*p)) p++;
-       if (*p) *p++ = '\0';
-       while (*p && isspace(*p)) p++;
-       
-       if (!nasm_strnicmp(q, "align=", 6)) {
-           align = atoi(q+6);
-           if (align == 0)
-               align = 1;
-           if ( (align-1) & align ) {   /* means it's not a power of two */
-               error (ERR_NONFATAL, "section alignment %d is not"
-                      " a power of two", align);
-               align = 1;
-           }
-       } else if (!nasm_stricmp(q, "alloc")) {
-           flags_and |= SHF_ALLOC;
-           flags_or |= SHF_ALLOC;
-       } else if (!nasm_stricmp(q, "noalloc")) {
-           flags_and |= SHF_ALLOC;
-           flags_or &= ~SHF_ALLOC;
-       } else if (!nasm_stricmp(q, "exec")) {
-           flags_and |= SHF_EXECINSTR;
-           flags_or |= SHF_EXECINSTR;
-       } else if (!nasm_stricmp(q, "noexec")) {
-           flags_and |= SHF_EXECINSTR;
-           flags_or &= ~SHF_EXECINSTR;
-       } else if (!nasm_stricmp(q, "write")) {
-           flags_and |= SHF_WRITE;
-           flags_or |= SHF_WRITE;
-       } else if (!nasm_stricmp(q, "nowrite")) {
-           flags_and |= SHF_WRITE;
-           flags_or &= ~SHF_WRITE;
-       } else if (!nasm_stricmp(q, "progbits")) {
-           type = SHT_PROGBITS;
-       } else if (!nasm_stricmp(q, "nobits")) {
-           type = SHT_NOBITS;
-       }
-    }
-
-    if (!strcmp(name, ".comment") ||
-       !strcmp(name, ".shstrtab") ||
-       !strcmp(name, ".symtab") ||
-       !strcmp(name, ".strtab")) {
-       error (ERR_NONFATAL, "attempt to redefine reserved section"
-              "name `%s'", name);
-       return NO_SEG;
-    }
-
-    for (i=0; i<nsects; i++)
-       if (!strcmp(name, sects[i]->name))
-           break;
-    if (i == nsects) {
-       if (!strcmp(name, ".text"))
-           i = elf_make_section (name, SHT_PROGBITS,
-                                 SHF_ALLOC | SHF_EXECINSTR, 16);
-       else if (!strcmp(name, ".data"))
-           i = elf_make_section (name, SHT_PROGBITS,
-                                 SHF_ALLOC | SHF_WRITE, 4);
-       else if (!strcmp(name, ".bss"))
-           i = elf_make_section (name, SHT_NOBITS,
-                                 SHF_ALLOC | SHF_WRITE, 4);
-       else
-           i = elf_make_section (name, SHT_PROGBITS, SHF_ALLOC, 1);
-       if (type)
-           sects[i]->type = type;
-       if (align)
-           sects[i]->align = align;
-       sects[i]->flags &= ~flags_and;
-       sects[i]->flags |= flags_or;
-    } else if (pass == 1) {
-       if (type || align || flags_and)
-           error (ERR_WARNING, "section attributes ignored on"
-                  " redeclaration of section `%s'", name);
-    }
-
-    return sects[i]->index;
-}
-
-static void elf_deflabel (char *name, long segment, long offset,
-                          int is_global, char *special) 
-{
-    int pos = strslen;
-    struct Symbol *sym;
-    int special_used = FALSE;
-
-#if defined(DEBUG) && DEBUG>2
-fprintf(stderr, " elf_deflabel: %s, seg=%ld, off=%ld, is_global=%d, %s\n",
-      name, segment, offset, is_global, special);
-#endif
-    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
-       /*
-        * This is a NASM special symbol. We never allow it into
-        * the ELF symbol table, even if it's a valid one. If it
-        * _isn't_ a valid one, we should barf immediately.
-        */
-       if (strcmp(name, "..gotpc") && strcmp(name, "..gotoff") &&
-           strcmp(name, "..got") && strcmp(name, "..plt") &&
-           strcmp(name, "..sym"))
-           error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
-       return;
-    }
-
-    if (is_global == 3) {
-       struct Symbol **s;
-       /*
-        * Fix up a forward-reference symbol size from the first
-        * pass.
-        */
-       for (s = &fwds; *s; s = &(*s)->nextfwd)
-           if (!strcmp((*s)->name, name)) {
-               struct tokenval tokval;
-               expr *e;
-               char *p = special;
-
-               while (*p && !isspace(*p)) p++;
-               while (*p && isspace(*p)) p++;
-               stdscan_reset();
-               stdscan_bufptr = p;
-               tokval.t_type = TOKEN_INVALID;
-               e = evaluate(stdscan, NULL, &tokval, NULL, 1, error, NULL);
-               if (e) {
-                   if (!is_simple(e))
-                       error (ERR_NONFATAL, "cannot use relocatable"
-                              " expression as symbol size");
-                   else
-                       (*s)->size = reloc_value(e);
-               }
-
-               /*
-                * Remove it from the list of unresolved sizes.
-                */
-               nasm_free ((*s)->name);
-               *s = (*s)->nextfwd;
-               return;
-           }
-       return;                        /* it wasn't an important one */
-    }
-
-    saa_wbytes (strs, name, (long)(1+strlen(name)));
-    strslen += 1+strlen(name);
-
-    sym = saa_wstruct (syms);
-
-    sym->strpos = pos;
-    sym->type = is_global ? SYM_GLOBAL : 0;
-    sym->size = 0;
-    if (segment == NO_SEG)
-       sym->section = SHN_ABS;
-    else {
-       int i;
-       sym->section = SHN_UNDEF;
-       if (nsects == 0 && segment == def_seg) {
-           int tempint;
-           if (segment != elf_section_names (".text", 2, &tempint))
-               error (ERR_PANIC, "strange segment conditions in ELF driver");
-           sym->section = nsects;
-       } else {
-           for (i=0; i<nsects; i++)
-               if (segment == sects[i]->index) {
-                   sym->section = i+1;
-                   break;
-               }
-       }
-    }
-
-    if (is_global == 2) {
-       sym->size = offset;
-       sym->value = 0;
-       sym->section = SHN_COMMON;
-       /*
-        * We have a common variable. Check the special text to see
-        * if it's a valid number and power of two; if so, store it
-        * as the alignment for the common variable.
-        */
-       if (special) {
-           int err;
-           sym->value = readnum (special, &err);
-           if (err)
-               error(ERR_NONFATAL, "alignment constraint `%s' is not a"
-                     " valid number", special);
-           else if ( (sym->value | (sym->value-1)) != 2*sym->value - 1)
-               error(ERR_NONFATAL, "alignment constraint `%s' is not a"
-                     " power of two", special);
-       }
-       special_used = TRUE;
-    } else
-       sym->value = (sym->section == SHN_UNDEF ? 0 : offset);
-
-    if (sym->type == SYM_GLOBAL) {
-       /*
-        * There's a problem here that needs fixing. 
-        * If sym->section == SHN_ABS, then the first line of the
-        * else section causes a core dump, because its a reference
-        * beyond the end of the section array.
-        * This behaviour is exhibited by this code:
-        *     GLOBAL crash_nasm
-        *     crash_nasm equ 0
-        *
-        * I'm not sure how to procede, because I haven't got the
-        * first clue about how ELF works, so I don't know what to
-        * do with it. Furthermore, I'm not sure what the rest of this
-        * section of code does. Help?
-        *
-        * For now, I'll see if doing absolutely nothing with it will
-        * work...
-        */
-       if (sym->section == SHN_UNDEF || sym->section == SHN_COMMON)
-       {
-           bsym = raa_write (bsym, segment, nglobs);
-       }
-       else if (sym->section != SHN_ABS) 
-       {
-           /*
-            * This is a global symbol; so we must add it to the linked
-            * list of global symbols in its section. We'll push it on
-            * the beginning of the list, because it doesn't matter
-            * much which end we put it on and it's easier like this.
-            *
-            * In addition, we check the special text for symbol
-            * type and size information.
-            */
-           sym->next = sects[sym->section-1]->gsyms;
-           sects[sym->section-1]->gsyms = sym;
-
-           if (special) {
-               int n = strcspn(special, " ");
-
-               if (!nasm_strnicmp(special, "function", n))
-                   sym->type |= SYM_FUNCTION;
-               else if (!nasm_strnicmp(special, "data", n) ||
-                        !nasm_strnicmp(special, "object", n))
-                   sym->type |= SYM_DATA;
-               else
-                   error(ERR_NONFATAL, "unrecognised symbol type `%.*s'",
-                         n, special);
-               if (special[n]) {
-                   struct tokenval tokval;
-                   expr *e;
-                   int fwd = FALSE;
-                   char *saveme=stdscan_bufptr;   /* bugfix? fbk 8/10/00 */
-
-                   while (special[n] && isspace(special[n]))
-                       n++;
-                   /*
-                    * We have a size expression; attempt to
-                    * evaluate it.
-                    */
-                   stdscan_reset();
-                   stdscan_bufptr = special+n;
-                   tokval.t_type = TOKEN_INVALID;
-                   e = evaluate(stdscan, NULL, &tokval, &fwd, 0, error, NULL);
-                   if (fwd) {
-                       sym->nextfwd = fwds;
-                       fwds = sym;
-                       sym->name = nasm_strdup(name);
-                   } else if (e) {
-                       if (!is_simple(e))
-                           error (ERR_NONFATAL, "cannot use relocatable"
-                                  " expression as symbol size");
-                       else
-                           sym->size = reloc_value(e);
-                   }
-                   stdscan_bufptr=saveme;    /* bugfix? fbk 8/10/00 */
-               }
-               special_used = TRUE;
-           }
-       }
-       sym->globnum = nglobs;
-       nglobs++;
-    } else
-       nlocals++;
-
-    if (special && !special_used)
-       error(ERR_NONFATAL, "no special symbol features supported here");
-}
-
-static void elf_add_reloc (struct Section *sect, long segment,
-                          int type) 
-{
-    struct Reloc *r;
-
-    r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
-    sect->tail = &r->next;
-    r->next = NULL;
-
-    r->address = sect->len;
-    if (segment == NO_SEG)
-       r->symbol = 2;
-    else {
-       int i;
-       r->symbol = 0;
-       for (i=0; i<nsects; i++)
-           if (segment == sects[i]->index)
-               r->symbol = i+3;
-       if (!r->symbol)
-           r->symbol = GLOBAL_TEMP_BASE + raa_read(bsym, segment);
-    }
-    r->type = type;
-
-    sect->nrelocs++;
-}
-
-/*
- * This routine deals with ..got and ..sym relocations: the more
- * complicated kinds. In shared-library writing, some relocations
- * with respect to global symbols must refer to the precise symbol
- * rather than referring to an offset from the base of the section
- * _containing_ the symbol. Such relocations call to this routine,
- * which searches the symbol list for the symbol in question.
- *
- * R_386_GOT32 references require the _exact_ symbol address to be
- * used; R_386_32 references can be at an offset from the symbol.
- * The boolean argument `exact' tells us this.
- *
- * Return value is the adjusted value of `addr', having become an
- * offset from the symbol rather than the section. Should always be
- * zero when returning from an exact call.
- *
- * Limitation: if you define two symbols at the same place,
- * confusion will occur.
- *
- * Inefficiency: we search, currently, using a linked list which
- * isn't even necessarily sorted.
- */
-static long elf_add_gsym_reloc (struct Section *sect,
-                               long segment, long offset,
-                               int type, int exact) 
-{
-    struct Reloc *r;
-    struct Section *s;
-    struct Symbol *sym, *sm;
-    int i;
-
-    /*
-     * First look up the segment/offset pair and find a global
-     * symbol corresponding to it. If it's not one of our segments,
-     * then it must be an external symbol, in which case we're fine
-     * doing a normal elf_add_reloc after first sanity-checking
-     * that the offset from the symbol is zero.
-     */
-    s = NULL;
-    for (i=0; i<nsects; i++)
-       if (segment == sects[i]->index) {
-           s = sects[i];
-           break;
-       }
-    if (!s) {
-       if (exact && offset != 0)
-           error (ERR_NONFATAL, "unable to find a suitable global symbol"
-                  " for this reference");
-       else
-           elf_add_reloc (sect, segment, type);
-       return offset;
-    }
-
-    if (exact) {
-       /*
-        * Find a symbol pointing _exactly_ at this one.
-        */
-       for (sym = s->gsyms; sym; sym = sym->next)
-           if (sym->value == offset)
-               break;
-    } else {
-       /*
-        * Find the nearest symbol below this one.
-        */
-       sym = NULL;
-       for (sm = s->gsyms; sm; sm = sm->next)
-           if (sm->value <= offset && (!sym || sm->value > sym->value))
-               sym = sm;
-    }
-    if (!sym && exact) {
-       error (ERR_NONFATAL, "unable to find a suitable global symbol"
-              " for this reference");
-       return 0;
-    }
-
-    r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
-    sect->tail = &r->next;
-    r->next = NULL;
-
-    r->address = sect->len;
-    r->symbol = GLOBAL_TEMP_BASE + sym->globnum;
-    r->type = type;
-
-    sect->nrelocs++;
-
-    return offset - sym->value;
-}
-
-static void elf_out (long segto, void *data, unsigned long type,
-                     long segment, long wrt) 
-{
-    struct Section *s;
-    long realbytes = type & OUT_SIZMASK;
-    long addr;
-    unsigned char mydata[4], *p;
-    int i;
-
-    type &= OUT_TYPMASK;
-
-    /*
-     * handle absolute-assembly (structure definitions)
-     */
-    if (segto == NO_SEG) {
-       if (type != OUT_RESERVE)
-           error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
-                  " space");
-       return;
-    }
-
-    s = NULL;
-    for (i=0; i<nsects; i++)
-       if (segto == sects[i]->index) {
-           s = sects[i];
-           break;
-       }
-    if (!s) {
-       int tempint;                   /* ignored */
-       if (segto != elf_section_names (".text", 2, &tempint))
-           error (ERR_PANIC, "strange segment conditions in ELF driver");
-       else
-           s = sects[nsects-1];
-    }
-
-    if (s->type == SHT_NOBITS && type != OUT_RESERVE) {
-       error(ERR_WARNING, "attempt to initialise memory in"
-             " BSS section `%s': ignored", s->name);
-       if (type == OUT_REL2ADR)
-           realbytes = 2;
-       else if (type == OUT_REL4ADR)
-           realbytes = 4;
-       s->len += realbytes;
-       return;
-    }
-
-    if (type == OUT_RESERVE) {
-       if (s->type == SHT_PROGBITS) {
-           error(ERR_WARNING, "uninitialised space declared in"
-                 " non-BSS section `%s': zeroing", s->name);
-           elf_sect_write (s, NULL, realbytes);
-       } else
-           s->len += realbytes;
-    } else if (type == OUT_RAWDATA) {
-       if (segment != NO_SEG)
-           error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
-       elf_sect_write (s, data, realbytes);
-    } else if (type == OUT_ADDRESS) {
-       addr = *(long *)data;
-       if (segment != NO_SEG) {
-           if (segment % 2) {
-               error(ERR_NONFATAL, "ELF format does not support"
-                     " segment base references");
-           } else {
-               if (wrt == NO_SEG) {
-                   elf_add_reloc (s, segment, R_386_32);
-               } else if (wrt == elf_gotpc_sect+1) {
-                   /*
-                    * The user will supply GOT relative to $$. ELF
-                    * will let us have GOT relative to $. So we
-                    * need to fix up the data item by $-$$.
-                    */
-                   addr += s->len;
-                   elf_add_reloc (s, segment, R_386_GOTPC);
-               } else if (wrt == elf_gotoff_sect+1) {
-                   elf_add_reloc (s, segment, R_386_GOTOFF);
-               } else if (wrt == elf_got_sect+1) {
-                   addr = elf_add_gsym_reloc (s, segment, addr,
-                                              R_386_GOT32, TRUE);
-               } else if (wrt == elf_sym_sect+1) {
-                   addr = elf_add_gsym_reloc (s, segment, addr,
-                                              R_386_32, FALSE);
-               } else if (wrt == elf_plt_sect+1) {
-                   error(ERR_NONFATAL, "ELF format cannot produce non-PC-"
-                         "relative PLT references");
-               } else {
-                   error (ERR_NONFATAL, "ELF format does not support this"
-                          " use of WRT");
-                   wrt = NO_SEG;      /* we can at least _try_ to continue */
-               }
-           }
-       }
-       p = mydata;
-       if (realbytes != 4 && segment != NO_SEG)
-           error (ERR_NONFATAL, "ELF format does not support non-32-bit"
-                  " relocations");
-       WRITELONG (p, addr);
-       elf_sect_write (s, mydata, realbytes);
-    } else if (type == OUT_REL2ADR) {
-       error (ERR_NONFATAL, "ELF format does not support 16-bit"
-              " relocations");
-    } else if (type == OUT_REL4ADR) {
-       if (segment == segto)
-           error(ERR_PANIC, "intra-segment OUT_REL4ADR");
-       if (segment != NO_SEG && segment % 2) {
-           error(ERR_NONFATAL, "ELF format does not support"
-                 " segment base references");
-       } else {
-           if (wrt == NO_SEG) {
-               elf_add_reloc (s, segment, R_386_PC32);
-           } else if (wrt == elf_plt_sect+1) {
-               elf_add_reloc (s, segment, R_386_PLT32);
-           } else if (wrt == elf_gotpc_sect+1 ||
-                      wrt == elf_gotoff_sect+1 ||
-                      wrt == elf_got_sect+1) {
-               error(ERR_NONFATAL, "ELF format cannot produce PC-"
-                     "relative GOT references");
-           } else {
-               error (ERR_NONFATAL, "ELF format does not support this"
-                      " use of WRT");
-               wrt = NO_SEG;      /* we can at least _try_ to continue */
-           }
-       }
-       p = mydata;
-       WRITELONG (p, *(long*)data - realbytes);
-       elf_sect_write (s, mydata, 4L);
-    }
-}
-
-static void elf_write(void) 
-{
-    int nsections, align;
-    char *p;
-    int commlen;
-    char comment[64];
-    int i;
-
-    struct SAA *symtab;
-    long symtablen, symtablocal;
-
-    /*
-     * Work out how many sections we will have. We have SHN_UNDEF,
-     * then the flexible user sections, then the four fixed
-     * sections `.comment', `.shstrtab', `.symtab' and `.strtab',
-     * then optionally relocation sections for the user sections.
-     */
-    nsections = 5;                    /* SHN_UNDEF and the fixed ones */
-    add_sectname ("", ".comment");
-    add_sectname ("", ".shstrtab");
-    add_sectname ("", ".symtab");
-    add_sectname ("", ".strtab");
-    for (i=0; i<nsects; i++) {
-       nsections++;                   /* for the section itself */
-       if (sects[i]->head) {
-           nsections++;               /* for its relocations */
-           add_sectname (".rel", sects[i]->name);
-       }
-    }
-
-    /*
-     * Do the comment.
-     */
-    *comment = '\0';
-    commlen = 2+sprintf(comment+1, "The Netwide Assembler %s", NASM_VER);
-
-    /*
-     * Output the ELF header.
-     */
-    fwrite ("\177ELF\1\1\1\0\0\0\0\0\0\0\0\0", 16, 1, elffp);
-    fwriteshort (1, elffp);           /* ET_REL relocatable file */
-    fwriteshort (3, elffp);           /* EM_386 processor ID */
-    fwritelong (1L, elffp);           /* EV_CURRENT file format version */
-    fwritelong (0L, elffp);           /* no entry point */
-    fwritelong (0L, elffp);           /* no program header table */
-    fwritelong (0x40L, elffp);        /* section headers straight after
-                                       * ELF header plus alignment */
-    fwritelong (0L, elffp);           /* 386 defines no special flags */
-    fwriteshort (0x34, elffp);        /* size of ELF header */
-    fwriteshort (0, elffp);           /* no program header table, again */
-    fwriteshort (0, elffp);           /* still no program header table */
-    fwriteshort (0x28, elffp);        /* size of section header */
-    fwriteshort (nsections, elffp);    /* number of sections */
-    fwriteshort (nsects+2, elffp);     /* string table section index for
-                                       * section header table */
-    fwritelong (0L, elffp);           /* align to 0x40 bytes */
-    fwritelong (0L, elffp);
-    fwritelong (0L, elffp);
-
-    /*
-     * Build the symbol table and relocation tables.
-     */
-    symtab = elf_build_symtab (&symtablen, &symtablocal);
-    for (i=0; i<nsects; i++)
-       if (sects[i]->head)
-           sects[i]->rel = elf_build_reltab (&sects[i]->rellen,
-                                             sects[i]->head);
-
-    /*
-     * Now output the section header table.
-     */
-
-    elf_foffs = 0x40 + 0x28 * nsections;
-    align = ((elf_foffs+SEG_ALIGN_1) & ~SEG_ALIGN_1) - elf_foffs;
-    elf_foffs += align;
-    elf_nsect = 0;
-    elf_sects = nasm_malloc(sizeof(*elf_sects) * (2 * nsects + 10));
-
-    elf_section_header (0, 0, 0, NULL, FALSE, 0L, 0, 0, 0, 0); /* SHN_UNDEF */
-    p = shstrtab+1;
-    for (i=0; i<nsects; i++) {
-       elf_section_header (p - shstrtab, sects[i]->type, sects[i]->flags,
-                           (sects[i]->type == SHT_PROGBITS ?
-                            sects[i]->data : NULL), TRUE,
-                           sects[i]->len, 0, 0, sects[i]->align, 0);
-       p += strlen(p)+1;
-    }
-    elf_section_header (p - shstrtab, 1, 0, comment, FALSE,
-                       (long)commlen, 0, 0, 1, 0);/* .comment */
-    p += strlen(p)+1;
-    elf_section_header (p - shstrtab, 3, 0, shstrtab, FALSE,
-                       (long)shstrtablen, 0, 0, 1, 0);/* .shstrtab */
-    p += strlen(p)+1;
-    elf_section_header (p - shstrtab, 2, 0, symtab, TRUE,
-                       symtablen, nsects+4, symtablocal, 4, 16);/* .symtab */
-    p += strlen(p)+1;
-    elf_section_header (p - shstrtab, 3, 0, strs, TRUE,
-                       strslen, 0, 0, 1, 0);       /* .strtab */
-    for (i=0; i<nsects; i++) if (sects[i]->head) {
-       p += strlen(p)+1;
-       elf_section_header (p - shstrtab, 9, 0, sects[i]->rel, TRUE,
-                           sects[i]->rellen, nsects+3, i+1, 4, 8);
-    }
-
-    fwrite (align_str, align, 1, elffp);
-
-    /*
-     * Now output the sections.
-     */
-    elf_write_sections();
-
-    nasm_free (elf_sects);
-    saa_free (symtab);
-}
-
-static struct SAA *elf_build_symtab (long *len, long *local) 
-{
-    struct SAA *s = saa_init(1L);
-    struct Symbol *sym;
-    unsigned char entry[16], *p;
-    int i;
-
-    *len = *local = 0;
-
-    /*
-     * First, an all-zeros entry, required by the ELF spec.
-     */
-    saa_wbytes (s, NULL, 16L);        /* null symbol table entry */
-    *len += 16;
-    (*local)++;
-
-    /*
-     * Next, an entry for the file name.
-     */
-    p = entry;
-    WRITELONG (p, 1);                 /* we know it's 1st thing in strtab */
-    WRITELONG (p, 0);                 /* no value */
-    WRITELONG (p, 0);                 /* no size either */
-    WRITESHORT (p, 4);                /* type FILE */
-    WRITESHORT (p, SHN_ABS);
-    saa_wbytes (s, entry, 16L);
-    *len += 16;
-    (*local)++;
-
-    /*
-     * Now some standard symbols defining the segments, for relocation
-     * purposes.
-     */
-    for (i = 1; i <= nsects+1; i++) {
-       p = entry;
-       WRITELONG (p, 0);              /* no symbol name */
-       WRITELONG (p, 0);              /* offset zero */
-       WRITELONG (p, 0);              /* size zero */
-       WRITESHORT (p, 3);             /* local section-type thing */
-       WRITESHORT (p, (i==1 ? SHN_ABS : i-1));   /* the section id */
-       saa_wbytes (s, entry, 16L);
-       *len += 16;
-       (*local)++;
-    }
-
-    /*
-     * Now the other local symbols.
-     */
-    saa_rewind (syms);
-    while ( (sym = saa_rstruct (syms)) ) {
-       if (sym->type & SYM_GLOBAL)
-           continue;
-       p = entry;
-       WRITELONG (p, sym->strpos);
-       WRITELONG (p, sym->value);
-       WRITELONG (p, sym->size);
-       WRITESHORT (p, sym->type);     /* local non-typed thing */
-       WRITESHORT (p, sym->section);
-       saa_wbytes (s, entry, 16L);
-        *len += 16;
-       (*local)++;
-    }
-
-    /*
-     * Now the global symbols.
-     */
-    saa_rewind (syms);
-    while ( (sym = saa_rstruct (syms)) ) {
-       if (!(sym->type & SYM_GLOBAL))
-           continue;
-       p = entry;
-       WRITELONG (p, sym->strpos);
-       WRITELONG (p, sym->value);
-       WRITELONG (p, sym->size);
-       WRITESHORT (p, sym->type);     /* global non-typed thing */
-       WRITESHORT (p, sym->section);
-       saa_wbytes (s, entry, 16L);
-       *len += 16;
-    }
-
-    return s;
-}
-
-static struct SAA *elf_build_reltab (long *len, struct Reloc *r) {
-    struct SAA *s;
-    unsigned char *p, entry[8];
-
-    if (!r)
-       return NULL;
-
-    s = saa_init(1L);
-    *len = 0;
-
-    while (r) {
-       long sym = r->symbol;
-
-       if (sym >= GLOBAL_TEMP_BASE)
-           sym += -GLOBAL_TEMP_BASE + (nsects+3) + nlocals;
-
-       p = entry;
-       WRITELONG (p, r->address);
-       WRITELONG (p, (sym << 8) + r->type);
-       saa_wbytes (s, entry, 8L);
-       *len += 8;
-
-       r = r->next;
-    }
-
-    return s;
-}
-
-static void elf_section_header (int name, int type, int flags,
-                               void *data, int is_saa, long datalen,
-                               int link, int info, int align, int eltsize) 
-{
-    elf_sects[elf_nsect].data = data;
-    elf_sects[elf_nsect].len = datalen;
-    elf_sects[elf_nsect].is_saa = is_saa;
-    elf_nsect++;
-
-    fwritelong ((long)name, elffp);
-    fwritelong ((long)type, elffp);
-    fwritelong ((long)flags, elffp);
-    fwritelong (0L, elffp);           /* no address, ever, in object files */
-    fwritelong (type == 0 ? 0L : elf_foffs, elffp);
-    fwritelong (datalen, elffp);
-    if (data)
-       elf_foffs += (datalen+SEG_ALIGN_1) & ~SEG_ALIGN_1;
-    fwritelong ((long)link, elffp);
-    fwritelong ((long)info, elffp);
-    fwritelong ((long)align, elffp);
-    fwritelong ((long)eltsize, elffp);
-}
-
-static void elf_write_sections (void) 
-{
-    int i;
-    for (i = 0; i < elf_nsect; i++)
-       if (elf_sects[i].data) {
-           long len = elf_sects[i].len;
-           long reallen = (len+SEG_ALIGN_1) & ~SEG_ALIGN_1;
-           long align = reallen - len;
-           if (elf_sects[i].is_saa)
-               saa_fpwrite (elf_sects[i].data, elffp);
-           else
-               fwrite (elf_sects[i].data, len, 1, elffp);
-           fwrite (align_str, align, 1, elffp);
-       }
-}
-
-static void elf_sect_write (struct Section *sect,
-                            unsigned char *data, unsigned long len) 
-{
-    saa_wbytes (sect->data, data, len);
-    sect->len += len;
-}
-
-static long elf_segbase (long segment) 
-{
-    return segment;
-}
-
-static int elf_directive (char *directive, char *value, int pass) 
-{
-    return 0;
-}
-
-static void elf_filename (char *inname, char *outname, efunc error) 
-{
-    strcpy(elf_module, inname);
-    standard_extension (inname, outname, ".o", error);
-}
-
-static char *elf_stdmac[] = {
-    "%define __SECT__ [section .text]",
-    "%macro __NASM_CDecl__ 1",
-    "%define $_%1 $%1",
-    "%endmacro",
-    NULL
-};
-static int elf_set_info(enum geninfo type, char **val)
-{
-    return 0;
-}
-
-struct ofmt of_elf = {
-    "ELF32 (i386) object files (e.g. Linux)",
-    "elf",
-    NULL,
-    null_debug_arr,
-    &null_debug_form,
-    elf_stdmac,
-    elf_init,
-    elf_set_info,
-    elf_out,
-    elf_deflabel,
-    elf_section_names,
-    elf_segbase,
-    elf_directive,
-    elf_filename,
-    elf_cleanup
-};
-
-#endif /* OF_ELF */
diff --git a/outforms.h b/outforms.h
deleted file mode 100644 (file)
index 2afbbe2..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-/* outform.h   header file for binding output format drivers to the
- *              remainder of the code in the Netwide Assembler
- *
- * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
- * Julian Hall. All rights reserved. The software is
- * redistributable under the licence given in the file "Licence"
- * distributed in the NASM archive.
- */
-
-/*
- * This header file allows configuration of which output formats
- * get compiled into the NASM binary. You can configure by defining
- * various preprocessor symbols beginning with "OF_", either on the
- * compiler command line or at the top of this file.
- *
- * OF_ONLY                -- only include specified object formats
- * OF_name                -- ensure that output format 'name' is included
- * OF_NO_name             -- remove output format 'name'
- * OF_DOS                 -- ensure that 'obj', 'bin' & 'win32' are included.
- * OF_UNIX                -- ensure that 'aout', 'aoutb', 'coff', 'elf' are in.
- * OF_OTHERS              -- ensure that 'bin', 'as86' & 'rdf' are in.
- * OF_ALL                 -- ensure that all formats are included.
- *
- * OF_DEFAULT=of_name     -- ensure that 'name' is the default format.
- *
- * eg: -DOF_UNIX -DOF_ELF -DOF_DEFAULT=of_elf would be a suitable config
- * for an average linux system.
- *
- * Default config = -DOF_ALL -DOF_DEFAULT=of_bin
- *
- * You probably only want to set these options while compiling 'nasm.c'. */
-
-#ifndef NASM_OUTFORMS_H
-#define NASM_OUTFORMS_H
-
-#include "nasm.h"
-
-/* -------------- USER MODIFIABLE PART ---------------- */
-
-/*
- * Insert #defines here in accordance with the configuration
- * instructions above.
- *
- * E.g.
- *
- * #define OF_ONLY
- * #define OF_OBJ
- * #define OF_BIN
- *
- * for a 16-bit DOS assembler with no extraneous formats.
- */
-
-/* ------------ END USER MODIFIABLE PART -------------- */
-
-/* ====configurable info begins here==== */
-/* formats configurable:
- * bin,obj,elf,aout,aoutb,coff,win32,as86,rdf */
-
-/* process options... */
-
-#ifndef OF_ONLY
-#ifndef OF_ALL
-#define OF_ALL      /* default is to have all formats */
-#endif
-#endif
-
-#ifdef OF_ALL      /* set all formats on... */
-#ifndef OF_BIN
-#define OF_BIN
-#endif
-#ifndef OF_OBJ
-#define OF_OBJ
-#endif
-#ifndef OF_ELF
-#define OF_ELF
-#endif
-#ifndef OF_COFF
-#define OF_COFF
-#endif
-#ifndef OF_AOUT
-#define OF_AOUT
-#endif
-#ifndef OF_AOUTB
-#define OF_AOUTB
-#endif
-#ifndef OF_WIN32
-#define OF_WIN32
-#endif
-#ifndef OF_AS86
-#define OF_AS86
-#endif
-#ifndef OF_RDF
-#define OF_RDF
-#endif
-#endif /* OF_ALL */
-
-/* turn on groups of formats specified.... */
-#ifdef OF_DOS
-#ifndef OF_OBJ
-#define OF_OBJ
-#endif
-#ifndef OF_BIN
-#define OF_BIN
-#endif
-#ifndef OF_WIN32
-#define OF_WIN32
-#endif
-#endif
-
-#ifdef OF_UNIX
-#ifndef OF_AOUT
-#define OF_AOUT
-#endif
-#ifndef OF_AOUTB
-#define OF_AOUTB
-#endif
-#ifndef OF_COFF
-#define OF_COFF
-#endif
-#ifndef OF_ELF
-#define OF_ELF
-#endif
-#endif
-
-#ifdef OF_OTHERS
-#ifndef OF_BIN
-#define OF_BIN
-#endif
-#ifndef OF_AS86
-#define OF_AS86
-#endif
-#ifndef OF_RDF
-#define OF_RDF
-#endif
-#endif
-
-/* finally... override any format specifically specifed to be off */
-#ifdef OF_NO_BIN
-#undef OF_BIN
-#endif
-#ifdef OF_NO_OBJ
-#undef OF_OBJ
-#endif
-#ifdef OF_NO_ELF
-#undef OF_ELF
-#endif
-#ifdef OF_NO_AOUT
-#undef OF_AOUT
-#endif
-#ifdef OF_NO_AOUTB
-#undef OF_AOUTB
-#endif
-#ifdef OF_NO_COFF
-#undef OF_COFF
-#endif
-#ifdef OF_NO_WIN32
-#undef OF_WIN32
-#endif
-#ifdef OF_NO_AS86
-#undef OF_AS86
-#endif
-#ifdef OF_NO_RDF
-#undef OF_RDF
-#endif
-
-#ifndef OF_DEFAULT
-#define OF_DEFAULT of_bin
-#endif
-
-#ifdef BUILD_DRIVERS_ARRAY            /* only if included from outform.c */
-
-/* pull in the externs for the different formats, then make the *drivers
- * array based on the above defines */
-
-extern struct ofmt of_bin;
-extern struct ofmt of_aout;
-extern struct ofmt of_aoutb;
-extern struct ofmt of_coff;
-extern struct ofmt of_elf;
-extern struct ofmt of_as86;
-extern struct ofmt of_obj;
-extern struct ofmt of_win32;
-extern struct ofmt of_rdf;
-extern struct ofmt of_dbg;
-
-struct ofmt *drivers[]={
-#ifdef OF_BIN
-    &of_bin,
-#endif
-#ifdef OF_AOUT
-    &of_aout,
-#endif
-#ifdef OF_AOUTB
-    &of_aoutb,
-#endif
-#ifdef OF_COFF
-    &of_coff,
-#endif
-#ifdef OF_ELF
-    &of_elf,
-#endif
-#ifdef OF_AS86
-    &of_as86,
-#endif
-#ifdef OF_OBJ
-    &of_obj,
-#endif
-#ifdef OF_WIN32
-    &of_win32,
-#endif
-#ifdef OF_RDF
-    &of_rdf,
-#endif
-#ifdef OF_DBG
-    &of_dbg,
-#endif
-
-   NULL
-};
-
-#endif  /* BUILD_DRIVERS_ARRAY */
-
-#endif  /* NASM_OUTFORMS_H */
diff --git a/outobj.c b/outobj.c
deleted file mode 100644 (file)
index 4d8b6c9..0000000
--- a/outobj.c
+++ /dev/null
@@ -1,2531 +0,0 @@
-/* outobj.c    output routines for the Netwide Assembler to produce
- *             .OBJ object files
- *
- * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
- * Julian Hall. All rights reserved. The software is
- * redistributable under the licence given in the file "Licence"
- * distributed in the NASM archive.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "nasm.h"
-#include "nasmlib.h"
-#include "outform.h"
-
-#ifdef OF_OBJ
-
-/*
- * outobj.c is divided into two sections.  The first section is low level
- * routines for creating obj records;  It has nearly zero NASM specific
- * code.  The second section is high level routines for processing calls and
- * data structures from the rest of NASM into obj format.
- *
- * It should be easy (though not zero work) to lift the first section out for
- * use as an obj file writer for some other assembler or compiler.
- */
-
-/*
- * These routines are built around the ObjRecord data struture.  An ObjRecord
- * holds an object file record that may be under construction or complete.
- *
- * A major function of these routines is to support continuation of an obj
- * record into the next record when the maximum record size is exceeded.  The
- * high level code does not need to worry about where the record breaks occur.
- * It does need to do some minor extra steps to make the automatic continuation
- * work.  Those steps may be skipped for records where the high level knows no
- * continuation could be required.
- *
- * 1) An ObjRecord is allocated and cleared by obj_new, or an existing ObjRecord
- *    is cleared by obj_clear.
- *
- * 2) The caller should fill in .type.
- *
- * 3) If the record is continuable and there is processing that must be done at
- *    the start of each record then the caller should fill in .ori with the
- *    address of the record initializer routine.
- *
- * 4) If the record is continuable and it should be saved (rather than emitted
- *    immediately) as each record is done, the caller should set .up to be a
- *    pointer to a location in which the caller keeps the master pointer to the
- *    ObjRecord.  When the record is continued, the obj_bump routine will then
- *    allocate a new ObjRecord structure and update the master pointer.
- *
- * 5) If the .ori field was used then the caller should fill in the .parm with
- *    any data required by the initializer.
- *
- * 6) The caller uses the routines: obj_byte, obj_word, obj_rword, obj_dword,
- *    obj_x, obj_index, obj_value and obj_name to fill in the various kinds of
- *    data required for this record.
- *
- * 7) If the record is continuable, the caller should call obj_commit at each
- *    point where breaking the record is permitted.
- *
- * 8) To write out the record, the caller should call obj_emit2.  If the
- *    caller has called obj_commit for all data written then he can get slightly
- *    faster code by calling obj_emit instead of obj_emit2.
- *
- * Most of these routines return an ObjRecord pointer.  This will be the input
- * pointer most of the time and will be the new location if the ObjRecord
- * moved as a result of the call.  The caller may ignore the return value in
- * three cases:  It is a "Never Reallocates" routine;  or  The caller knows
- * continuation is not possible;  or  The caller uses the master pointer for the
- * next operation.
- */
-
-#define RECORD_MAX 1024-3      /* maximal size of any record except type+reclen */
-#define OBJ_PARMS  3           /* maximum .parm used by any .ori routine */
-
-#define FIX_08_LOW      0x8000 /* location type for various fixup subrecords */
-#define FIX_16_OFFSET   0x8400
-#define FIX_16_SELECTOR 0x8800
-#define FIX_32_POINTER  0x8C00
-#define FIX_08_HIGH     0x9000
-#define FIX_32_OFFSET   0xA400
-#define FIX_48_POINTER  0xAC00
-
-enum RecordID {                               /* record ID codes */
-
-    THEADR = 0x80,                    /* module header */
-    COMENT = 0x88,                    /* comment record */
-
-    LINNUM = 0x94,                     /* line number record */
-    LNAMES = 0x96,                    /* list of names */
-
-    SEGDEF = 0x98,                    /* segment definition */
-    GRPDEF = 0x9A,                    /* group definition */
-    EXTDEF = 0x8C,                    /* external definition */
-    PUBDEF = 0x90,                    /* public definition */
-    COMDEF = 0xB0,                    /* common definition */
-
-    LEDATA = 0xA0,                    /* logical enumerated data */
-    FIXUPP = 0x9C,                    /* fixups (relocations) */
-    FIXU32 = 0x9D,                    /* 32-bit fixups (relocations) */
-
-    MODEND = 0x8A,                    /* module end */
-    MODE32 = 0x8B                     /* module end for 32-bit objects */
-};
-
-enum ComentID {                        /* ID codes for comment records */
-
-     dEXTENDED = 0xA1,                 /* tells that we are using translator-specific extensions */
-     dLINKPASS = 0xA2,                 /* link pass 2 marker */
-     dTYPEDEF = 0xE3,                  /* define a type */
-     dSYM = 0xE6,                      /* symbol debug record */
-     dFILNAME = 0xE8,                  /* file name record */
-     dCOMPDEF = 0xEA                   /* compiler type info */
-
-};
-
-typedef struct ObjRecord ObjRecord;
-typedef void ORI(ObjRecord *orp);
-
-struct ObjRecord {
-    ORI           *ori;                        /* Initialization routine           */
-    int            used;               /* Current data size                */
-    int            committed;          /* Data size at last boundary       */
-    int            x_size;             /* (see obj_x)                      */
-    unsigned int   type;               /* Record type                      */
-    ObjRecord     *child;              /* Associated record below this one */
-    ObjRecord    **up;                 /* Master pointer to this ObjRecord */
-    ObjRecord     *back;               /* Previous part of this record     */
-    unsigned long  parm[OBJ_PARMS];    /* Parameters for ori routine       */
-    unsigned char  buf[RECORD_MAX];
-};
-
-static void obj_fwrite(ObjRecord *orp);
-static void ori_ledata(ObjRecord *orp);
-static void ori_pubdef(ObjRecord *orp);
-static void ori_null(ObjRecord *orp);
-static ObjRecord *obj_commit(ObjRecord *orp);
-
-static int obj_uppercase;              /* Flag: all names in uppercase */
-static int obj_use32;                  /* Flag: at least one segment is 32-bit */
-
-/*
- * Clear an ObjRecord structure.  (Never reallocates).
- * To simplify reuse of ObjRecord's, .type, .ori and .parm are not cleared.
- */
-static ObjRecord *obj_clear(ObjRecord *orp) 
-{
-    orp->used = 0;
-    orp->committed = 0;
-    orp->x_size = 0;
-    orp->child = NULL;
-    orp->up = NULL;
-    orp->back = NULL;
-    return (orp);
-}
-
-/*
- * Emit an ObjRecord structure.  (Never reallocates).
- * The record is written out preceeded (recursively) by its previous part (if
- * any) and followed (recursively) by its child (if any).
- * The previous part and the child are freed.  The main ObjRecord is cleared,
- * not freed.
- */
-static ObjRecord *obj_emit(ObjRecord *orp) 
-{
-    if (orp->back) {
-       obj_emit(orp->back);
-       nasm_free(orp->back);
-    }
-
-    if (orp->committed)
-       obj_fwrite(orp);
-
-    if (orp->child) {
-       obj_emit(orp->child);
-       nasm_free(orp->child);
-    }
-
-    return (obj_clear(orp));
-}
-
-/*
- * Commit and Emit a record.  (Never reallocates).
- */
-static ObjRecord *obj_emit2(ObjRecord *orp) 
-{
-    obj_commit(orp);
-    return (obj_emit(orp));
-}
-
-/*
- * Allocate and clear a new ObjRecord;  Also sets .ori to ori_null
- */
-static ObjRecord *obj_new(void) 
-{
-    ObjRecord *orp;
-    
-    orp = obj_clear( nasm_malloc(sizeof(ObjRecord)) );
-    orp->ori = ori_null;
-    return (orp);
-}
-    
-/*
- * Advance to the next record because the existing one is full or its x_size
- * is incompatible.
- * Any uncommited data is moved into the next record.
- */
-static ObjRecord *obj_bump(ObjRecord *orp) 
-{
-    ObjRecord *nxt;
-    int used = orp->used;
-    int committed = orp->committed;
-
-    if (orp->up) {
-       *orp->up = nxt = obj_new();
-       nxt->ori = orp->ori;
-       nxt->type = orp->type;
-       nxt->up = orp->up;
-       nxt->back = orp;
-       memcpy( nxt->parm, orp->parm, sizeof(orp->parm));
-    } else
-       nxt = obj_emit(orp);
-
-    used -= committed;
-    if (used) {
-       nxt->committed = 1;
-       nxt->ori (nxt);
-       nxt->committed = nxt->used;
-       memcpy( nxt->buf + nxt->committed, orp->buf + committed, used);
-       nxt->used = nxt->committed + used;
-    }
-
-    return (nxt);
-}
-
-/*
- * Advance to the next record if necessary to allow the next field to fit.
- */
-static ObjRecord *obj_check(ObjRecord *orp, int size) 
-{
-    if (orp->used + size > RECORD_MAX)
-       orp = obj_bump(orp);
-
-    if (!orp->committed) {
-       orp->committed = 1;
-       orp->ori (orp);
-       orp->committed = orp->used;
-    }
-
-    return (orp);
-}
-
-/*
- * All data written so far is commited to the current record (won't be moved to
- * the next record in case of continuation).
- */
-static ObjRecord *obj_commit(ObjRecord *orp) 
-{
-    orp->committed = orp->used;
-    return (orp);
-}
-
-/*
- * Write a byte
- */
-static ObjRecord *obj_byte(ObjRecord *orp, unsigned char val) 
-{
-    orp = obj_check(orp, 1);
-    orp->buf[orp->used] = val;
-    orp->used++;
-    return (orp);
-}
-
-/*
- * Write a word
- */
-static ObjRecord *obj_word(ObjRecord *orp, unsigned int val) 
-{
-    orp = obj_check(orp, 2);
-    orp->buf[orp->used] = val;
-    orp->buf[orp->used+1] = val >> 8;
-    orp->used += 2;
-    return (orp);
-}
-
-/*
- * Write a reversed word
- */
-static ObjRecord *obj_rword(ObjRecord *orp, unsigned int val) 
-{
-    orp = obj_check(orp, 2);
-    orp->buf[orp->used] = val >> 8;
-    orp->buf[orp->used+1] = val;
-    orp->used += 2;
-    return (orp);
-}
-
-/*
- * Write a dword
- */
-static ObjRecord *obj_dword(ObjRecord *orp, unsigned long val) 
-{
-    orp = obj_check(orp, 4);
-    orp->buf[orp->used] = val;
-    orp->buf[orp->used+1] = val >> 8;
-    orp->buf[orp->used+2] = val >> 16;
-    orp->buf[orp->used+3] = val >> 24;
-    orp->used += 4;
-    return (orp);
-}
-
-/*
- * All fields of "size x" in one obj record must be the same size (either 16
- * bits or 32 bits).  There is a one bit flag in each record which specifies
- * which.
- * This routine is used to force the current record to have the desired
- * x_size.  x_size is normally automatic (using obj_x), so that this
- * routine should be used outside obj_x, only to provide compatibility with
- * linkers that have bugs in their processing of the size bit.
- */
-
-static ObjRecord *obj_force(ObjRecord *orp, int x)
-{
-    if (orp->x_size == (x^48))
-       orp = obj_bump(orp);
-    orp->x_size = x;
-       return (orp);
-}
-
-/*
- * This routine writes a field of size x.  The caller does not need to worry at
- * all about whether 16-bits or 32-bits are required.
- */
-static ObjRecord *obj_x(ObjRecord *orp, unsigned long val) 
-{
-    if (orp->type & 1)
-       orp->x_size = 32;
-    if (val > 0xFFFF)
-       orp = obj_force(orp, 32);
-    if (orp->x_size == 32)
-       return (obj_dword(orp, val));
-    orp->x_size = 16;
-    return (obj_word(orp, val));
-}
-
-/*
- * Writes an index
- */
-static ObjRecord *obj_index(ObjRecord *orp, unsigned int val) 
-{
-    if (val < 128)
-       return ( obj_byte(orp, val) );
-    return (obj_word(orp, (val>>8) | (val<<8) | 0x80));
-}
-
-/*
- * Writes a variable length value
- */
-static ObjRecord *obj_value(ObjRecord *orp, unsigned long val) 
-{
-    if (val <= 128)
-       return ( obj_byte(orp, val) );
-    if (val <= 0xFFFF) {
-       orp = obj_byte(orp, 129);
-       return ( obj_word(orp, val) );
-    }
-    if (val <= 0xFFFFFF)
-       return ( obj_dword(orp, (val<<8) + 132 ) );
-    orp = obj_byte(orp, 136);
-    return ( obj_dword(orp, val) );
-}
-
-/*
- * Writes a counted string
- */
-static ObjRecord *obj_name(ObjRecord *orp, char *name) 
-{
-    int len = strlen(name);
-    unsigned char *ptr;
-
-    orp = obj_check(orp, len+1);
-    ptr = orp->buf + orp->used;
-    *ptr++ = len;
-    orp->used += len+1;
-    if (obj_uppercase)
-       while (--len >= 0) {
-           *ptr++ = toupper(*name);
-           name++;
-    } else
-       memcpy(ptr, name, len);
-    return (orp);
-}
-
-/*
- * Initializer for an LEDATA record.
- * parm[0] = offset
- * parm[1] = segment index
- * During the use of a LEDATA ObjRecord, parm[0] is constantly updated to
- * represent the offset that would be required if the record were split at the
- * last commit point.
- * parm[2] is a copy of parm[0] as it was when the current record was initted.
- */
-static void ori_ledata(ObjRecord *orp) 
-{
-    obj_index (orp, orp->parm[1]);
-    orp->parm[2] = orp->parm[0];
-    obj_x (orp, orp->parm[0]);
-}
-
-/*
- * Initializer for a PUBDEF record.
- * parm[0] = group index
- * parm[1] = segment index
- * parm[2] = frame (only used when both indexes are zero)
- */
-static void ori_pubdef(ObjRecord *orp) 
-{
-    obj_index (orp, orp->parm[0]);
-    obj_index (orp, orp->parm[1]);
-    if ( !(orp->parm[0] | orp->parm[1]) )
-       obj_word (orp, orp->parm[2]);
-}
-
-/*
- * Initializer for a LINNUM record.
- * parm[0] = group index
- * parm[1] = segment index
- */
-static void ori_linnum(ObjRecord *orp) 
-{
-    obj_index (orp, orp->parm[0]);
-    obj_index (orp, orp->parm[1]);
-}
-/*
- * Initializer for a local vars record.
- */
-static void ori_local(ObjRecord *orp) 
-{
-    obj_byte (orp, 0x40);
-    obj_byte (orp, dSYM);
-}
-
-/*
- * Null initializer for records that continue without any header info
- */
-static void ori_null(ObjRecord *orp) 
-{
-    (void) orp;  /* Do nothing */
-}
-
-/*
- * This concludes the low level section of outobj.c
- */
-
-static char obj_infile[FILENAME_MAX];
-
-static efunc error;
-static evalfunc evaluate;
-static ldfunc deflabel;
-static FILE *ofp;
-static long first_seg;
-static int any_segs;
-static int passtwo;
-static int arrindex;
-
-#define GROUP_MAX 256                 /* we won't _realistically_ have more
-                                       * than this many segs in a group */
-#define EXT_BLKSIZ 256                /* block size for externals list */
-
-struct Segment;                               /* need to know these structs exist */
-struct Group;
-
-struct LineNumber {
-    struct LineNumber *next;
-    struct Segment *segment;
-    long offset;
-    long lineno;
-};
-
-static struct FileName {
-    struct FileName *next;
-    char *name;
-    struct LineNumber *lnhead, **lntail;
-    int index;
-} *fnhead, **fntail;
-
-static struct Array {
-    struct Array *next;
-    unsigned size;
-    int basetype;
-} *arrhead, **arrtail;
-
-#define ARRAYBOT 31 /* magic number  for first array index */
-
-
-static struct Public {
-    struct Public *next;
-    char *name;
-    long offset;
-    long segment;                     /* only if it's far-absolute */
-    int type;                          /* only for local debug syms */
-} *fpubhead, **fpubtail, *last_defined;
-
-static struct External {
-    struct External *next;
-    char *name;
-    long commonsize;
-    long commonelem;                  /* element size if FAR, else zero */
-    int index;                        /* OBJ-file external index */
-    enum {
-       DEFWRT_NONE,                   /* no unusual default-WRT */
-       DEFWRT_STRING,                 /* a string we don't yet understand */
-       DEFWRT_SEGMENT,                /* a segment */
-       DEFWRT_GROUP                   /* a group */
-    } defwrt_type;
-    union {
-       char *string;
-       struct Segment *seg;
-       struct Group *grp;
-    } defwrt_ptr;
-    struct External *next_dws;        /* next with DEFWRT_STRING */
-} *exthead, **exttail, *dws;
-
-static int externals;
-
-static struct ExtBack {
-    struct ExtBack *next;
-    struct External *exts[EXT_BLKSIZ];
-} *ebhead, **ebtail;
-
-static struct Segment {
-    struct Segment *next;
-    long index;                               /* the NASM segment id */
-    long obj_index;                   /* the OBJ-file segment index */
-    struct Group *grp;                /* the group it belongs to */
-    unsigned long currentpos;
-    long align;                               /* can be SEG_ABS + absolute addr */
-    enum {
-       CMB_PRIVATE = 0,
-       CMB_PUBLIC = 2,
-       CMB_STACK = 5,
-       CMB_COMMON = 6
-    } combine;
-    long use32;                               /* is this segment 32-bit? */
-    struct Public *pubhead, **pubtail, *lochead, **loctail;
-    char *name;
-    char *segclass, *overlay;         /* `class' is a C++ keyword :-) */
-    ObjRecord *orp;
-} *seghead, **segtail, *obj_seg_needs_update;
-
-static struct Group {
-    struct Group *next;
-    char *name;
-    long index;                               /* NASM segment id */
-    long obj_index;                   /* OBJ-file group index */
-    long nentries;                    /* number of elements... */
-    long nindices;                    /* ...and number of index elts... */
-    union {
-       long index;
-       char *name;
-    } segs[GROUP_MAX];                /* ...in this */
-} *grphead, **grptail, *obj_grp_needs_update;
-
-static struct ImpDef {
-    struct ImpDef *next;
-    char *extname;
-    char *libname;
-    unsigned int impindex;
-    char *impname;
-} *imphead, **imptail;
-
-static struct ExpDef {
-    struct ExpDef *next;
-    char *intname;
-    char *extname;
-    unsigned int ordinal;
-    int flags;
-} *exphead, **exptail;
-
-#define EXPDEF_FLAG_ORDINAL  0x80
-#define EXPDEF_FLAG_RESIDENT 0x40
-#define EXPDEF_FLAG_NODATA   0x20
-#define EXPDEF_MASK_PARMCNT  0x1F
-
-static long obj_entry_seg, obj_entry_ofs;
-
-struct ofmt of_obj;
-
-/* The current segment */
-static struct Segment *current_seg;
-
-static long obj_segment (char *, int, int *);
-static void obj_write_file(int debuginfo);
-static int obj_directive (char *, char *, int);
-
-static void obj_init (FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
-{
-    ofp = fp;
-    error = errfunc;
-    evaluate = eval;
-    deflabel = ldef;
-    first_seg = seg_alloc();
-    any_segs = FALSE;
-    fpubhead = NULL;
-    fpubtail = &fpubhead;
-    exthead = NULL;
-    exttail = &exthead;
-    imphead = NULL;
-    imptail = &imphead;
-    exphead = NULL;
-    exptail = &exphead;
-    dws = NULL;
-    externals = 0;
-    ebhead = NULL;
-    ebtail = &ebhead;
-    seghead = obj_seg_needs_update = NULL;
-    segtail = &seghead;
-    grphead = obj_grp_needs_update = NULL;
-    grptail = &grphead;
-    obj_entry_seg = NO_SEG;
-    obj_uppercase = FALSE;
-    obj_use32 = FALSE;
-    passtwo = 0;
-    current_seg = NULL;
-
-    of_obj.current_dfmt->init (&of_obj,NULL,fp,errfunc);
-}
-
-static int obj_set_info(enum geninfo type, char **val)
-{
-    (void) type;
-    (void) val;
-
-    return 0;
-}
-static void obj_cleanup (int debuginfo) 
-{
-    obj_write_file(debuginfo);
-    of_obj.current_dfmt->cleanup();
-    fclose (ofp);
-    while (seghead) {
-       struct Segment *segtmp = seghead;
-       seghead = seghead->next;
-       while (segtmp->pubhead) {
-           struct Public *pubtmp = segtmp->pubhead;
-           segtmp->pubhead = pubtmp->next;
-           nasm_free (pubtmp->name);
-           nasm_free (pubtmp);
-       }
-       nasm_free (segtmp->segclass);
-       nasm_free (segtmp->overlay);
-       nasm_free (segtmp);
-    }
-    while (fpubhead) {
-       struct Public *pubtmp = fpubhead;
-       fpubhead = fpubhead->next;
-       nasm_free (pubtmp->name);
-       nasm_free (pubtmp);
-    }
-    while (exthead) {
-       struct External *exttmp = exthead;
-       exthead = exthead->next;
-       nasm_free (exttmp);
-    }
-    while (imphead) {
-       struct ImpDef *imptmp = imphead;
-       imphead = imphead->next;
-       nasm_free (imptmp->extname);
-       nasm_free (imptmp->libname);
-       nasm_free (imptmp->impname);   /* nasm_free won't mind if it's NULL */
-       nasm_free (imptmp);
-    }
-    while (exphead) {
-       struct ExpDef *exptmp = exphead;
-       exphead = exphead->next;
-       nasm_free (exptmp->extname);
-       nasm_free (exptmp->intname);
-       nasm_free (exptmp);
-    }
-    while (ebhead) {
-       struct ExtBack *ebtmp = ebhead;
-       ebhead = ebhead->next;
-       nasm_free (ebtmp);
-    }
-    while (grphead) {
-       struct Group *grptmp = grphead;
-       grphead = grphead->next;
-       nasm_free (grptmp);
-    }
-}
-
-static void obj_ext_set_defwrt (struct External *ext, char *id) 
-{
-    struct Segment *seg;
-    struct Group *grp;
-
-    for (seg = seghead; seg; seg = seg->next)
-       if (!strcmp(seg->name, id)) {
-           ext->defwrt_type = DEFWRT_SEGMENT;
-           ext->defwrt_ptr.seg = seg;
-           nasm_free (id);
-           return;
-       }
-
-    for (grp = grphead; grp; grp = grp->next)
-       if (!strcmp(grp->name, id)) {
-           ext->defwrt_type = DEFWRT_GROUP;
-           ext->defwrt_ptr.grp = grp;
-           nasm_free (id);
-           return;
-       }
-
-    ext->defwrt_type = DEFWRT_STRING;
-    ext->defwrt_ptr.string = id;
-    ext->next_dws = dws;
-    dws = ext;
-}
-
-static void obj_deflabel (char *name, long segment,
-                         long offset, int is_global, char *special) 
-{
-    /*
-     * We have three cases:
-     *
-     * (i) `segment' is a segment-base. If so, set the name field
-     * for the segment or group structure it refers to, and then
-     * return.
-     *
-     * (ii) `segment' is one of our segments, or a SEG_ABS segment.
-     * Save the label position for later output of a PUBDEF record.
-     * (Or a MODPUB, if we work out how.)
-     *
-     * (iii) `segment' is not one of our segments. Save the label
-     * position for later output of an EXTDEF, and also store a
-     * back-reference so that we can map later references to this
-     * segment number to the external index.
-     */
-    struct External *ext;
-    struct ExtBack *eb;
-    struct Segment *seg;
-    int i;
-    int used_special = FALSE;         /* have we used the special text? */
-
-#if defined(DEBUG) && DEBUG>2
-fprintf(stderr, " obj_deflabel: %s, seg=%ld, off=%ld, is_global=%d, %s\n",
-      name, segment, offset, is_global, special);
-#endif
-
-    /*
-     * If it's a special-retry from pass two, discard it.
-     */
-    if (is_global == 3)
-       return;
-
-    /*
-     * First check for the double-period, signifying something
-     * unusual.
-     */
-    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
-       if (!strcmp(name, "..start")) {
-           obj_entry_seg = segment;
-           obj_entry_ofs = offset;
-           return;
-       }
-       error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
-    }
-
-    /*
-     * Case (i):
-     */
-    if (obj_seg_needs_update) {
-       obj_seg_needs_update->name = name;
-       return;
-    } else if (obj_grp_needs_update) {
-       obj_grp_needs_update->name = name;
-       return;
-    }
-    if (segment < SEG_ABS && segment != NO_SEG && segment % 2)
-       return;
-
-    if (segment >= SEG_ABS || segment == NO_SEG) {
-       /*
-        * SEG_ABS subcase of (ii).
-        */
-       if (is_global) {
-           struct Public *pub;
-
-           pub = *fpubtail = nasm_malloc(sizeof(*pub));
-           fpubtail = &pub->next;
-           pub->next = NULL;
-           pub->name = nasm_strdup(name);
-           pub->offset = offset;
-           pub->segment = (segment == NO_SEG ? 0 : segment & ~SEG_ABS);
-       }
-       if (special)
-           error(ERR_NONFATAL, "OBJ supports no special symbol features"
-                 " for this symbol type");
-       return;
-    }
-
-    /*
-     * If `any_segs' is still FALSE, we might need to define a
-     * default segment, if they're trying to declare a label in
-     * `first_seg'.
-     */
-    if (!any_segs && segment == first_seg) {
-       int tempint;                   /* ignored */
-       if (segment != obj_segment("__NASMDEFSEG", 2, &tempint))
-           error (ERR_PANIC, "strange segment conditions in OBJ driver");
-    }
-
-    for (seg = seghead; seg && is_global; seg = seg->next)
-       if (seg->index == segment) {
-           struct Public *loc = nasm_malloc (sizeof(*loc));
-           /*
-            * Case (ii). Maybe MODPUB someday?
-            */
-           *seg->pubtail = loc;
-           seg->pubtail = &loc->next;
-           loc->next = NULL;
-           loc->name = nasm_strdup(name);
-           loc->offset = offset;
-                  
-           if (special)
-               error(ERR_NONFATAL, "OBJ supports no special symbol features"
-                     " for this symbol type");
-           return;
-       }
-
-    /*
-     * Case (iii).
-     */
-    if (is_global) {
-        ext = *exttail = nasm_malloc(sizeof(*ext));
-        ext->next = NULL;
-        exttail = &ext->next;
-        ext->name = name;
-       /* Place by default all externs into the current segment */
-        ext->defwrt_type = DEFWRT_NONE;
-       if (current_seg) {
-           if (current_seg->grp) {
-               ext->defwrt_type = DEFWRT_GROUP;
-               ext->defwrt_ptr.grp = current_seg->grp;
-           } else {
-               ext->defwrt_type = DEFWRT_SEGMENT;
-               ext->defwrt_ptr.seg = current_seg;
-           }
-       }
-        if (is_global == 2) {
-           ext->commonsize = offset;
-           ext->commonelem = 1;               /* default FAR */
-        } else
-           ext->commonsize = 0;
-    }
-    else
-       return;
-
-    /*
-     * Now process the special text, if any, to find default-WRT
-     * specifications and common-variable element-size and near/far
-     * specifications.
-     */
-    while (special && *special) {
-       used_special = TRUE;
-
-       /*
-        * We might have a default-WRT specification.
-        */
-       if (!nasm_strnicmp(special, "wrt", 3)) {
-           char *p;
-           int len;
-           special += 3;
-           special += strspn(special, " \t");
-           p = nasm_strndup(special, len = strcspn(special, ":"));
-           obj_ext_set_defwrt (ext, p);
-           special += len;
-           if (*special && *special != ':')
-               error(ERR_NONFATAL, "`:' expected in special symbol"
-                     " text for `%s'", ext->name);
-           else if (*special == ':')
-               special++;
-       }
-
-       /*
-        * The NEAR or FAR keywords specify nearness or
-        * farness. FAR gives default element size 1.
-        */
-       if (!nasm_strnicmp(special, "far", 3)) {
-           if (ext->commonsize)
-               ext->commonelem = 1;
-           else
-               error(ERR_NONFATAL, "`%s': `far' keyword may only be applied"
-                     " to common variables\n", ext->name);
-           special += 3;
-           special += strspn(special, " \t");
-       } else if (!nasm_strnicmp(special, "near", 4)) {
-           if (ext->commonsize)
-               ext->commonelem = 0;
-           else
-               error(ERR_NONFATAL, "`%s': `far' keyword may only be applied"
-                     " to common variables\n", ext->name);
-           special += 4;
-           special += strspn(special, " \t");
-       }
-
-       /*
-        * If it's a common, and anything else remains on the line
-        * before a further colon, evaluate it as an expression and
-        * use that as the element size. Forward references aren't
-        * allowed.
-        */
-       if (*special == ':')
-           special++;
-       else if (*special) {
-           if (ext->commonsize) {
-               expr *e;
-               struct tokenval tokval;
-
-               stdscan_reset();
-               stdscan_bufptr = special;
-               tokval.t_type = TOKEN_INVALID;
-               e = evaluate(stdscan, NULL, &tokval, NULL, 1, error, NULL);
-               if (e) {
-                   if (!is_simple(e))
-                       error (ERR_NONFATAL, "cannot use relocatable"
-                              " expression as common-variable element size");
-                   else
-                       ext->commonelem = reloc_value(e);
-               }
-               special = stdscan_bufptr;
-           } else {
-               error (ERR_NONFATAL, "`%s': element-size specifications only"
-                      " apply to common variables", ext->name);
-               while (*special && *special != ':')
-                   special++;
-               if (*special == ':')
-                   special++;
-           }
-       }
-    }
-
-    i = segment/2;
-    eb = ebhead;
-    if (!eb) {
-       eb = *ebtail = nasm_malloc(sizeof(*eb));
-       eb->next = NULL;
-       ebtail = &eb->next;
-    }
-    while (i > EXT_BLKSIZ) {
-       if (eb && eb->next)
-           eb = eb->next;
-       else {
-           eb = *ebtail = nasm_malloc(sizeof(*eb));
-           eb->next = NULL;
-           ebtail = &eb->next;
-       }
-       i -= EXT_BLKSIZ;
-    }
-    eb->exts[i] = ext;
-    ext->index = ++externals;
-
-    if (special && !used_special)
-       error(ERR_NONFATAL, "OBJ supports no special symbol features"
-             " for this symbol type");
-}
-
-/* forward declaration */
-static void obj_write_fixup (ObjRecord *orp, int bytes,
-    int segrel, long seg, long wrt, struct Segment *segto);
-
-static void obj_out (long segto, void *data, unsigned long type,
-                    long segment, long wrt) 
-{
-    unsigned long size, realtype;
-    unsigned char *ucdata;
-    long ldata;
-    struct Segment *seg;
-    ObjRecord *orp;
-
-    /*
-     * handle absolute-assembly (structure definitions)
-     */
-    if (segto == NO_SEG) {
-       if ((type & OUT_TYPMASK) != OUT_RESERVE)
-           error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
-                  " space");
-       return;
-    }
-
-    /*
-     * If `any_segs' is still FALSE, we must define a default
-     * segment.
-     */
-    if (!any_segs) {
-       int tempint;                   /* ignored */
-       if (segto != obj_segment("__NASMDEFSEG", 2, &tempint))
-           error (ERR_PANIC, "strange segment conditions in OBJ driver");
-    }
-
-    /*
-     * Find the segment we are targetting.
-     */
-    for (seg = seghead; seg; seg = seg->next)
-       if (seg->index == segto)
-           break;
-    if (!seg)
-       error (ERR_PANIC, "code directed to nonexistent segment?");
-
-    orp = seg->orp;
-    orp->parm[0] = seg->currentpos;
-
-    size = type & OUT_SIZMASK;
-    realtype = type & OUT_TYPMASK;
-    if (realtype == OUT_RAWDATA) {
-       ucdata = data;
-       while (size > 0) {
-           unsigned int len;
-           orp = obj_check(seg->orp, 1);
-           len = RECORD_MAX - orp->used;
-           if (len > size)
-               len = size;
-           memcpy (orp->buf+orp->used, ucdata, len);
-           orp->committed = orp->used += len;
-           orp->parm[0] = seg->currentpos += len;
-           ucdata += len;
-           size -= len;
-       }
-    }
-    else if (realtype == OUT_ADDRESS || realtype == OUT_REL2ADR ||
-            realtype == OUT_REL4ADR) 
-    {
-       int rsize;
-
-       if (segment == NO_SEG && realtype != OUT_ADDRESS)
-           error(ERR_NONFATAL, "relative call to absolute address not"
-                 " supported by OBJ format");
-       if (segment >= SEG_ABS)
-           error(ERR_NONFATAL, "far-absolute relocations not supported"
-                 " by OBJ format");
-       ldata = *(long *)data;
-       if (realtype == OUT_REL2ADR) {
-           ldata += (size-2);
-           size = 2;
-       }
-       if (realtype == OUT_REL4ADR) {
-           ldata += (size-4);
-           size = 4;
-       }
-       if (size == 2)
-           orp = obj_word (orp, ldata);
-       else
-           orp = obj_dword (orp, ldata);
-       rsize = size;
-       if (segment < SEG_ABS && (segment != NO_SEG && segment % 2) &&
-           size == 4) {
-           /*
-            * This is a 4-byte segment-base relocation such as
-            * `MOV EAX,SEG foo'. OBJ format can't actually handle
-            * these, but if the constant term has the 16 low bits
-            * zero, we can just apply a 2-byte segment-base
-            * relocation to the low word instead.
-            */
-           rsize = 2;
-           if (ldata & 0xFFFF)
-               error(ERR_NONFATAL, "OBJ format cannot handle complex"
-                     " dword-size segment base references");
-       }
-       if (segment != NO_SEG)
-           obj_write_fixup (orp, rsize,
-                            (realtype == OUT_ADDRESS  ? 0x4000 : 0),
-                            segment, wrt, seg);
-       seg->currentpos += size;
-    } else if (realtype == OUT_RESERVE) {
-       if (orp->committed)
-           orp = obj_bump(orp);
-       seg->currentpos += size;
-    }
-    obj_commit(orp);
-}
-
-static void obj_write_fixup (ObjRecord *orp, int bytes,
-    int segrel, long seg, long wrt, struct Segment *segto)
-{
-    int locat, method;
-    int base;
-    long tidx, fidx;
-    struct Segment *s = NULL;
-    struct Group *g = NULL;
-    struct External *e = NULL;
-    ObjRecord *forp;
-
-    if (bytes == 1) {
-       error(ERR_NONFATAL, "`obj' output driver does not support"
-             " one-byte relocations");
-       return;
-    }
-
-    forp = orp->child;
-    if (forp == NULL) {
-       orp->child = forp = obj_new();
-       forp->up = &(orp->child);
-       /* We should choose between FIXUPP and FIXU32 record type */
-       /* If we're targeting a 32-bit segment, use a FIXU32 record */
-       if (segto->use32)
-           forp->type = FIXU32;
-       else
-           forp->type = FIXUPP;
-    }
-
-    if (seg % 2) {
-       base = TRUE;
-       locat = FIX_16_SELECTOR;
-       seg--;
-       if (bytes != 2)
-           error(ERR_PANIC, "OBJ: 4-byte segment base fixup got"
-                 " through sanity check");
-    }
-    else {
-       base = FALSE;
-       locat = (bytes == 2) ? FIX_16_OFFSET : FIX_32_OFFSET;
-       if (!segrel)
-           /*
-            * There is a bug in tlink that makes it process self relative
-            * fixups incorrectly if the x_size doesn't match the location
-            * size.
-            */
-           forp = obj_force(forp, bytes<<3);
-    }
-
-    forp = obj_rword (forp, locat | segrel | (orp->parm[0]-orp->parm[2]));
-
-    tidx = fidx = -1, method = 0;      /* placate optimisers */
-
-    /*
-     * See if we can find the segment ID in our segment list. If
-     * so, we have a T4 (LSEG) target.
-     */
-    for (s = seghead; s; s = s->next)
-       if (s->index == seg)
-           break;
-    if (s)
-       method = 4, tidx = s->obj_index;
-    else {
-       for (g = grphead; g; g = g->next)
-           if (g->index == seg)
-               break;
-       if (g)
-           method = 5, tidx = g->obj_index;
-       else {
-           long i = seg/2;
-           struct ExtBack *eb = ebhead;
-           while (i > EXT_BLKSIZ) {
-               if (eb)
-                   eb = eb->next;
-               else
-                   break;
-               i -= EXT_BLKSIZ;
-           }
-           if (eb)
-               method = 6, e = eb->exts[i], tidx = e->index;
-           else
-               error(ERR_PANIC,
-                     "unrecognised segment value in obj_write_fixup");
-       }
-    }
-
-    /*
-     * If no WRT given, assume the natural default, which is method
-     * F5 unless:
-     *
-     * - we are doing an OFFSET fixup for a grouped segment, in
-     *   which case we require F1 (group).
-     *
-     * - we are doing an OFFSET fixup for an external with a
-     *   default WRT, in which case we must honour the default WRT.
-     */
-    if (wrt == NO_SEG) {
-       if (!base && s && s->grp)
-           method |= 0x10, fidx = s->grp->obj_index;
-       else if (!base && e && e->defwrt_type != DEFWRT_NONE) {
-           if (e->defwrt_type == DEFWRT_SEGMENT)
-               method |= 0x00, fidx = e->defwrt_ptr.seg->obj_index;
-           else if (e->defwrt_type == DEFWRT_GROUP)
-               method |= 0x10, fidx = e->defwrt_ptr.grp->obj_index;
-           else {
-               error(ERR_NONFATAL, "default WRT specification for"
-                     " external `%s' unresolved", e->name);
-               method |= 0x50, fidx = -1; /* got to do _something_ */
-           }
-       } else
-           method |= 0x50, fidx = -1;
-    } else {
-       /*
-        * See if we can find the WRT-segment ID in our segment
-        * list. If so, we have a F0 (LSEG) frame.
-        */
-       for (s = seghead; s; s = s->next)
-           if (s->index == wrt-1)
-               break;
-       if (s)
-           method |= 0x00, fidx = s->obj_index;
-       else {
-           for (g = grphead; g; g = g->next)
-               if (g->index == wrt-1)
-                   break;
-           if (g)
-               method |= 0x10, fidx = g->obj_index;
-           else {
-               long i = wrt/2;
-               struct ExtBack *eb = ebhead;
-               while (i > EXT_BLKSIZ) {
-                   if (eb)
-                       eb = eb->next;
-                   else
-                       break;
-                   i -= EXT_BLKSIZ;
-               }
-               if (eb)
-                   method |= 0x20, fidx = eb->exts[i]->index;
-               else
-                   error(ERR_PANIC,
-                         "unrecognised WRT value in obj_write_fixup");
-           }
-       }
-    }
-
-    forp = obj_byte (forp, method);
-    if (fidx != -1)
-       forp = obj_index (forp, fidx);
-    forp = obj_index (forp, tidx);
-    obj_commit (forp);
-}
-
-static long obj_segment (char *name, int pass, int *bits) 
-{
-    /*
-     * We call the label manager here to define a name for the new
-     * segment, and when our _own_ label-definition stub gets
-     * called in return, it should register the new segment name
-     * using the pointer it gets passed. That way we save memory,
-     * by sponging off the label manager.
-     */
-#if defined(DEBUG) && DEBUG>=3
-fprintf(stderr," obj_segment: < %s >, pass=%d, *bits=%d\n",
-       name, pass, *bits);
-#endif     
-    if (!name) {
-       *bits = 16;
-       current_seg = NULL;
-       return first_seg;
-    } else {
-       struct Segment *seg;
-       struct Group *grp;
-       struct External **extp;
-       int obj_idx, i, attrs, rn_error;
-       char *p;
-
-       /*
-        * Look for segment attributes.
-        */
-       attrs = 0;
-       while (*name == '.')
-           name++;                    /* hack, but a documented one */
-       p = name;
-       while (*p && !isspace(*p))
-           p++;
-       if (*p) {
-           *p++ = '\0';
-           while (*p && isspace(*p))
-               *p++ = '\0';
-       }
-       while (*p) {
-           while (*p && !isspace(*p))
-               p++;
-           if (*p) {
-               *p++ = '\0';
-               while (*p && isspace(*p))
-                   *p++ = '\0';
-           }
-
-           attrs++;
-       }
-
-       obj_idx = 1;
-       for (seg = seghead; seg; seg = seg->next) {
-           obj_idx++;
-           if (!strcmp(seg->name, name)) {
-               if (attrs > 0 && pass == 1)
-                   error(ERR_WARNING, "segment attributes specified on"
-                         " redeclaration of segment: ignoring");
-               if (seg->use32)
-                   *bits = 32;
-               else
-                   *bits = 16;
-               current_seg = seg;
-               return seg->index;
-           }
-       }
-
-       *segtail = seg = nasm_malloc(sizeof(*seg));
-       seg->next = NULL;
-       segtail = &seg->next;
-       seg->index = (any_segs ? seg_alloc() : first_seg);
-       seg->obj_index = obj_idx;
-       seg->grp = NULL;
-       any_segs = TRUE;
-       seg->name = NULL;
-       seg->currentpos = 0;
-       seg->align = 1;                /* default */
-       seg->use32 = FALSE;            /* default */
-       seg->combine = CMB_PUBLIC;     /* default */
-       seg->segclass = seg->overlay = NULL;
-       seg->pubhead = NULL;
-       seg->pubtail = &seg->pubhead;
-       seg->lochead = NULL;
-       seg->loctail = &seg->lochead;
-       seg->orp = obj_new();
-       seg->orp->up = &(seg->orp);
-       seg->orp->ori = ori_ledata;
-       seg->orp->type = LEDATA;
-       seg->orp->parm[1] = obj_idx;
-
-       /*
-        * Process the segment attributes.
-        */
-       p = name;
-       while (attrs--) {
-           p += strlen(p);
-           while (!*p) p++;
-
-           /*
-            * `p' contains a segment attribute.
-            */
-           if (!nasm_stricmp(p, "private"))
-               seg->combine = CMB_PRIVATE;
-           else if (!nasm_stricmp(p, "public"))
-               seg->combine = CMB_PUBLIC;
-           else if (!nasm_stricmp(p, "common"))
-               seg->combine = CMB_COMMON;
-           else if (!nasm_stricmp(p, "stack"))
-               seg->combine = CMB_STACK;
-           else if (!nasm_stricmp(p, "use16"))
-               seg->use32 = FALSE;
-           else if (!nasm_stricmp(p, "use32"))
-               seg->use32 = TRUE;
-           else if (!nasm_stricmp(p, "flat")) {
-               /*
-                * This segment is an OS/2 FLAT segment. That means
-                * that its default group is group FLAT, even if
-                * the group FLAT does not explicitly _contain_ the
-                * segment.
-                * 
-                * When we see this, we must create the group
-                * `FLAT', containing no segments, if it does not
-                * already exist; then we must set the default
-                * group of this segment to be the FLAT group.
-                */
-               struct Group *grp;
-               for (grp = grphead; grp; grp = grp->next)
-                   if (!strcmp(grp->name, "FLAT"))
-                       break;
-               if (!grp) {
-                   obj_directive ("group", "FLAT", 1);
-                   for (grp = grphead; grp; grp = grp->next)
-                       if (!strcmp(grp->name, "FLAT"))
-                           break;
-                   if (!grp)
-                       error (ERR_PANIC, "failure to define FLAT?!");
-               }
-               seg->grp = grp;
-           } else if (!nasm_strnicmp(p, "class=", 6))
-               seg->segclass = nasm_strdup(p+6);
-           else if (!nasm_strnicmp(p, "overlay=", 8))
-               seg->overlay = nasm_strdup(p+8);
-           else if (!nasm_strnicmp(p, "align=", 6)) {
-               seg->align = readnum(p+6, &rn_error);
-               if (rn_error) {
-                   seg->align = 1;
-                   error (ERR_NONFATAL, "segment alignment should be"
-                          " numeric");
-               }
-               switch ((int) seg->align) {
-                 case 1:              /* BYTE */
-                 case 2:              /* WORD */
-                 case 4:              /* DWORD */
-                 case 16:             /* PARA */
-                 case 256:            /* PAGE */
-                 case 4096:           /* PharLap extension */
-                   break;
-                 case 8:
-                   error(ERR_WARNING, "OBJ format does not support alignment"
-                         " of 8: rounding up to 16");
-                   seg->align = 16;
-                   break;
-                 case 32:
-                 case 64:
-                 case 128:
-                   error(ERR_WARNING, "OBJ format does not support alignment"
-                         " of %d: rounding up to 256", seg->align);
-                   seg->align = 256;
-                   break;
-                 case 512:
-                 case 1024:
-                 case 2048:
-                   error(ERR_WARNING, "OBJ format does not support alignment"
-                         " of %d: rounding up to 4096", seg->align);
-                   seg->align = 4096;
-                   break;
-                 default:
-                   error(ERR_NONFATAL, "invalid alignment value %d",
-                         seg->align);
-                   seg->align = 1;
-                   break;
-               }
-           } else if (!nasm_strnicmp(p, "absolute=", 9)) {
-               seg->align = SEG_ABS + readnum(p+9, &rn_error);
-               if (rn_error)
-                   error (ERR_NONFATAL, "argument to `absolute' segment"
-                          " attribute should be numeric");
-           }
-       }
-
-        /* We need to know whenever we have at least one 32-bit segment */
-        obj_use32 |= seg->use32;
-
-       obj_seg_needs_update = seg;
-       if (seg->align >= SEG_ABS)
-           deflabel (name, NO_SEG, seg->align - SEG_ABS,
-                     NULL, FALSE, FALSE, &of_obj, error);
-       else
-           deflabel (name, seg->index+1, 0L,
-                     NULL, FALSE, FALSE, &of_obj, error);
-       obj_seg_needs_update = NULL;
-
-       /*
-        * See if this segment is defined in any groups.
-        */
-       for (grp = grphead; grp; grp = grp->next) {
-           for (i = grp->nindices; i < grp->nentries; i++) {
-               if (!strcmp(grp->segs[i].name, seg->name)) {
-                   nasm_free (grp->segs[i].name);
-                   grp->segs[i] = grp->segs[grp->nindices];
-                   grp->segs[grp->nindices++].index = seg->obj_index;
-                   if (seg->grp)
-                       error(ERR_WARNING, "segment `%s' is already part of"
-                             " a group: first one takes precedence",
-                             seg->name);
-                   else
-                       seg->grp = grp;
-               }
-           }
-       }
-
-       /*
-        * Walk through the list of externals with unresolved
-        * default-WRT clauses, and resolve any that point at this
-        * segment.
-        */
-       extp = &dws;
-       while (*extp) {
-           if ((*extp)->defwrt_type == DEFWRT_STRING &&
-               !strcmp((*extp)->defwrt_ptr.string, seg->name)) {
-               nasm_free((*extp)->defwrt_ptr.string);
-               (*extp)->defwrt_type = DEFWRT_SEGMENT;
-               (*extp)->defwrt_ptr.seg = seg;
-               *extp = (*extp)->next_dws;
-           } else
-               extp = &(*extp)->next_dws;
-       }
-
-       if (seg->use32)
-           *bits = 32;
-       else
-           *bits = 16;
-       current_seg = seg;
-       return seg->index;
-    }
-}
-
-static int obj_directive (char *directive, char *value, int pass) 
-{
-    if (!strcmp(directive, "group")) {
-       char *p, *q, *v;
-       if (pass == 1) {
-           struct Group *grp;
-           struct Segment *seg;
-           struct External **extp;
-           int obj_idx;
-
-           q = value;
-           while (*q == '.')
-               q++;                   /* hack, but a documented one */
-           v = q;
-           while (*q && !isspace(*q))
-               q++;
-           if (isspace(*q)) {
-               *q++ = '\0';
-               while (*q && isspace(*q))
-                   q++;
-           }
-           /*
-            * Here we used to sanity-check the group directive to
-            * ensure nobody tried to declare a group containing no
-            * segments. However, OS/2 does this as standard
-            * practice, so the sanity check has been removed.
-            *
-            * if (!*q) {
-            *     error(ERR_NONFATAL,"GROUP directive contains no segments");
-            *     return 1;
-            * }
-            */
-
-           obj_idx = 1;
-           for (grp = grphead; grp; grp = grp->next) {
-               obj_idx++;
-               if (!strcmp(grp->name, v)) {
-                   error(ERR_NONFATAL, "group `%s' defined twice", v);
-                   return 1;
-               }
-           }
-
-           *grptail = grp = nasm_malloc(sizeof(*grp));
-           grp->next = NULL;
-           grptail = &grp->next;
-           grp->index = seg_alloc();
-           grp->obj_index = obj_idx;
-           grp->nindices = grp->nentries = 0;
-           grp->name = NULL;
-
-           obj_grp_needs_update = grp;
-           deflabel (v, grp->index+1, 0L,
-                     NULL, FALSE, FALSE, &of_obj, error);
-           obj_grp_needs_update = NULL;
-
-           while (*q) {
-               p = q;
-               while (*q && !isspace(*q))
-                   q++;
-               if (isspace(*q)) {
-                   *q++ = '\0';
-                   while (*q && isspace(*q))
-                       q++;
-               }
-               /*
-                * Now p contains a segment name. Find it.
-                */
-               for (seg = seghead; seg; seg = seg->next)
-                   if (!strcmp(seg->name, p))
-                       break;
-               if (seg) {
-                   /*
-                    * We have a segment index. Shift a name entry
-                    * to the end of the array to make room.
-                    */
-                   grp->segs[grp->nentries++] = grp->segs[grp->nindices];
-                   grp->segs[grp->nindices++].index = seg->obj_index;
-                   if (seg->grp)
-                       error(ERR_WARNING, "segment `%s' is already part of"
-                             " a group: first one takes precedence",
-                             seg->name);
-                   else
-                       seg->grp = grp;
-               } else {
-                   /*
-                    * We have an as-yet undefined segment.
-                    * Remember its name, for later.
-                    */
-                   grp->segs[grp->nentries++].name = nasm_strdup(p);
-               }
-           }
-
-           /*
-            * Walk through the list of externals with unresolved
-            * default-WRT clauses, and resolve any that point at
-            * this group.
-            */
-           extp = &dws;
-           while (*extp) {
-               if ((*extp)->defwrt_type == DEFWRT_STRING &&
-                   !strcmp((*extp)->defwrt_ptr.string, grp->name)) {
-                   nasm_free((*extp)->defwrt_ptr.string);
-                   (*extp)->defwrt_type = DEFWRT_GROUP;
-                   (*extp)->defwrt_ptr.grp = grp;
-                   *extp = (*extp)->next_dws;
-           } else
-                   extp = &(*extp)->next_dws;
-           }
-       }
-       return 1;
-    }
-    if (!strcmp(directive, "uppercase")) {
-       obj_uppercase = TRUE;
-       return 1;
-    }
-    if (!strcmp(directive, "import")) {
-       char *q, *extname, *libname, *impname;
-
-       if (pass == 2)
-           return 1;                  /* ignore in pass two */
-       extname = q = value;
-       while (*q && !isspace(*q))
-           q++;
-       if (isspace(*q)) {
-           *q++ = '\0';
-           while (*q && isspace(*q))
-               q++;
-       }
-
-       libname = q;
-       while (*q && !isspace(*q))
-           q++;
-       if (isspace(*q)) {
-           *q++ = '\0';
-           while (*q && isspace(*q))
-               q++;
-       }
-
-       impname = q;
-
-       if (!*extname || !*libname)
-           error(ERR_NONFATAL, "`import' directive requires symbol name"
-                 " and library name");
-       else {
-           struct ImpDef *imp;
-           int err = FALSE;
-
-           imp = *imptail = nasm_malloc(sizeof(struct ImpDef));
-           imptail = &imp->next;
-           imp->next = NULL;
-           imp->extname = nasm_strdup(extname);
-           imp->libname = nasm_strdup(libname);
-           imp->impindex = readnum(impname, &err);
-           if (!*impname || err)
-               imp->impname = nasm_strdup(impname);
-           else
-               imp->impname = NULL;
-       }
-
-       return 1;
-    }
-    if (!strcmp(directive, "export")) {
-       char *q, *extname, *intname, *v;
-       struct ExpDef *export;
-       int flags = 0;
-       unsigned int ordinal = 0;
-
-       if (pass == 2)
-           return 1;                  /* ignore in pass two */
-       intname = q = value;
-       while (*q && !isspace(*q))
-           q++;
-       if (isspace(*q)) {
-           *q++ = '\0';
-           while (*q && isspace(*q))
-               q++;
-       }
-
-       extname = q;
-       while (*q && !isspace(*q))
-           q++;
-       if (isspace(*q)) {
-           *q++ = '\0';
-           while (*q && isspace(*q))
-               q++;
-       }
-
-       if (!*intname) {
-           error(ERR_NONFATAL, "`export' directive requires export name");
-           return 1;
-       }
-       if (!*extname) {
-           extname = intname;
-           intname = "";
-       }
-       while (*q) {
-           v = q;
-           while (*q && !isspace(*q))
-               q++;
-           if (isspace(*q)) {
-               *q++ = '\0';
-               while (*q && isspace(*q))
-                   q++;
-           }
-           if (!nasm_stricmp(v, "resident"))
-               flags |= EXPDEF_FLAG_RESIDENT;
-           else if (!nasm_stricmp(v, "nodata"))
-               flags |= EXPDEF_FLAG_NODATA;
-           else if (!nasm_strnicmp(v, "parm=", 5)) {
-               int err = FALSE;
-               flags |= EXPDEF_MASK_PARMCNT & readnum(v+5, &err);
-               if (err) {
-                   error(ERR_NONFATAL,
-                         "value `%s' for `parm' is non-numeric", v+5);
-                   return 1;
-               }
-           } else {
-               int err = FALSE;
-               ordinal = readnum(v, &err);
-               if (err) {
-                   error(ERR_NONFATAL, "unrecognised export qualifier `%s'",
-                         v);
-                   return 1;
-               }
-               flags |= EXPDEF_FLAG_ORDINAL;
-           }
-       }
-
-       export = *exptail = nasm_malloc(sizeof(struct ExpDef));
-       exptail = &export->next;
-       export->next = NULL;
-       export->extname = nasm_strdup(extname);
-       export->intname = nasm_strdup(intname);
-       export->ordinal = ordinal;
-       export->flags = flags;
-
-       return 1;
-    }
-    return 0;
-}
-
-static long obj_segbase (long segment) 
-{
-    struct Segment *seg;
-
-    /*
-     * Find the segment in our list.
-     */
-    for (seg = seghead; seg; seg = seg->next)
-       if (seg->index == segment-1)
-           break;
-
-    if (!seg) {
-       /*
-        * Might be an external with a default WRT.
-        */
-       long i = segment/2;
-       struct ExtBack *eb = ebhead;
-       struct External *e;
-
-       while (i > EXT_BLKSIZ) {
-           if (eb)
-               eb = eb->next;
-           else
-               break;
-           i -= EXT_BLKSIZ;
-       }
-       if (eb) {
-           e = eb->exts[i];
-           if (e->defwrt_type == DEFWRT_NONE)
-               return segment;        /* fine */
-           else if (e->defwrt_type == DEFWRT_SEGMENT)
-               return e->defwrt_ptr.seg->index+1;
-           else if (e->defwrt_type == DEFWRT_GROUP)
-               return e->defwrt_ptr.grp->index+1;
-           else
-               return NO_SEG;         /* can't tell what it is */
-       }
-
-       return segment;                /* not one of ours - leave it alone */
-    }
-
-    if (seg->align >= SEG_ABS)
-       return seg->align;             /* absolute segment */
-    if (seg->grp)
-       return seg->grp->index+1;      /* grouped segment */
-
-    return segment;                   /* no special treatment */
-}
-
-static void obj_filename (char *inname, char *outname, efunc error) 
-{
-    strcpy(obj_infile, inname);
-    standard_extension (inname, outname, ".obj", error);
-}
-
-static void obj_write_file (int debuginfo) 
-{
-    struct Segment *seg, *entry_seg_ptr = 0;
-    struct FileName *fn;
-    struct LineNumber *ln;
-    struct Group *grp;
-    struct Public *pub, *loc;
-    struct External *ext;
-    struct ImpDef *imp;
-    struct ExpDef *export;
-    static char boast[] = "The Netwide Assembler " NASM_VER;
-    int lname_idx;
-    ObjRecord *orp;
-
-    /*
-     * Write the THEADR module header.
-     */
-    orp = obj_new();
-    orp->type = THEADR;
-    obj_name (orp, obj_infile);
-    obj_emit2 (orp);
-
-    /*
-     * Write the NASM boast comment.
-     */
-    orp->type = COMENT;
-    obj_rword (orp, 0);   /* comment type zero */
-    obj_name (orp, boast);
-    obj_emit2 (orp);
-
-    orp->type = COMENT;
-    /*
-     * Write the IMPDEF records, if any.
-     */
-    for (imp = imphead; imp; imp = imp->next) {
-       obj_rword (orp, 0xA0);   /* comment class A0 */
-       obj_byte (orp, 1);   /* subfunction 1: IMPDEF */
-       if (imp->impname)
-           obj_byte (orp, 0);   /* import by name */
-       else
-           obj_byte (orp, 1);   /* import by ordinal */
-       obj_name (orp, imp->extname);
-       obj_name (orp, imp->libname);
-       if (imp->impname)
-           obj_name (orp, imp->impname);
-       else
-           obj_word (orp, imp->impindex);
-       obj_emit2 (orp);
-    }
-
-    /*
-     * Write the EXPDEF records, if any.
-     */
-    for (export = exphead; export; export = export->next) {
-       obj_rword (orp, 0xA0);   /* comment class A0 */
-       obj_byte (orp, 2);   /* subfunction 2: EXPDEF */
-       obj_byte (orp, export->flags);
-       obj_name (orp, export->extname);
-       obj_name (orp, export->intname);
-       if (export->flags & EXPDEF_FLAG_ORDINAL)
-           obj_word (orp, export->ordinal);
-       obj_emit2 (orp);
-    }
-
-    /* we're using extended OMF if we put in debug info*/
-    if (debuginfo) {
-      orp->type = COMENT;
-      obj_byte (orp, 0x40);
-      obj_byte (orp, dEXTENDED);
-      obj_emit2 (orp);
-    }
-
-    /*
-     * Write the first LNAMES record, containing LNAME one, which
-     * is null. Also initialise the LNAME counter.
-     */
-    orp->type = LNAMES;
-    obj_byte (orp, 0);
-    lname_idx = 1;
-    /*
-     * Write some LNAMES for the segment names
-     */
-    for (seg = seghead; seg; seg = seg->next) {
-       orp = obj_name (orp, seg->name);
-       if (seg->segclass)
-           orp = obj_name (orp, seg->segclass);
-       if (seg->overlay)
-           orp = obj_name (orp, seg->overlay);
-       obj_commit (orp);
-    }
-    /*
-     * Write some LNAMES for the group names
-     */
-    for (grp = grphead; grp; grp = grp->next) {
-       orp = obj_name (orp, grp->name);
-       obj_commit (orp);
-    }
-    obj_emit (orp);
-
-
-    /*
-     * Write the SEGDEF records.
-     */
-    orp->type = SEGDEF;
-    for (seg = seghead; seg; seg = seg->next) {
-       int acbp;
-       unsigned long seglen = seg->currentpos;
-
-       acbp = (seg->combine << 2);    /* C field */
-
-       if (seg->use32)
-           acbp |= 0x01;              /* P bit is Use32 flag */
-       else if (seglen == 0x10000L) {
-           seglen = 0;                /* This special case may be needed for old linkers */
-           acbp |= 0x02;              /* B bit */
-       }
-
-
-       /* A field */
-       if (seg->align >= SEG_ABS)
-           /* acbp |= 0x00 */;
-       else if (seg->align >= 4096) {
-           if (seg->align > 4096)
-               error(ERR_NONFATAL, "segment `%s' requires more alignment"
-                     " than OBJ format supports", seg->name);
-           acbp |= 0xC0;              /* PharLap extension */
-       } else if (seg->align >= 256) {
-           acbp |= 0x80;
-       } else if (seg->align >= 16) {
-           acbp |= 0x60;
-       } else if (seg->align >= 4) {
-           acbp |= 0xA0;
-       } else if (seg->align >= 2) {
-           acbp |= 0x40;
-       } else
-           acbp |= 0x20;
-
-       obj_byte (orp, acbp);
-       if (seg->align & SEG_ABS) {
-           obj_x (orp, seg->align - SEG_ABS);  /* Frame */
-           obj_byte (orp, 0);  /* Offset */
-       }
-       obj_x (orp, seglen);
-       obj_index (orp, ++lname_idx);
-       obj_index (orp, seg->segclass ? ++lname_idx : 1);
-       obj_index (orp, seg->overlay ? ++lname_idx : 1);
-       obj_emit2 (orp);
-    }
-
-    /*
-     * Write the GRPDEF records.
-     */
-    orp->type = GRPDEF;
-    for (grp = grphead; grp; grp = grp->next) {
-       int i;
-
-       if (grp->nindices != grp->nentries) {
-           for (i = grp->nindices; i < grp->nentries; i++) {
-               error(ERR_NONFATAL, "group `%s' contains undefined segment"
-                     " `%s'", grp->name, grp->segs[i].name);
-               nasm_free (grp->segs[i].name);
-               grp->segs[i].name = NULL;
-           }
-       }
-       obj_index (orp, ++lname_idx);
-       for (i = 0; i < grp->nindices; i++) {
-           obj_byte (orp, 0xFF);
-           obj_index (orp, grp->segs[i].index);
-       }
-       obj_emit2 (orp);
-    }
-
-    /*
-     * Write the PUBDEF records: first the ones in the segments,
-     * then the far-absolutes.
-     */
-    orp->type = PUBDEF;
-    orp->ori = ori_pubdef;
-    for (seg = seghead; seg; seg = seg->next) {
-       orp->parm[0] = seg->grp ? seg->grp->obj_index : 0;
-       orp->parm[1] = seg->obj_index;
-       for (pub = seg->pubhead; pub; pub = pub->next) {
-           orp = obj_name (orp, pub->name);
-           orp = obj_x (orp, pub->offset);
-           orp = obj_byte (orp, 0);  /* type index */
-           obj_commit (orp);
-       }
-       obj_emit (orp);
-    }
-    orp->parm[0] = 0;
-    orp->parm[1] = 0;
-    for (pub = fpubhead; pub; pub = pub->next) {   /* pub-crawl :-) */
-       if (orp->parm[2] != pub->segment) {
-           obj_emit (orp);
-           orp->parm[2] = pub->segment;
-       }
-       orp = obj_name (orp, pub->name);
-       orp = obj_x (orp, pub->offset);
-       orp = obj_byte (orp, 0);  /* type index */
-       obj_commit (orp);
-    }
-    obj_emit (orp);
-
-    /*
-     * Write the EXTDEF and COMDEF records, in order.
-     */
-    orp->ori = ori_null;
-    for (ext = exthead; ext; ext = ext->next) {
-       if (ext->commonsize == 0) {
-           if (orp->type != EXTDEF) {
-               obj_emit (orp);
-               orp->type = EXTDEF;
-           }
-           orp = obj_name (orp, ext->name);
-           orp = obj_index (orp, 0);
-       } else {
-           if (orp->type != COMDEF) {
-               obj_emit (orp);
-               orp->type = COMDEF;
-           }
-           orp = obj_name (orp, ext->name);
-           orp = obj_index (orp, 0);
-           if (ext->commonelem) {
-               orp = obj_byte (orp, 0x61);/* far communal */
-               orp = obj_value (orp, (ext->commonsize / ext->commonelem));
-               orp = obj_value (orp, ext->commonelem);
-           } else {
-               orp = obj_byte (orp, 0x62);/* near communal */
-               orp = obj_value (orp, ext->commonsize);
-           }
-       }
-       obj_commit (orp);
-    }
-    obj_emit (orp);
-
-    /*
-     * Write a COMENT record stating that the linker's first pass
-     * may stop processing at this point. Exception is if our
-     * MODEND record specifies a start point, in which case,
-     * according to some variants of the documentation, this COMENT
-     * should be omitted. So we'll omit it just in case.
-     * But, TASM puts it in all the time so if we are using
-     * TASM debug stuff we are putting it in
-     */
-    if (debuginfo || obj_entry_seg == NO_SEG) {
-       orp->type = COMENT;
-        obj_byte (orp, 0x40);
-        obj_byte (orp, dLINKPASS);
-       obj_byte (orp, 1);
-       obj_emit2 (orp);
-    } 
-
-    /*
-     * 1) put out the compiler type
-     * 2) Put out the type info.  The only type we are using is near label #19
-     */
-    if (debuginfo) {
-      int i;
-      struct Array *arrtmp = arrhead;
-      orp->type = COMENT;
-      obj_byte (orp, 0x40);
-      obj_byte (orp, dCOMPDEF);
-      obj_byte (orp, 4);
-      obj_byte (orp, 0);
-      obj_emit2 (orp);
-
-      obj_byte (orp, 0x40);
-      obj_byte (orp, dTYPEDEF);
-      obj_word (orp, 0x18); /* type # for linking */
-      obj_word (orp, 6);    /* size of type */
-      obj_byte (orp, 0x2a); /* absolute type for debugging */
-      obj_emit2 (orp);
-      obj_byte (orp, 0x40);
-      obj_byte (orp, dTYPEDEF);
-      obj_word (orp, 0x19); /* type # for linking */
-      obj_word (orp, 0);    /* size of type */
-      obj_byte (orp, 0x24); /* absolute type for debugging */
-      obj_byte (orp, 0);    /* near/far specifier */
-      obj_emit2 (orp);
-      obj_byte (orp, 0x40);
-      obj_byte (orp, dTYPEDEF);
-      obj_word (orp, 0x1A); /* type # for linking */
-      obj_word (orp, 0);    /* size of type */
-      obj_byte (orp, 0x24); /* absolute type for debugging */
-      obj_byte (orp, 1);    /* near/far specifier */
-      obj_emit2 (orp);
-      obj_byte (orp, 0x40);
-      obj_byte (orp, dTYPEDEF);
-      obj_word (orp, 0x1b); /* type # for linking */
-      obj_word (orp, 0);    /* size of type */
-      obj_byte (orp, 0x23); /* absolute type for debugging */
-      obj_byte (orp, 0);
-      obj_byte (orp, 0);
-      obj_byte (orp, 0);
-      obj_emit2 (orp);
-      obj_byte (orp, 0x40);
-      obj_byte (orp, dTYPEDEF);
-      obj_word (orp, 0x1c); /* type # for linking */
-      obj_word (orp, 0);    /* size of type */
-      obj_byte (orp, 0x23); /* absolute type for debugging */
-      obj_byte (orp, 0);
-      obj_byte (orp, 4);
-      obj_byte (orp, 0);
-      obj_emit2 (orp);
-      obj_byte (orp, 0x40);
-      obj_byte (orp, dTYPEDEF);
-      obj_word (orp, 0x1d); /* type # for linking */
-      obj_word (orp, 0);    /* size of type */
-      obj_byte (orp, 0x23); /* absolute type for debugging */
-      obj_byte (orp, 0);
-      obj_byte (orp, 1);
-      obj_byte (orp, 0);
-      obj_emit2 (orp);
-      obj_byte (orp, 0x40);
-      obj_byte (orp, dTYPEDEF);
-      obj_word (orp, 0x1e); /* type # for linking */
-      obj_word (orp, 0);    /* size of type */
-      obj_byte (orp, 0x23); /* absolute type for debugging */
-      obj_byte (orp, 0);
-      obj_byte (orp, 5);
-      obj_byte (orp, 0);
-      obj_emit2 (orp);
-
-      /* put out the array types */
-      for (i= ARRAYBOT; i < arrindex; i++) {
-        obj_byte (orp, 0x40);
-       obj_byte (orp, dTYPEDEF);
-       obj_word (orp, i ); /* type # for linking */
-       obj_word (orp, arrtmp->size);    /* size of type */
-       obj_byte (orp, 0x1A); /* absolute type for debugging (array)*/
-       obj_byte (orp, arrtmp->basetype ); /* base type */
-       obj_emit2 (orp);
-        arrtmp = arrtmp->next ;
-      }
-    }
-    /*
-     * write out line number info with a LINNUM record
-     * switch records when we switch segments, and output the
-     * file in a pseudo-TASM fashion.  The record switch is naive; that
-     * is that one file may have many records for the same segment
-     * if there are lots of segment switches
-     */
-    if (fnhead && debuginfo) {
-       seg = fnhead->lnhead->segment;
-
-       for (fn = fnhead; fn; fn = fn->next) {
-           /* write out current file name */
-            orp->type = COMENT;
-            orp->ori = ori_null;
-           obj_byte (orp, 0x40);
-           obj_byte (orp, dFILNAME);
-            obj_byte( orp,0);
-            obj_name( orp,fn->name);
-            obj_dword(orp, 0);
-           obj_emit2 (orp);
-
-           /* write out line numbers this file */
-
-            orp->type = LINNUM;
-            orp->ori = ori_linnum;
-           for (ln = fn->lnhead; ln; ln = ln->next) {
-               if (seg != ln->segment) {
-                   /* if we get here have to flush the buffer and start
-                     * a new record for a new segment
-                    */
-                   seg = ln->segment;
-                   obj_emit ( orp );
-               }
-               orp->parm[0] = seg->grp ? seg->grp->obj_index : 0;
-               orp->parm[1] = seg->obj_index;
-               orp = obj_word(orp, ln->lineno);
-                orp = obj_x(orp, ln->offset);
-               obj_commit (orp);
-           }
-           obj_emit (orp);
-       }
-    }
-    /*
-     * we are going to locate the entry point segment now
-     * rather than wait until the MODEND record, because,
-     * then we can output a special symbol to tell where the
-     * entry point is.
-     *
-     */
-    if (obj_entry_seg != NO_SEG) {
-       for (seg = seghead; seg; seg = seg->next) {
-           if (seg->index == obj_entry_seg) {
-                entry_seg_ptr = seg;
-               break;
-           }
-       }
-       if (!seg)
-           error(ERR_NONFATAL, "entry point is not in this module");
-    }
-
-    /*
-     * get ready to put out symbol records
-     */
-    orp->type = COMENT;
-    orp->ori = ori_local;
-   
-    /*
-     * put out a symbol for the entry point
-     * no dots in this symbol, because, borland does
-     * not (officially) support dots in label names
-     * and I don't know what various versions of TLINK will do
-     */
-    if (debuginfo && obj_entry_seg != NO_SEG) {
-        orp = obj_name (orp,"start_of_program");
-       orp = obj_word (orp,0x19);  /* type: near label */
-       orp = obj_index (orp, seg->grp ? seg->grp->obj_index : 0);
-       orp = obj_index (orp, seg->obj_index);
-       orp = obj_x (orp, obj_entry_ofs);
-       obj_commit (orp);
-    } 
-    /*
-     * put out the local labels
-     */
-    for (seg = seghead; seg && debuginfo; seg = seg->next) {
-        /* labels this seg */
-        for (loc = seg->lochead; loc; loc = loc->next) {
-            orp = obj_name (orp,loc->name);
-           orp = obj_word (orp, loc->type);
-           orp = obj_index (orp, seg->grp ? seg->grp->obj_index : 0);
-           orp = obj_index (orp, seg->obj_index);
-           orp = obj_x (orp,loc->offset);
-           obj_commit (orp);
-        }
-    }
-    if (orp->used)
-        obj_emit (orp);
-
-    /*
-     * Write the LEDATA/FIXUPP pairs.
-     */
-    for (seg = seghead; seg; seg = seg->next) {
-       obj_emit (seg->orp);
-       nasm_free (seg->orp);
-    }
-
-    /*
-     * Write the MODEND module end marker.
-     */
-    orp->type = obj_use32 ? MODE32 : MODEND;
-    orp->ori = ori_null;
-    if (entry_seg_ptr) {
-       orp->type = entry_seg_ptr->use32 ? MODE32 : MODEND;
-       obj_byte (orp, 0xC1);
-       seg = entry_seg_ptr;
-       if (seg->grp) {
-           obj_byte (orp, 0x10);
-           obj_index (orp, seg->grp->obj_index);
-       } else {
-           /*
-            * the below changed to prevent TLINK crashing.
-            * Previous more efficient version read:
-            *
-            *  obj_byte (orp, 0x50);
-            */
-           obj_byte (orp, 0x00);
-           obj_index (orp, seg->obj_index);
-       }
-       obj_index (orp, seg->obj_index);
-       obj_x (orp, obj_entry_ofs);
-    } else
-       obj_byte (orp, 0);
-    obj_emit2 (orp);
-    nasm_free (orp);
-}
-
-void obj_fwrite(ObjRecord *orp) 
-{
-    unsigned int cksum, len;
-    unsigned char *ptr;
-
-    cksum = orp->type;
-    if (orp->x_size == 32)
-       cksum |= 1;
-    fputc (cksum, ofp);
-    len = orp->committed+1;
-    cksum += (len & 0xFF) + ((len>>8) & 0xFF);
-    fwriteshort (len, ofp);
-    fwrite (orp->buf, 1, len-1, ofp);
-    for (ptr=orp->buf; --len; ptr++)
-       cksum += *ptr;
-    fputc ( (-cksum) & 0xFF, ofp);
-}
-
-static char *obj_stdmac[] = {
-    "%define __SECT__ [section .text]",
-    "%imacro group 1+.nolist",
-    "[group %1]",
-    "%endmacro",
-    "%imacro uppercase 0+.nolist",
-    "[uppercase %1]",
-    "%endmacro",
-    "%imacro export 1+.nolist",
-    "[export %1]",
-    "%endmacro",
-    "%imacro import 1+.nolist",
-    "[import %1]",
-    "%endmacro",
-    "%macro __NASM_CDecl__ 1",
-    "%endmacro",
-    NULL
-};
-
-void dbgbi_init(struct ofmt * of, void * id, FILE * fp, efunc error)
-{
-    (void) of;
-    (void) id;
-    (void) fp;
-    (void) error;
-
-    fnhead = NULL;
-    fntail = &fnhead;
-    arrindex = ARRAYBOT ;
-    arrhead = NULL;
-    arrtail = &arrhead;
-}
-static void dbgbi_cleanup(void)
-{
-    struct Segment *segtmp;
-    while (fnhead) {
-       struct FileName *fntemp = fnhead;
-       while (fnhead->lnhead) {
-           struct LineNumber *lntemp = fnhead->lnhead;
-           fnhead->lnhead = lntemp->next;
-           nasm_free( lntemp);
-       }
-       fnhead = fnhead->next;
-       nasm_free (fntemp->name);
-       nasm_free (fntemp);
-    }
-    for (segtmp=seghead; segtmp; segtmp=segtmp->next) {
-       while (segtmp->lochead) {
-           struct Public *loctmp = segtmp->lochead;
-           segtmp->lochead = loctmp->next;
-           nasm_free (loctmp->name);
-           nasm_free (loctmp);
-       }
-    }
-    while (arrhead) {
-       struct Array *arrtmp = arrhead;
-        arrhead = arrhead->next;
-        nasm_free (arrtmp);
-    }
-}
-
-static void dbgbi_linnum (const char *lnfname, long lineno, long segto)
-{
-    struct FileName *fn;
-    struct LineNumber *ln;
-    struct Segment *seg;
-
-    if (segto == NO_SEG)
-       return;
-
-    /*
-     * If `any_segs' is still FALSE, we must define a default
-     * segment.
-     */
-    if (!any_segs) {
-       int tempint;                   /* ignored */
-       if (segto != obj_segment("__NASMDEFSEG", 2, &tempint))
-           error (ERR_PANIC, "strange segment conditions in OBJ driver");
-    }
-
-    /*
-     * Find the segment we are targetting.
-     */
-    for (seg = seghead; seg; seg = seg->next)
-       if (seg->index == segto)
-           break;
-    if (!seg)
-       error (ERR_PANIC, "lineno directed to nonexistent segment?");
-
-/*    for (fn = fnhead; fn; fn = fnhead->next) */
-    for (fn = fnhead; fn; fn = fn->next) /* fbk - Austin Lunnen - John Fine*/
-       if (!nasm_stricmp(lnfname,fn->name))
-           break;
-    if (!fn) {
-       fn = nasm_malloc ( sizeof( *fn));
-       fn->name = nasm_malloc ( strlen(lnfname) + 1) ;
-        strcpy (fn->name,lnfname);
-       fn->lnhead = NULL;
-       fn->lntail = & fn->lnhead;
-       fn->next = NULL;
-       *fntail = fn;
-       fntail = &fn->next;
-    }
-    ln = nasm_malloc ( sizeof( *ln));
-    ln->segment = seg;
-    ln->offset = seg->currentpos;
-    ln->lineno = lineno;
-    ln->next = NULL;
-    *fn->lntail = ln;
-    fn->lntail = &ln->next;
-
-}
-static void dbgbi_deflabel (char *name, long segment,
-                         long offset, int is_global, char *special) 
-{
-    struct Segment *seg;
-
-    (void) special;
-
-    /*
-     * If it's a special-retry from pass two, discard it.
-     */
-    if (is_global == 3)
-       return;
-
-    /*
-     * First check for the double-period, signifying something
-     * unusual.
-     */
-    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
-       return;
-    }
-
-    /*
-     * Case (i):
-     */
-    if (obj_seg_needs_update) {
-       return;
-    } else if (obj_grp_needs_update) {
-       return;
-    }
-    if (segment < SEG_ABS && segment != NO_SEG && segment % 2)
-       return;
-
-    if (segment >= SEG_ABS || segment == NO_SEG) {
-       return;
-    }
-
-    /*
-     * If `any_segs' is still FALSE, we might need to define a
-     * default segment, if they're trying to declare a label in
-     * `first_seg'.  But the label should exist due to a prior
-     * call to obj_deflabel so we can skip that.
-     */
-
-    for (seg = seghead; seg; seg = seg->next)
-       if (seg->index == segment) {
-           struct Public *loc = nasm_malloc (sizeof(*loc));
-           /*
-            * Case (ii). Maybe MODPUB someday?
-            */
-           last_defined = *seg->loctail = loc;
-           seg->loctail = &loc->next;
-           loc->next = NULL;
-           loc->name = nasm_strdup(name);
-           loc->offset = offset;
-       }
-}
-static void dbgbi_typevalue (long type)
-{
-    int vsize;
-    int elem = TYM_ELEMENTS(type);
-    type = TYM_TYPE(type);
-
-    if (!last_defined)
-       return;
-
-    switch (type) {
-       case TY_BYTE:
-           last_defined->type = 8; /* unsigned char */
-           vsize = 1;
-           break;
-       case TY_WORD:
-           last_defined->type = 10; /* unsigned word */
-           vsize = 2;
-           break;
-       case TY_DWORD:
-           last_defined->type = 12; /* unsigned dword */
-           vsize = 4;
-           break;
-       case TY_FLOAT:
-           last_defined->type = 14; /* float */
-           vsize = 4;
-           break;
-       case TY_QWORD:
-           last_defined->type = 15; /* qword */
-           vsize = 8;
-           break;
-       case TY_TBYTE:
-           last_defined->type = 16; /* TBYTE */
-           vsize = 10;
-           break;
-       default:
-           last_defined->type = 0x19; /*label */
-           vsize = 0;
-           break;
-    }
-                
-    if (elem > 1) {
-        struct Array *arrtmp = nasm_malloc (sizeof(*arrtmp));
-        int vtype = last_defined->type;
-        arrtmp->size = vsize * elem;
-        arrtmp->basetype = vtype;
-        arrtmp->next = NULL;
-        last_defined->type = arrindex++;
-        *arrtail = arrtmp;
-        arrtail = & (arrtmp->next);
-    }
-    last_defined = NULL;
-}
-static void dbgbi_output (int output_type, void *param)
-{
-    (void) output_type;
-    (void) param;
-}
-static struct dfmt borland_debug_form = {
-    "Borland Debug Records",
-    "borland",
-    dbgbi_init,
-    dbgbi_linnum,
-    dbgbi_deflabel,
-    null_debug_routine,
-    dbgbi_typevalue,
-    dbgbi_output,
-    dbgbi_cleanup,
-};
-
-static struct dfmt *borland_debug_arr[3] = {
-       &borland_debug_form,
-       &null_debug_form,
-       NULL
-};
-
-struct ofmt of_obj = {
-    "MS-DOS 16-bit/32-bit OMF object files",
-    "obj",
-    NULL,
-    borland_debug_arr,
-    &null_debug_form,
-    obj_stdmac,
-    obj_init,
-    obj_set_info,
-    obj_out,
-    obj_deflabel,
-    obj_segment,
-    obj_segbase,
-    obj_directive,
-    obj_filename,
-    obj_cleanup
-};
-#endif /* OF_OBJ */
diff --git a/output/outaout.c b/output/outaout.c
new file mode 100644 (file)
index 0000000..b8e74be
--- /dev/null
@@ -0,0 +1,933 @@
+/* outaout.c   output routines for the Netwide Assembler to produce
+ *             Linux a.out object files
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "nasm.h"
+#include "nasmlib.h"
+#include "outform.h"
+
+#if defined OF_AOUT || defined OF_AOUTB
+
+#define RELTYPE_ABSOLUTE 0x00
+#define RELTYPE_RELATIVE 0x01
+#define RELTYPE_GOTPC    0x01   /* no explicit GOTPC in a.out */
+#define RELTYPE_GOTOFF   0x10
+#define RELTYPE_GOT      0x10   /* distinct from GOTOFF bcos sym not sect */
+#define RELTYPE_PLT      0x21
+#define RELTYPE_SYMFLAG  0x08
+
+struct Reloc {
+    struct Reloc *next;
+    long address;                     /* relative to _start_ of section */
+    long symbol;                      /* symbol number or -ve section id */
+    int bytes;                        /* 2 or 4 */
+    int reltype;                      /* see above */
+};
+
+struct Symbol {
+    long strpos;                      /* string table position of name */
+    int type;                         /* symbol type - see flags below */
+    long value;                               /* address, or COMMON variable size */
+    long size;                        /* size for data or function exports */
+    long segment;                     /* back-reference used by gsym_reloc */
+    struct Symbol *next;              /* list of globals in each section */
+    struct Symbol *nextfwd;           /* list of unresolved-size symbols */
+    char *name;                               /* for unresolved-size symbols */
+    long symnum;                      /* index into symbol table */
+};
+
+/*
+ * Section IDs - used in Reloc.symbol when negative, and in
+ * Symbol.type when positive.
+ */
+#define SECT_ABS 2                    /* absolute value */
+#define SECT_TEXT 4                   /* text section */
+#define SECT_DATA 6                   /* data section */
+#define SECT_BSS 8                    /* bss section */
+#define SECT_MASK 0xE                 /* mask out any of the above */
+
+/*
+ * More flags used in Symbol.type.
+ */
+#define SYM_GLOBAL 1                  /* it's a global symbol */
+#define SYM_DATA 0x100                /* used for shared libs */
+#define SYM_FUNCTION 0x200            /* used for shared libs */
+#define SYM_WITH_SIZE 0x4000          /* not output; internal only */
+
+/*
+ * Bit more explanation of symbol types: SECT_xxx denotes a local
+ * symbol. SECT_xxx|SYM_GLOBAL denotes a global symbol, defined in
+ * this module. Just SYM_GLOBAL, with zero value, denotes an
+ * external symbol referenced in this module. And just SYM_GLOBAL,
+ * but with a non-zero value, declares a C `common' variable, of
+ * size `value'.
+ */
+
+struct Section {
+    struct SAA *data;
+    unsigned long len, size, nrelocs;
+    long index;
+    struct Reloc *head, **tail;
+    struct Symbol *gsyms, *asym;
+};
+
+static struct Section stext, sdata, sbss;
+
+static struct SAA *syms;
+static unsigned long nsyms;
+
+static struct RAA *bsym;
+
+static struct SAA *strs;
+static unsigned long strslen;
+
+static struct Symbol *fwds;
+
+static FILE *aoutfp;
+static efunc error;
+static evalfunc evaluate;
+
+static int bsd;
+static int is_pic;
+
+static void aout_write(void);
+static void aout_write_relocs(struct Reloc *);
+static void aout_write_syms(void);
+static void aout_sect_write(struct Section *, unsigned char *, unsigned long);
+static void aout_pad_sections(void);
+static void aout_fixup_relocs(struct Section *);
+
+/*
+ * Special section numbers which are used to define special
+ * symbols, which can be used with WRT to provide PIC relocation
+ * types.
+ */
+static long aout_gotpc_sect, aout_gotoff_sect;
+static long aout_got_sect, aout_plt_sect;
+static long aout_sym_sect;
+
+static void aoutg_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
+{
+    aoutfp = fp;
+    error = errfunc;
+    evaluate = eval;
+    (void) ldef;                      /* placate optimisers */
+    stext.data = saa_init(1L); stext.head = NULL; stext.tail = &stext.head;
+    sdata.data = saa_init(1L); sdata.head = NULL; sdata.tail = &sdata.head;
+    stext.len = stext.size = sdata.len = sdata.size = sbss.len = 0;
+    stext.nrelocs = sdata.nrelocs = 0;
+    stext.gsyms = sdata.gsyms = sbss.gsyms = NULL;
+    stext.index = seg_alloc();
+    sdata.index = seg_alloc();
+    sbss.index = seg_alloc();
+    stext.asym = sdata.asym = sbss.asym = NULL;
+    syms = saa_init((long)sizeof(struct Symbol));
+    nsyms = 0;
+    bsym = raa_init();
+    strs = saa_init(1L);
+    strslen = 0;
+    fwds = NULL;
+}
+
+#ifdef OF_AOUT
+
+static void aout_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
+{
+    bsd = FALSE;
+    aoutg_init (fp, errfunc, ldef, eval);
+
+    aout_gotpc_sect = aout_gotoff_sect = aout_got_sect =
+       aout_plt_sect = aout_sym_sect = NO_SEG;
+}
+
+#endif
+
+#ifdef OF_AOUTB
+
+extern struct ofmt of_aoutb;
+
+static void aoutb_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
+{
+    bsd = TRUE;
+    aoutg_init (fp, errfunc, ldef, eval);
+
+    is_pic = 0x00;                    /* may become 0x40 */
+
+    aout_gotpc_sect = seg_alloc();
+    ldef("..gotpc", aout_gotpc_sect+1, 0L, NULL, FALSE,FALSE,&of_aoutb,error);
+    aout_gotoff_sect = seg_alloc();
+    ldef("..gotoff", aout_gotoff_sect+1, 0L,NULL,FALSE,FALSE,&of_aoutb,error);
+    aout_got_sect = seg_alloc();
+    ldef("..got", aout_got_sect+1, 0L, NULL, FALSE,FALSE,&of_aoutb,error);
+    aout_plt_sect = seg_alloc();
+    ldef("..plt", aout_plt_sect+1, 0L, NULL, FALSE,FALSE,&of_aoutb,error);
+    aout_sym_sect = seg_alloc();
+    ldef("..sym", aout_sym_sect+1, 0L, NULL, FALSE,FALSE,&of_aoutb,error);
+}
+
+#endif
+
+static void aout_cleanup(int debuginfo) 
+{
+    struct Reloc *r;
+
+    (void) debuginfo;
+
+    aout_pad_sections();
+    aout_fixup_relocs(&stext);
+    aout_fixup_relocs(&sdata);
+    aout_write();
+    fclose (aoutfp);
+    saa_free (stext.data);
+    while (stext.head) {
+       r = stext.head;
+       stext.head = stext.head->next;
+       nasm_free (r);
+    }
+    saa_free (sdata.data);
+    while (sdata.head) {
+       r = sdata.head;
+       sdata.head = sdata.head->next;
+       nasm_free (r);
+    }
+    saa_free (syms);
+    raa_free (bsym);
+    saa_free (strs);
+}
+
+static long aout_section_names (char *name, int pass, int *bits) 
+{
+    /*
+     * Default to 32 bits.
+     */
+    if (!name)
+       *bits = 32;
+
+    if (!name)
+       return stext.index;
+
+    if (!strcmp(name, ".text"))
+       return stext.index;
+    else if (!strcmp(name, ".data"))
+       return sdata.index;
+    else if (!strcmp(name, ".bss"))
+       return sbss.index;
+    else
+       return NO_SEG;
+}
+
+static void aout_deflabel (char *name, long segment, long offset,
+                          int is_global, char *special) 
+{
+    int pos = strslen+4;
+    struct Symbol *sym;
+    int special_used = FALSE;
+
+    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
+       /*
+        * This is a NASM special symbol. We never allow it into
+        * the a.out symbol table, even if it's a valid one. If it
+        * _isn't_ a valid one, we should barf immediately.
+        */
+       if (strcmp(name, "..gotpc") && strcmp(name, "..gotoff") &&
+           strcmp(name, "..got") && strcmp(name, "..plt") &&
+           strcmp(name, "..sym"))
+           error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
+       return;
+    }
+
+    if (is_global == 3) {
+       struct Symbol **s;
+       /*
+        * Fix up a forward-reference symbol size from the first
+        * pass.
+        */
+       for (s = &fwds; *s; s = &(*s)->nextfwd)
+           if (!strcmp((*s)->name, name)) {
+               struct tokenval tokval;
+               expr *e;
+               char *p = special;
+
+               while (*p && !isspace(*p)) p++;
+               while (*p && isspace(*p)) p++;
+               stdscan_reset();
+               stdscan_bufptr = p;
+               tokval.t_type = TOKEN_INVALID;
+               e = evaluate(stdscan, NULL, &tokval, NULL, 1, error, NULL);
+               if (e) {
+                   if (!is_simple(e))
+                       error (ERR_NONFATAL, "cannot use relocatable"
+                              " expression as symbol size");
+                   else
+                       (*s)->size = reloc_value(e);
+               }
+
+               /*
+                * Remove it from the list of unresolved sizes.
+                */
+               nasm_free ((*s)->name);
+               *s = (*s)->nextfwd;
+               return;
+           }
+       return;                        /* it wasn't an important one */
+    }
+
+    saa_wbytes (strs, name, (long)(1+strlen(name)));
+    strslen += 1+strlen(name);
+
+    sym = saa_wstruct (syms);
+
+    sym->strpos = pos;
+    sym->type = is_global ? SYM_GLOBAL : 0;
+    sym->segment = segment;
+    if (segment == NO_SEG)
+       sym->type |= SECT_ABS;
+    else if (segment == stext.index) {
+       sym->type |= SECT_TEXT;
+       if (is_global) {
+           sym->next = stext.gsyms;
+           stext.gsyms = sym;
+       } else if (!stext.asym)
+           stext.asym = sym;
+    } else if (segment == sdata.index) {
+       sym->type |= SECT_DATA;
+       if (is_global) {
+           sym->next = sdata.gsyms;
+           sdata.gsyms = sym;
+       } else if (!sdata.asym)
+           sdata.asym = sym;
+    } else if (segment == sbss.index) {
+       sym->type |= SECT_BSS;
+       if (is_global) {
+           sym->next = sbss.gsyms;
+           sbss.gsyms = sym;
+       } else if (!sbss.asym)
+           sbss.asym = sym;
+    } else
+       sym->type = SYM_GLOBAL;
+    if (is_global == 2)
+       sym->value = offset;
+    else
+       sym->value = (sym->type == SYM_GLOBAL ? 0 : offset);
+
+    if (is_global && sym->type != SYM_GLOBAL) {
+       /*
+        * Global symbol exported _from_ this module. We must check
+        * the special text for type information.
+        */
+
+       if (special) {
+           int n = strcspn(special, " ");
+
+           if (!nasm_strnicmp(special, "function", n))
+               sym->type |= SYM_FUNCTION;
+           else if (!nasm_strnicmp(special, "data", n) ||
+                    !nasm_strnicmp(special, "object", n))
+               sym->type |= SYM_DATA;
+           else
+               error(ERR_NONFATAL, "unrecognised symbol type `%.*s'",
+                     n, special);
+           if (special[n]) {
+               struct tokenval tokval;
+               expr *e;
+               int fwd = FALSE;
+               char *saveme=stdscan_bufptr;  /* bugfix? fbk 8/10/00 */
+
+               if (!bsd) {
+                   error(ERR_NONFATAL, "Linux a.out does not support"
+                         " symbol size information");
+               } else {
+                   while (special[n] && isspace(special[n]))
+                       n++;
+                   /*
+                    * We have a size expression; attempt to
+                    * evaluate it.
+                    */
+                   sym->type |= SYM_WITH_SIZE;
+                   stdscan_reset();
+                   stdscan_bufptr = special+n;
+                   tokval.t_type = TOKEN_INVALID;
+                   e = evaluate(stdscan, NULL, &tokval, &fwd, 0, error, NULL);
+                   if (fwd) {
+                       sym->nextfwd = fwds;
+                       fwds = sym;
+                       sym->name = nasm_strdup(name);
+                   } else if (e) {
+                       if (!is_simple(e))
+                           error (ERR_NONFATAL, "cannot use relocatable"
+                                  " expression as symbol size");
+                       else
+                           sym->size = reloc_value(e);
+                   }
+               }
+               stdscan_bufptr=saveme;     /* bugfix? fbk 8/10/00 */
+           }
+           special_used = TRUE;
+       }
+    }
+
+    /*
+     * define the references from external-symbol segment numbers
+     * to these symbol records.
+     */
+    if (segment != NO_SEG && segment != stext.index &&
+       segment != sdata.index && segment != sbss.index)
+       bsym = raa_write (bsym, segment, nsyms);
+    sym->symnum = nsyms;
+
+    nsyms++;
+    if (sym->type & SYM_WITH_SIZE)
+       nsyms++;                       /* and another for the size */
+
+    if (special && !special_used)
+       error(ERR_NONFATAL, "no special symbol features supported here");
+}
+
+static void aout_add_reloc (struct Section *sect, long segment,
+                           int reltype, int bytes) 
+{
+    struct Reloc *r;
+
+    r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
+    sect->tail = &r->next;
+    r->next = NULL;
+
+    r->address = sect->len;
+    r->symbol = (segment == NO_SEG ? -SECT_ABS :
+                segment == stext.index ? -SECT_TEXT :
+                segment == sdata.index ? -SECT_DATA :
+                segment == sbss.index ? -SECT_BSS :
+                raa_read(bsym, segment));
+    r->reltype = reltype;
+    if (r->symbol >= 0)
+       r->reltype |= RELTYPE_SYMFLAG;
+    r->bytes = bytes;
+
+    sect->nrelocs++;
+}
+
+/*
+ * This routine deals with ..got and ..sym relocations: the more
+ * complicated kinds. In shared-library writing, some relocations
+ * with respect to global symbols must refer to the precise symbol
+ * rather than referring to an offset from the base of the section
+ * _containing_ the symbol. Such relocations call to this routine,
+ * which searches the symbol list for the symbol in question.
+ *
+ * RELTYPE_GOT references require the _exact_ symbol address to be
+ * used; RELTYPE_ABSOLUTE references can be at an offset from the
+ * symbol. The boolean argument `exact' tells us this.
+ *
+ * Return value is the adjusted value of `addr', having become an
+ * offset from the symbol rather than the section. Should always be
+ * zero when returning from an exact call.
+ *
+ * Limitation: if you define two symbols at the same place,
+ * confusion will occur.
+ *
+ * Inefficiency: we search, currently, using a linked list which
+ * isn't even necessarily sorted.
+ */
+static long aout_add_gsym_reloc (struct Section *sect,
+                                long segment, long offset,
+                                int type, int bytes, int exact) 
+{
+    struct Symbol *sym, *sm, *shead;
+    struct Reloc *r;
+
+    /*
+     * First look up the segment to find whether it's text, data,
+     * bss or an external symbol.
+     */
+    shead = NULL;
+    if (segment == stext.index)
+       shead = stext.gsyms;
+    else if (segment == sdata.index)
+       shead = sdata.gsyms;
+    else if (segment == sbss.index)
+       shead = sbss.gsyms;
+    if (!shead) {
+       if (exact && offset != 0)
+           error (ERR_NONFATAL, "unable to find a suitable global symbol"
+                  " for this reference");
+       else
+           aout_add_reloc (sect, segment, type, bytes);
+       return offset;
+    }
+
+    if (exact) {
+       /*
+        * Find a symbol pointing _exactly_ at this one.
+        */
+       for (sym = shead; sym; sym = sym->next)
+           if (sym->value == offset)
+               break;
+    } else {
+       /*
+        * Find the nearest symbol below this one.
+        */
+       sym = NULL;
+       for (sm = shead; sm; sm = sm->next)
+           if (sm->value <= offset && (!sym || sm->value > sym->value))
+               sym = sm;
+    }
+    if (!sym && exact) {
+       error (ERR_NONFATAL, "unable to find a suitable global symbol"
+              " for this reference");
+       return 0;
+    }
+
+    r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
+    sect->tail = &r->next;
+    r->next = NULL;
+
+    r->address = sect->len;
+    r->symbol = sym->symnum;
+    r->reltype = type | RELTYPE_SYMFLAG;
+    r->bytes = bytes;
+
+    sect->nrelocs++;
+
+    return offset - sym->value;
+}
+
+/*
+ * This routine deals with ..gotoff relocations. These _must_ refer
+ * to a symbol, due to a perversity of *BSD's PIC implementation,
+ * and it must be a non-global one as well; so we store `asym', the
+ * first nonglobal symbol defined in each section, and always work
+ * from that. Relocation type is always RELTYPE_GOTOFF.
+ *
+ * Return value is the adjusted value of `addr', having become an
+ * offset from the `asym' symbol rather than the section.
+ */
+static long aout_add_gotoff_reloc (struct Section *sect, long segment,
+                                  long offset, int bytes) 
+{
+    struct Reloc *r;
+    struct Symbol *asym;
+
+    /*
+     * First look up the segment to find whether it's text, data,
+     * bss or an external symbol.
+     */
+    asym = NULL;
+    if (segment == stext.index)
+       asym = stext.asym;
+    else if (segment == sdata.index)
+       asym = sdata.asym;
+    else if (segment == sbss.index)
+       asym = sbss.asym;
+    if (!asym)
+       error (ERR_NONFATAL, "`..gotoff' relocations require a non-global"
+              " symbol in the section");
+
+    r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
+    sect->tail = &r->next;
+    r->next = NULL;
+
+    r->address = sect->len;
+    r->symbol = asym->symnum;
+    r->reltype = RELTYPE_GOTOFF;
+    r->bytes = bytes;
+
+    sect->nrelocs++;
+
+    return offset - asym->value;
+}
+
+static void aout_out (long segto, void *data, unsigned long type,
+                     long segment, long wrt) 
+{
+    struct Section *s;
+    long realbytes = type & OUT_SIZMASK;
+    long addr;
+    unsigned char mydata[4], *p;
+
+    type &= OUT_TYPMASK;
+
+    /*
+     * handle absolute-assembly (structure definitions)
+     */
+    if (segto == NO_SEG) {
+       if (type != OUT_RESERVE)
+           error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
+                  " space");
+       return;
+    }
+
+    if (segto == stext.index)
+       s = &stext;
+    else if (segto == sdata.index)
+       s = &sdata;
+    else if (segto == sbss.index)
+       s = NULL;
+    else {
+       error(ERR_WARNING, "attempt to assemble code in"
+             " segment %d: defaulting to `.text'", segto);
+       s = &stext;
+    }
+
+    if (!s && type != OUT_RESERVE) {
+       error(ERR_WARNING, "attempt to initialise memory in the"
+             " BSS section: ignored");
+       if (type == OUT_REL2ADR)
+           realbytes = 2;
+       else if (type == OUT_REL4ADR)
+           realbytes = 4;
+       sbss.len += realbytes;
+       return;
+    }
+
+    if (type == OUT_RESERVE) {
+       if (s) {
+           error(ERR_WARNING, "uninitialised space declared in"
+                 " %s section: zeroing",
+                 (segto == stext.index ? "code" : "data"));
+           aout_sect_write (s, NULL, realbytes);
+       } else
+           sbss.len += realbytes;
+    } else if (type == OUT_RAWDATA) {
+       if (segment != NO_SEG)
+           error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
+       aout_sect_write (s, data, realbytes);
+    } else if (type == OUT_ADDRESS) {
+       addr = *(long *)data;
+       if (segment != NO_SEG) {
+           if (segment % 2) {
+               error(ERR_NONFATAL, "a.out format does not support"
+                     " segment base references");
+           } else {
+               if (wrt == NO_SEG) {
+                   aout_add_reloc (s, segment, RELTYPE_ABSOLUTE, realbytes);
+               } else if (!bsd) {
+                   error (ERR_NONFATAL, "Linux a.out format does not support"
+                          " any use of WRT");
+                   wrt = NO_SEG;      /* we can at least _try_ to continue */
+               } else if (wrt == aout_gotpc_sect+1) {
+                   is_pic = 0x40;
+                   aout_add_reloc (s, segment, RELTYPE_GOTPC, realbytes);
+               } else if (wrt == aout_gotoff_sect+1) {
+                   is_pic = 0x40;
+                   addr = aout_add_gotoff_reloc (s, segment,
+                                                 addr, realbytes);
+               } else if (wrt == aout_got_sect+1) {
+                   is_pic = 0x40;
+                   addr = aout_add_gsym_reloc (s, segment, addr, RELTYPE_GOT,
+                                               realbytes, TRUE);
+               } else if (wrt == aout_sym_sect+1) {
+                   addr = aout_add_gsym_reloc (s, segment, addr,
+                                               RELTYPE_ABSOLUTE, realbytes,
+                                               FALSE);
+               } else if (wrt == aout_plt_sect+1) {
+                   is_pic = 0x40;
+                   error(ERR_NONFATAL, "a.out format cannot produce non-PC-"
+                         "relative PLT references");
+               } else {
+                   error (ERR_NONFATAL, "a.out format does not support this"
+                          " use of WRT");
+                   wrt = NO_SEG;      /* we can at least _try_ to continue */
+               }
+           }
+       }
+       p = mydata;
+       if (realbytes == 2)
+           WRITESHORT (p, addr);
+       else
+           WRITELONG (p, addr);
+       aout_sect_write (s, mydata, realbytes);
+    } else if (type == OUT_REL2ADR) {
+       if (segment == segto)
+           error(ERR_PANIC, "intra-segment OUT_REL2ADR");
+       if (segment != NO_SEG && segment % 2) {
+           error(ERR_NONFATAL, "a.out format does not support"
+                 " segment base references");
+       } else {
+           if (wrt == NO_SEG) {
+               aout_add_reloc (s, segment, RELTYPE_RELATIVE, 2);
+           } else if (!bsd) {
+               error (ERR_NONFATAL, "Linux a.out format does not support"
+                      " any use of WRT");
+               wrt = NO_SEG;      /* we can at least _try_ to continue */
+           } else if (wrt == aout_plt_sect+1) {
+               is_pic = 0x40;
+               aout_add_reloc (s, segment, RELTYPE_PLT, 2);
+           } else if (wrt == aout_gotpc_sect+1 ||
+                      wrt == aout_gotoff_sect+1 ||
+                      wrt == aout_got_sect+1) {
+               error(ERR_NONFATAL, "a.out format cannot produce PC-"
+                     "relative GOT references");
+           } else {
+               error (ERR_NONFATAL, "a.out format does not support this"
+                      " use of WRT");
+               wrt = NO_SEG;      /* we can at least _try_ to continue */
+           }
+       }
+       p = mydata;
+       WRITESHORT (p, *(long*)data-(realbytes + s->len));
+       aout_sect_write (s, mydata, 2L);
+    } else if (type == OUT_REL4ADR) {
+       if (segment == segto)
+           error(ERR_PANIC, "intra-segment OUT_REL4ADR");
+       if (segment != NO_SEG && segment % 2) {
+           error(ERR_NONFATAL, "a.out format does not support"
+                 " segment base references");
+       } else {
+           if (wrt == NO_SEG) {
+               aout_add_reloc (s, segment, RELTYPE_RELATIVE, 4);
+           } else if (!bsd) {
+               error (ERR_NONFATAL, "Linux a.out format does not support"
+                      " any use of WRT");
+               wrt = NO_SEG;      /* we can at least _try_ to continue */
+           } else if (wrt == aout_plt_sect+1) {
+               is_pic = 0x40;
+               aout_add_reloc (s, segment, RELTYPE_PLT, 4);
+           } else if (wrt == aout_gotpc_sect+1 ||
+                      wrt == aout_gotoff_sect+1 ||
+                      wrt == aout_got_sect+1) {
+               error(ERR_NONFATAL, "a.out format cannot produce PC-"
+                     "relative GOT references");
+           } else {
+               error (ERR_NONFATAL, "a.out format does not support this"
+                      " use of WRT");
+               wrt = NO_SEG;      /* we can at least _try_ to continue */
+           }
+       }
+       p = mydata;
+       WRITELONG (p, *(long*)data-(realbytes + s->len));
+       aout_sect_write (s, mydata, 4L);
+    }
+}
+
+static void aout_pad_sections(void) 
+{
+    static unsigned char pad[] = { 0x90, 0x90, 0x90, 0x90 };
+    /*
+     * Pad each of the text and data sections with NOPs until their
+     * length is a multiple of four. (NOP == 0x90.) Also increase
+     * the length of the BSS section similarly.
+     */
+    aout_sect_write (&stext, pad, (-(long)stext.len) & 3);
+    aout_sect_write (&sdata, pad, (-(long)sdata.len) & 3);
+    sbss.len = (sbss.len + 3) & ~3;
+}
+
+/*
+ * a.out files have the curious property that all references to
+ * things in the data or bss sections are done by addresses which
+ * are actually relative to the start of the _text_ section, in the
+ * _file_. (No relation to what happens after linking. No idea why
+ * this should be so. It's very strange.) So we have to go through
+ * the relocation table, _after_ the final size of each section is
+ * known, and fix up the relocations pointed to.
+ */
+static void aout_fixup_relocs(struct Section *sect) 
+{
+    struct Reloc *r;
+
+    saa_rewind (sect->data);
+    for (r = sect->head; r; r = r->next) {
+       unsigned char *p, *q, blk[4];
+       long l;
+
+       saa_fread (sect->data, r->address, blk, (long)r->bytes);
+       p = q = blk;
+       l = *p++;
+       if (r->bytes > 1) {
+           l += ((long)*p++) << 8;
+           if (r->bytes == 4) {
+               l += ((long)*p++) << 16;
+               l += ((long)*p++) << 24;
+           }
+       }
+       if (r->symbol == -SECT_DATA)
+           l += stext.len;
+       else if (r->symbol == -SECT_BSS)
+           l += stext.len + sdata.len;
+       if (r->bytes == 4)
+           WRITELONG(q, l);
+       else if (r->bytes == 2)
+           WRITESHORT(q, l);
+       else
+           *q++ = l & 0xFF;
+       saa_fwrite (sect->data, r->address, blk, (long)r->bytes);
+    }
+}
+
+static void aout_write(void) 
+{
+    /*
+     * Emit the a.out header.
+     */
+    /* OMAGIC, M_386 or MID_I386, no flags */
+    fwritelong (bsd ? 0x07018600 | is_pic : 0x640107L, aoutfp);
+    fwritelong (stext.len, aoutfp);
+    fwritelong (sdata.len, aoutfp);
+    fwritelong (sbss.len, aoutfp);
+    fwritelong (nsyms * 12, aoutfp);   /* length of symbol table */
+    fwritelong (0L, aoutfp);          /* object files have no entry point */
+    fwritelong (stext.nrelocs * 8, aoutfp);   /* size of text relocs */
+    fwritelong (sdata.nrelocs * 8, aoutfp);   /* size of data relocs */
+
+    /*
+     * Write out the code section and the data section.
+     */
+    saa_fpwrite (stext.data, aoutfp);
+    saa_fpwrite (sdata.data, aoutfp);
+
+    /*
+     * Write out the relocations.
+     */
+    aout_write_relocs (stext.head);
+    aout_write_relocs (sdata.head);
+
+    /*
+     * Write the symbol table.
+     */
+    aout_write_syms ();
+
+    /*
+     * And the string table.
+     */
+    fwritelong (strslen+4, aoutfp);    /* length includes length count */
+    saa_fpwrite (strs, aoutfp);
+}
+
+static void aout_write_relocs (struct Reloc *r) 
+{
+    while (r) {
+       unsigned long word2;
+
+       fwritelong (r->address, aoutfp);
+
+       if (r->symbol >= 0)
+           word2 = r->symbol;
+       else
+           word2 = -r->symbol;
+       word2 |= r->reltype << 24;
+       word2 |= (r->bytes == 1 ? 0 :
+                 r->bytes == 2 ? 0x2000000L : 0x4000000L);
+       fwritelong (word2, aoutfp);
+
+       r = r->next;
+    }
+}
+
+static void aout_write_syms (void) 
+{
+    unsigned long i;
+
+    saa_rewind (syms);
+    for (i = 0; i < nsyms; i++) {
+       struct Symbol *sym = saa_rstruct(syms);
+       fwritelong (sym->strpos, aoutfp);
+       fwritelong ((long)sym->type & ~SYM_WITH_SIZE, aoutfp);
+       /*
+        * Fix up the symbol value now we know the final section
+        * sizes.
+        */
+       if ((sym->type & SECT_MASK) == SECT_DATA)
+           sym->value += stext.len;
+       if ((sym->type & SECT_MASK) == SECT_BSS)
+           sym->value += stext.len + sdata.len;
+       fwritelong (sym->value, aoutfp);
+       /*
+        * Output a size record if necessary.
+        */
+       if (sym->type & SYM_WITH_SIZE) {
+           fwritelong(sym->strpos, aoutfp);
+           fwritelong(0x0DL, aoutfp);  /* special value: means size */
+           fwritelong(sym->size, aoutfp);
+           i++;                       /* use up another of `nsyms' */
+       }
+    }
+}
+
+static void aout_sect_write (struct Section *sect,
+                            unsigned char *data, unsigned long len) 
+{
+    saa_wbytes (sect->data, data, len);
+    sect->len += len;
+}
+
+static long aout_segbase (long segment) 
+{
+    return segment;
+}
+
+static int aout_directive (char *directive, char *value, int pass) 
+{
+    return 0;
+}
+
+static void aout_filename (char *inname, char *outname, efunc error) 
+{
+    standard_extension (inname, outname, ".o", error);
+}
+
+static char *aout_stdmac[] = {
+    "%define __SECT__ [section .text]",
+    "%macro __NASM_CDecl__ 1",
+    "%endmacro",
+    NULL
+};
+
+static int aout_set_info(enum geninfo type, char **val)
+{
+    return 0;
+}
+#endif /* OF_AOUT || OF_AOUTB */
+
+#ifdef OF_AOUT
+
+struct ofmt of_aout = {
+    "Linux a.out object files",
+    "aout",
+    NULL,
+    null_debug_arr,
+    &null_debug_form,
+    aout_stdmac,
+    aout_init,
+    aout_set_info,
+    aout_out,
+    aout_deflabel,
+    aout_section_names,
+    aout_segbase,
+    aout_directive,
+    aout_filename,
+    aout_cleanup
+};
+
+#endif
+
+#ifdef OF_AOUTB
+
+struct ofmt of_aoutb = {
+    "NetBSD/FreeBSD a.out object files",
+    "aoutb",
+    NULL,
+    null_debug_arr,
+    &null_debug_form,
+    aout_stdmac,
+    aoutb_init,
+    aout_set_info,
+    aout_out,
+    aout_deflabel,
+    aout_section_names,
+    aout_segbase,
+    aout_directive,
+    aout_filename,
+    aout_cleanup
+};
+
+#endif
diff --git a/output/outas86.c b/output/outas86.c
new file mode 100644 (file)
index 0000000..8c69567
--- /dev/null
@@ -0,0 +1,589 @@
+/* outas86.c   output routines for the Netwide Assembler to produce
+ *             Linux as86 (bin86-0.3) object files
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "nasm.h"
+#include "nasmlib.h"
+#include "outform.h"
+
+#ifdef OF_AS86
+
+struct Piece {
+    struct Piece *next;
+    int type;                         /* 0 = absolute, 1 = seg, 2 = sym */
+    long offset;                      /* relative offset */
+    int number;                               /* symbol/segment number (4=bss) */
+    long bytes;                               /* size of reloc or of absolute data */
+    int relative;                     /* TRUE or FALSE */
+};
+
+struct Symbol {
+    long strpos;                      /* string table position of name */
+    int flags;                        /* symbol flags */
+    int segment;                      /* 4=bss at this point */
+    long value;                               /* address, or COMMON variable size */
+};
+
+/*
+ * Section IDs - used in Piece.number and Symbol.segment.
+ */
+#define SECT_TEXT 0                   /* text section */
+#define SECT_DATA 3                   /* data section */
+#define SECT_BSS 4                    /* bss section */
+
+/*
+ * Flags used in Symbol.flags.
+ */
+#define SYM_ENTRY (1<<8)
+#define SYM_EXPORT (1<<7)
+#define SYM_IMPORT (1<<6)
+#define SYM_ABSOLUTE (1<<4)
+
+struct Section {
+    struct SAA *data;
+    unsigned long datalen, size, len;
+    long index;
+    struct Piece *head, *last, **tail;
+};
+
+static char as86_module[FILENAME_MAX];
+
+static struct Section stext, sdata;
+static unsigned long bsslen;
+static long bssindex;
+
+static struct SAA *syms;
+static unsigned long nsyms;
+
+static struct RAA *bsym;
+
+static struct SAA *strs;
+static unsigned long strslen;
+
+static int as86_reloc_size;
+
+static FILE *as86fp;
+static efunc error;
+
+static void as86_write(void);
+static void as86_write_section (struct Section *, int);
+static int as86_add_string (char *name);
+static void as86_sect_write(struct Section *, unsigned char *, unsigned long);
+
+static void as86_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
+{
+    as86fp = fp;
+    error = errfunc;
+    (void) ldef;                      /* placate optimisers */
+    stext.data = saa_init(1L); stext.datalen = 0L;
+    stext.head = stext.last = NULL;
+    stext.tail = &stext.head;
+    sdata.data = saa_init(1L); sdata.datalen = 0L;
+    sdata.head = sdata.last = NULL;
+    sdata.tail = &sdata.head;
+    bsslen =
+       stext.len = stext.datalen = stext.size =
+       sdata.len = sdata.datalen = sdata.size = 0;
+    stext.index = seg_alloc();
+    sdata.index = seg_alloc();
+    bssindex = seg_alloc();
+    syms = saa_init((long)sizeof(struct Symbol));
+    nsyms = 0;
+    bsym = raa_init();
+    strs = saa_init(1L);
+    strslen = 0;
+
+    as86_add_string (as86_module);
+}
+
+static void as86_cleanup(int debuginfo) 
+{
+    struct Piece *p;
+
+    (void) debuginfo;
+
+    as86_write();
+    fclose (as86fp);
+    saa_free (stext.data);
+    while (stext.head) {
+       p = stext.head;
+       stext.head = stext.head->next;
+       nasm_free (p);
+    }
+    saa_free (sdata.data);
+    while (sdata.head) {
+       p = sdata.head;
+       sdata.head = sdata.head->next;
+       nasm_free (p);
+    }
+    saa_free (syms);
+    raa_free (bsym);
+    saa_free (strs);
+}
+
+static long as86_section_names (char *name, int pass, int *bits) 
+{
+    /*
+     * Default is 16 bits.
+     */
+    if (!name)
+       *bits = 16;
+
+    if (!name)
+       return stext.index;
+
+    if (!strcmp(name, ".text"))
+       return stext.index;
+    else if (!strcmp(name, ".data"))
+       return sdata.index;
+    else if (!strcmp(name, ".bss"))
+       return bssindex;
+    else
+       return NO_SEG;
+}
+
+static int as86_add_string (char *name) 
+{
+    int pos = strslen;
+    int length = strlen(name);
+
+    saa_wbytes (strs, name, (long)(length+1));
+    strslen += 1+length;
+
+    return pos;
+}
+
+static void as86_deflabel (char *name, long segment, long offset,
+                          int is_global, char *special) 
+{
+    struct Symbol *sym;
+
+    if (special)
+       error (ERR_NONFATAL, "as86 format does not support any"
+              " special symbol types");
+
+    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
+       error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
+       return;
+    }
+
+    sym = saa_wstruct (syms);
+
+    sym->strpos = as86_add_string (name);
+    sym->flags = 0;
+    if (segment == NO_SEG)
+       sym->flags |= SYM_ABSOLUTE, sym->segment = 0;
+    else if (segment == stext.index)
+       sym->segment = SECT_TEXT;
+    else if (segment == sdata.index)
+       sym->segment = SECT_DATA;
+    else if (segment == bssindex)
+       sym->segment = SECT_BSS;
+    else {
+       sym->flags |= SYM_IMPORT;
+       sym->segment = 15;
+    }
+
+    if (is_global == 2)
+       sym->segment = 3;       /* already have IMPORT */
+
+    if (is_global && !(sym->flags & SYM_IMPORT))
+       sym->flags |= SYM_EXPORT;
+
+    sym->value = offset;
+
+    /*
+     * define the references from external-symbol segment numbers
+     * to these symbol records.
+     */
+    if (segment != NO_SEG && segment != stext.index &&
+       segment != sdata.index && segment != bssindex)
+       bsym = raa_write (bsym, segment, nsyms);
+
+    nsyms++;
+}
+
+static void as86_add_piece (struct Section *sect, int type, long offset,
+                           long segment, long bytes, int relative) 
+{
+    struct Piece *p;
+
+    sect->len += bytes;
+
+    if (type == 0 && sect->last && sect->last->type == 0) {
+       sect->last->bytes += bytes;
+       return;
+    }
+
+    p = sect->last = *sect->tail = nasm_malloc(sizeof(struct Piece));
+    sect->tail = &p->next;
+    p->next = NULL;
+
+    p->type = type;
+    p->offset = offset;
+    p->bytes = bytes;
+    p->relative = relative;
+
+    if (type == 1 && segment == stext.index)
+       p->number = SECT_TEXT;
+    else if (type == 1 && segment == sdata.index)
+       p->number = SECT_DATA;
+    else if (type == 1 && segment == bssindex)
+       p->number = SECT_BSS;
+    else if (type == 1)
+       p->number = raa_read (bsym, segment), p->type = 2;
+}
+
+static void as86_out (long segto, void *data, unsigned long type,
+                     long segment, long wrt) 
+{
+    struct Section *s;
+    long realbytes = type & OUT_SIZMASK;
+    long offset;
+    unsigned char mydata[4], *p;
+
+    if (wrt != NO_SEG) {
+       wrt = NO_SEG;                  /* continue to do _something_ */
+       error (ERR_NONFATAL, "WRT not supported by as86 output format");
+    }
+
+    type &= OUT_TYPMASK;
+
+    /*
+     * handle absolute-assembly (structure definitions)
+     */
+    if (segto == NO_SEG) {
+       if (type != OUT_RESERVE)
+           error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
+                  " space");
+       return;
+    }
+
+    if (segto == stext.index)
+       s = &stext;
+    else if (segto == sdata.index)
+       s = &sdata;
+    else if (segto == bssindex)
+       s = NULL;
+    else {
+       error(ERR_WARNING, "attempt to assemble code in"
+             " segment %d: defaulting to `.text'", segto);
+       s = &stext;
+    }
+
+    if (!s && type != OUT_RESERVE) {
+       error(ERR_WARNING, "attempt to initialise memory in the"
+             " BSS section: ignored");
+       if (type == OUT_REL2ADR)
+           realbytes = 2;
+       else if (type == OUT_REL4ADR)
+           realbytes = 4;
+       bsslen += realbytes;
+       return;
+    }
+
+    if (type == OUT_RESERVE) {
+       if (s) {
+           error(ERR_WARNING, "uninitialised space declared in"
+                 " %s section: zeroing",
+                 (segto == stext.index ? "code" : "data"));
+           as86_sect_write (s, NULL, realbytes);
+           as86_add_piece (s, 0, 0L, 0L, realbytes, 0);
+       } else
+           bsslen += realbytes;
+    } else if (type == OUT_RAWDATA) {
+       if (segment != NO_SEG)
+           error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
+       as86_sect_write (s, data, realbytes);
+       as86_add_piece (s, 0, 0L, 0L, realbytes, 0);
+    } else if (type == OUT_ADDRESS) {
+       if (segment != NO_SEG) {
+           if (segment % 2) {
+               error(ERR_NONFATAL, "as86 format does not support"
+                     " segment base references");
+           } else{
+               offset = * (long *) data;
+               as86_add_piece (s, 1, offset, segment, realbytes, 0);
+           }
+       } else {
+           p = mydata;
+           WRITELONG (p, * (long *) data);
+           as86_sect_write (s, data, realbytes);
+           as86_add_piece (s, 0, 0L, 0L, realbytes, 0);
+       }
+    } else if (type == OUT_REL2ADR) {
+       if (segment == segto)
+           error(ERR_PANIC, "intra-segment OUT_REL2ADR");
+       if (segment != NO_SEG) {
+           if (segment % 2) {
+               error(ERR_NONFATAL, "as86 format does not support"
+                     " segment base references");
+           } else {
+               offset = * (long *) data;
+               as86_add_piece (s, 1, offset-realbytes+2, segment, 2L, 1);
+           }
+       }
+    } else if (type == OUT_REL4ADR) {
+       if (segment == segto)
+           error(ERR_PANIC, "intra-segment OUT_REL4ADR");
+       if (segment != NO_SEG) {
+           if (segment % 2) {
+               error(ERR_NONFATAL, "as86 format does not support"
+                     " segment base references");
+           } else {
+               offset = * (long *) data;
+               as86_add_piece (s, 1, offset-realbytes+4, segment, 4L, 1);
+           }
+       }
+    }
+}
+
+static void as86_write(void) 
+{
+    unsigned long i;
+    long symlen, seglen, segsize;
+
+    /*
+     * First, go through the symbol records working out how big
+     * each will be. Also fix up BSS references at this time, and
+     * set the flags words up completely.
+     */
+    symlen = 0;
+    saa_rewind (syms);
+    for (i = 0; i < nsyms; i++) {
+       struct Symbol *sym = saa_rstruct (syms);
+       if (sym->segment == SECT_BSS)
+           sym->segment = SECT_DATA, sym->value += sdata.len;
+       sym->flags |= sym->segment;
+       if (sym->value == 0)
+           sym->flags |= 0 << 14, symlen += 4;
+       else if (sym->value >= 0 && sym->value <= 255)
+           sym->flags |= 1 << 14, symlen += 5;
+       else if (sym->value >= 0 && sym->value <= 65535L)
+           sym->flags |= 2 << 14, symlen += 6;
+       else
+           sym->flags |= 3 << 14, symlen += 8;
+    }
+
+    /*
+     * Now do the same for the segments, and get the segment size
+     * descriptor word at the same time.
+     */
+    seglen = segsize = 0;
+    if ((unsigned long) stext.len > 65535L)
+       segsize |= 0x03000000L, seglen += 4;
+    else
+       segsize |= 0x02000000L, seglen += 2;
+    if ((unsigned long) sdata.len > 65535L)
+       segsize |= 0xC0000000L, seglen += 4;
+    else
+       segsize |= 0x80000000L, seglen += 2;
+
+    /*
+     * Emit the as86 header.
+     */
+    fwritelong (0x000186A3L, as86fp);
+    fputc (0x2A, as86fp);
+    fwritelong (27+symlen+seglen+strslen, as86fp);   /* header length */
+    fwritelong (stext.len+sdata.len, as86fp);
+    fwriteshort (strslen, as86fp);
+    fwriteshort (0, as86fp);          /* class = revision = 0 */
+    fwritelong (0x55555555L, as86fp);   /* segment max sizes: always this */
+    fwritelong (segsize, as86fp);      /* segment size descriptors */
+    if (segsize & 0x01000000L)
+       fwritelong (stext.len, as86fp);
+    else
+       fwriteshort (stext.len, as86fp);
+    if (segsize & 0x40000000L)
+       fwritelong (sdata.len, as86fp);
+    else
+       fwriteshort (sdata.len, as86fp);
+    fwriteshort (nsyms, as86fp);
+
+    /*
+     * Write the symbol table.
+     */
+    saa_rewind (syms);
+    for (i = 0; i < nsyms; i++) {
+       struct Symbol *sym = saa_rstruct (syms);
+       fwriteshort (sym->strpos, as86fp);
+       fwriteshort (sym->flags, as86fp);
+       switch (sym->flags & (3<<14)) {
+         case 0<<14: break;
+         case 1<<14: fputc (sym->value, as86fp); break;
+         case 2<<14: fwriteshort (sym->value, as86fp); break;
+         case 3<<14: fwritelong (sym->value, as86fp); break;
+       }
+    }
+
+    /*
+     * Write out the string table.
+     */
+    saa_fpwrite (strs, as86fp);
+
+    /*
+     * Write the program text.
+     */
+    as86_reloc_size = -1;
+    as86_write_section (&stext, SECT_TEXT);
+    as86_write_section (&sdata, SECT_DATA);
+    fputc (0, as86fp);                /* termination */
+}
+
+static void as86_set_rsize (int size) 
+{
+    if (as86_reloc_size != size) {
+       switch (as86_reloc_size = size) {
+         case 1: fputc (0x01, as86fp); break;
+         case 2: fputc (0x02, as86fp); break;
+         case 4: fputc (0x03, as86fp); break;
+         default: error (ERR_PANIC, "bizarre relocation size %d", size);
+       }
+    }
+}
+
+static void as86_write_section (struct Section *sect, int index) 
+{
+    struct Piece *p;
+    unsigned long s;
+    long length;
+
+    fputc (0x20+index, as86fp);               /* select the right section */
+
+    saa_rewind (sect->data);
+
+    for (p = sect->head; p; p = p->next)
+       switch (p->type) {
+         case 0:
+           /*
+            * Absolute data. Emit it in chunks of at most 64
+            * bytes.
+            */
+           length = p->bytes;
+           do {
+               char buf[64];
+               long tmplen = (length > 64 ? 64 : length);
+               fputc (0x40 | (tmplen & 0x3F), as86fp);
+               saa_rnbytes (sect->data, buf, tmplen);
+               fwrite (buf, 1, tmplen, as86fp);
+               length -= tmplen;
+           } while (length > 0);
+           break;
+         case 1:
+           /*
+            * A segment-type relocation. First fix up the BSS.
+            */
+           if (p->number == SECT_BSS)
+               p->number = SECT_DATA, p->offset += sdata.len;
+           as86_set_rsize (p->bytes);
+           fputc (0x80 | (p->relative ? 0x20 : 0) | p->number, as86fp);
+           if (as86_reloc_size == 2)
+               fwriteshort (p->offset, as86fp);
+           else
+               fwritelong (p->offset, as86fp);
+           break;
+         case 2:
+           /*
+            * A symbol-type relocation.
+            */
+           as86_set_rsize (p->bytes);
+           s = p->offset;
+           if (s > 65535L)
+               s = 3;
+           else if (s > 255)
+               s = 2;
+           else if (s > 0)
+               s = 1;
+           else
+               s = 0;
+           fputc (0xC0 |
+                  (p->relative ? 0x20 : 0) |
+                  (p->number > 255 ? 0x04 : 0) | s, as86fp);
+           if (p->number > 255)
+               fwriteshort (p->number, as86fp);
+           else
+               fputc (p->number, as86fp);
+           switch ((int)s) {
+             case 0: break;
+             case 1: fputc (p->offset, as86fp); break;
+             case 2: fwriteshort (p->offset, as86fp); break;
+             case 3: fwritelong (p->offset, as86fp); break;
+           }
+           break;
+       }
+}
+
+static void as86_sect_write (struct Section *sect,
+                            unsigned char *data, unsigned long len) 
+{
+    saa_wbytes (sect->data, data, len);
+    sect->datalen += len;
+}
+
+static long as86_segbase (long segment) 
+{
+    return segment;
+}
+
+static int as86_directive (char *directive, char *value, int pass) 
+{
+    return 0;
+}
+
+static void as86_filename (char *inname, char *outname, efunc error) 
+{
+    char *p;
+
+    if ( (p = strrchr (inname, '.')) != NULL) {
+       strncpy (as86_module, inname, p-inname);
+       as86_module[p-inname] = '\0';
+    } else
+       strcpy (as86_module, inname);
+
+    standard_extension (inname, outname, ".o", error);
+}
+
+static char *as86_stdmac[] = {
+    "%define __SECT__ [section .text]",
+    "%macro __NASM_CDecl__ 1",
+    "%endmacro",
+    NULL
+};
+
+static int as86_set_info(enum geninfo type, char **val)
+{
+    return 0;
+}
+void as86_linenumber (char *name, long segment, long offset, int is_main,
+                    int lineno)
+{
+}
+struct ofmt of_as86 = {
+    "Linux as86 (bin86 version 0.3) object files",
+    "as86",
+    NULL,
+    null_debug_arr,
+    &null_debug_form,
+    as86_stdmac,
+    as86_init,
+    as86_set_info,
+    as86_out,
+    as86_deflabel, 
+    as86_section_names,
+    as86_segbase,
+    as86_directive,
+    as86_filename,
+    as86_cleanup
+};
+
+#endif /* OF_AS86 */
diff --git a/output/outbin.c b/output/outbin.c
new file mode 100644 (file)
index 0000000..95ac5da
--- /dev/null
@@ -0,0 +1,591 @@
+/* outbin.c output routines for the Netwide Assembler to produce
+ *    flat-form binary files
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+/*
+ * version with multiple sections support
+ *
+ * sections go in order defined by their org's if present
+ * if no org present, sections go in sequence they appear.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "nasm.h"
+#include "nasmlib.h"
+#include "outform.h"
+
+#ifdef OF_BIN
+
+static FILE *fp;
+static efunc error;
+
+static struct Section {
+    struct Section *next;
+    struct SAA *contents;
+    long length;
+    long org;                  /* assigned org */
+    long pos;                  /* file position of section ?? */
+    long pad;                  /* padding bytes to next section in file */
+    long index;                /* the NASM section id */
+    long align;                /* section alignment, cannot be absolute addr */
+    char *name;
+} *sections, **sectail;
+
+static struct Reloc {
+    struct Reloc *next;
+    long posn;
+    long bytes;
+    long secref;
+    long secrel;
+    struct Section *target;
+} *relocs, **reloctail;
+
+static long current_section;
+
+static void add_reloc (struct Section *s, long bytes, long secref,
+             long secrel)
+{
+    struct Reloc *r;
+
+    r = *reloctail = nasm_malloc(sizeof(struct Reloc));
+    reloctail = &r->next;
+    r->next = NULL;
+    r->posn = s->length;
+    r->bytes = bytes;
+    r->secref = secref;
+    r->secrel = secrel;
+    r->target = s;
+}
+
+static struct Section *find_section_by_name(char *name)
+{
+   struct Section *s;
+
+   for (s = sections; s; s = s->next)
+      if (!strcmp(s->name,name))
+         break;
+
+   return s;
+}
+
+static struct Section *find_section_by_index(long index)
+{
+   struct Section *s;
+
+   for (s = sections; s; s = s->next)
+      if ( s->index == index )
+         break;
+
+   return s;
+}
+
+static struct Section *alloc_section(char *name)
+{
+   struct Section *s;
+
+   s = find_section_by_name(name);
+   if(s)
+      error(ERR_PANIC, "section %s re-defined", name);
+
+   s = nasm_malloc(sizeof(struct Section));
+   *sectail    = s;
+   sectail     = &s->next;
+   s->next     = NULL;
+
+   s->contents = saa_init(1L);
+   s->length   = 0;
+   s->pos      = 0;
+   s->org      = -1; /* default org is -1 because we want
+                      * to adjust sections one after another
+                      */
+   s->index    = seg_alloc();
+   s->align    = 4;
+   s->pad      = 0;
+   s->name     = nasm_strdup(name);
+
+   return s;
+}
+
+static void bin_init (FILE *afp, efunc errfunc, ldfunc ldef, evalfunc eval)
+{
+    fp = afp;
+    error = errfunc;
+
+    (void) eval;   /* Don't warn that this parameter is unused */
+    (void) ldef;            /* placate optimisers */
+
+    current_section = -1L;
+    relocs    = NULL;
+    reloctail = &relocs;
+    sections  = NULL;
+    sectail   = &sections;
+}
+
+static void bin_cleanup (int debuginfo)
+{
+   struct Section *outsections, **outstail;
+   struct Section *s, *o, *ls, *lo;
+   struct Reloc *r;
+   long least_org;
+
+   (void) debuginfo;
+
+   /* sort sections by their orgs
+    * sections without org follow their natural order
+    * after the org'd sections
+    */
+   outsections = NULL;
+   outstail = &outsections;
+
+   while( 1 )
+   {
+      least_org = 0x7fffffff;
+
+      ls = lo = NULL;
+      for( s = sections, o = NULL; s; o = s, s = s->next )
+         if( s->org != -1 && s->org < least_org )
+         {
+            least_org = s->org;
+            ls = s;
+            lo = o;
+         }
+
+      if(ls) /* relink to outsections */
+      {
+#ifdef DEBUG
+         fprintf(stdout, "bin_cleanup: relinking section %s org %ld\n", ls->name, ls->org);
+#endif
+         /* unlink from sections */
+         if(lo)
+            lo->next = ls->next;
+         else
+            if(ls == sections)
+               sections = ls->next;
+
+         /* link in to outsections */
+         if( ls->length > 0 )
+         {
+            *outstail   = ls;
+            outstail    = &ls->next;
+            ls->next    = NULL;
+         }
+      }
+      else
+         break;
+   }
+
+   /* link outsections at start of sections */
+   *outstail = sections;
+   sections = outsections;
+
+   /* calculate sections positions */
+   for(s = sections, o = NULL; s; s = s->next)
+   {
+      if(!strcmp(s->name,".bss")) continue; /* don't count .bss yet */
+
+      if(o)
+      {
+         /* if section doesn't have its
+          * own org, align from prev section
+          */
+         if( s->org == -1 )
+            s->org = o->org + o->length;
+
+         /* check orgs */
+         if( s->org - o->org < o->length )
+            error( ERR_PANIC, "sections %s and %s overlap!", o->name, s->name );
+
+         /* align previous section */
+         o->pad = ((o->pos + o->length + o->align-1) & ~(o->align-1)) - (o->pos + o->length);
+
+         if( s->org - o->org > o->length )
+         {
+#ifdef DEBUG
+            fprintf(stdout, "forced padding: %ld\n", s->org - o->org - o->length);
+#endif
+            o->pad = s->org - o->org - o->length;
+         }
+
+         s->pos += o->pos + o->length + o->pad;
+         s->org = s->pos + sections->org;
+      }
+
+#ifdef DEBUG
+      fprintf(stdout, "bin_cleanup: section %s at %ld(%lx) org %ld(%lx) prev <pos %ld(%lx)+size %ld(%lx)+pad %ld(%lx)> size %ld(%lx) align %ld(%lx)\n",
+              s->name, s->pos, s->pos, s->org, s->org, o?o->pos:0, o?o->pos:0,
+              o?o->length:0, o?o->length:0, o?o->pad:0, o?o->pad:0, s->length, s->length,
+              s->align, s->align);
+#endif
+
+      /* prepare for relocating by the way */
+      saa_rewind( s->contents );
+
+      o = s;
+   }
+
+   /* adjust .bss */
+   s = find_section_by_name(".bss");
+   if(s)
+   {
+      s->org = o->org + o->length + o->pad;
+
+#ifdef DEBUG
+      fprintf(stdout, "bin_cleanup: section %s at %ld org %ld prev (pos %ld+size %ld+pad %ld) size %ld align %ld\n",
+              s->name, s->pos, s->org, o?o->pos:0, o?o->length:0, o?o->pad:0, s->length, s->align);
+#endif
+   }
+
+   /* apply relocations */
+   for (r = relocs; r; r = r->next)
+   {
+      unsigned char *p, *q, mydata[4];
+      long l;
+
+      saa_fread (r->target->contents, r->posn, mydata, r->bytes);
+      p = q = mydata;
+      l = *p++;
+
+      if (r->bytes > 1) {
+         l += ((long)*p++) << 8;
+         if (r->bytes == 4) {
+            l += ((long)*p++) << 16;
+            l += ((long)*p++) << 24;
+         }
+      }
+
+      s = find_section_by_index(r->secref);
+      if(s)
+         l += s->org;
+
+      s = find_section_by_index(r->secrel);
+      if(s)
+         l -= s->org;
+
+      if (r->bytes == 4)
+          WRITELONG(q, l);
+      else if (r->bytes == 2)
+          WRITESHORT(q, l);
+      else
+          *q++ = l & 0xFF;
+      saa_fwrite (r->target->contents, r->posn, mydata, r->bytes);
+   }
+
+   /* write sections to file */
+   for(s = outsections; s; s = s->next)
+   {
+      if(s->length > 0 && strcmp(s->name,".bss"))
+      {
+#ifdef DEBUG
+         fprintf(stdout, "bin_cleanup: writing section %s\n", s->name);
+#endif
+         saa_fpwrite (s->contents, fp);
+         if( s->next )
+            while( s->pad-- > 0 )
+               fputc('\0', fp);
+               /* could pad with nops, since we don't
+                * know if this is code section or not
+                */
+      }
+   }
+
+   fclose (fp);
+
+   while (relocs) {
+      r = relocs->next;
+      nasm_free (relocs);
+      relocs = r;
+   }
+
+   while (outsections) {
+      s = outsections->next;
+      saa_free  (outsections->contents);
+      nasm_free (outsections->name);
+      nasm_free (outsections);
+      outsections = s;
+   }
+}
+
+static void bin_out (long segto, void *data, unsigned long type,
+           long segment, long wrt)
+{
+    unsigned char *p, mydata[4];
+    struct Section *s, *sec;
+    long realbytes;
+
+    if (wrt != NO_SEG) {
+   wrt = NO_SEG;            /* continue to do _something_ */
+   error (ERR_NONFATAL, "WRT not supported by binary output format");
+    }
+
+    /*
+     * handle absolute-assembly (structure definitions)
+     */
+    if (segto == NO_SEG) {
+   if ((type & OUT_TYPMASK) != OUT_RESERVE)
+       error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
+         " space");
+   return;
+    }
+
+    /*
+     * Find the segment we are targetting.
+     */
+    s = find_section_by_index(segto);
+    if (!s)
+   error (ERR_PANIC, "code directed to nonexistent segment?");
+
+    if (!strcmp(s->name, ".bss")) {         /* BSS */
+   if ((type & OUT_TYPMASK) != OUT_RESERVE)
+       error(ERR_WARNING, "attempt to initialise memory in the"
+        " BSS section: ignored");
+   s = NULL;
+    }
+
+   if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
+
+      if (segment != NO_SEG && !find_section_by_index(segment)) {
+          if (segment % 2)
+         error(ERR_NONFATAL, "binary output format does not support"
+               " segment base references");
+          else
+         error(ERR_NONFATAL, "binary output format does not support"
+               " external references");
+          segment = NO_SEG;
+      }
+
+      if (s) {
+         if (segment != NO_SEG)
+            add_reloc (s, type & OUT_SIZMASK, segment, -1L);
+         p = mydata;
+         if ((type & OUT_SIZMASK) == 4)
+            WRITELONG (p, *(long *)data);
+         else
+            WRITESHORT (p, *(long *)data);
+         saa_wbytes (s->contents, mydata, type & OUT_SIZMASK);
+         s->length += type & OUT_SIZMASK;
+      } else {
+         sec = find_section_by_name(".bss");
+         if(!sec)
+            error(ERR_PANIC, ".bss section is not present");
+         sec->length += type & OUT_SIZMASK;
+      }
+
+   } else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
+      type &= OUT_SIZMASK;
+      p = data;
+      if (s) {
+          saa_wbytes (s->contents, data, type);
+          s->length += type;
+      } else {
+         sec = find_section_by_name(".bss");
+         if(!sec)
+            error(ERR_PANIC, ".bss section is not present");
+         sec->length += type;
+      }
+
+   } else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
+      if (s) {
+          error(ERR_WARNING, "uninitialised space declared in"
+           " %s section: zeroing", s->name);
+      }
+      type &= OUT_SIZMASK;
+      if (s) {
+          saa_wbytes (s->contents, NULL, type);
+          s->length += type;
+      } else {
+         sec = find_section_by_name(".bss");
+         if(!sec)
+            error(ERR_PANIC, ".bss section is not present");
+         sec->length += type;
+      }
+   }
+   else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
+        (type & OUT_TYPMASK) == OUT_REL4ADR)
+   {
+      realbytes = ((type & OUT_TYPMASK) == OUT_REL4ADR ? 4 : 2);
+
+      if (segment != NO_SEG && !find_section_by_index(segment)) {
+          if (segment % 2)
+         error(ERR_NONFATAL, "binary output format does not support"
+               " segment base references");
+          else
+         error(ERR_NONFATAL, "binary output format does not support"
+               " external references");
+          segment = NO_SEG;
+      }
+
+      if (s) {
+         add_reloc (s, realbytes, segment, segto);
+         p = mydata;
+         if (realbytes == 4)
+            WRITELONG (p, *(long*)data - realbytes - s->length);
+         else
+            WRITESHORT (p, *(long*)data - realbytes - s->length);
+         saa_wbytes (s->contents, mydata, realbytes);
+         s->length += realbytes;
+      } else {
+         sec = find_section_by_name(".bss");
+         if(!sec)
+            error(ERR_PANIC, ".bss section is not present");
+         sec->length += realbytes;
+      }
+   }
+}
+
+static void bin_deflabel (char *name, long segment, long offset,
+           int is_global, char *special)
+{
+    (void) segment;   /* Don't warn that this parameter is unused */
+    (void) offset;    /* Don't warn that this parameter is unused */
+
+    if (special)
+   error (ERR_NONFATAL, "binary format does not support any"
+          " special symbol types");
+
+    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
+   error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
+   return;
+    }
+
+    if (is_global == 2) {
+   error (ERR_NONFATAL, "binary output format does not support common"
+          " variables");
+    }
+}
+
+static long bin_secname (char *name, int pass, int *bits)
+{
+    int sec_index;
+    long *sec_align;
+    char *p;
+    struct Section *sec;
+
+    (void) pass;   /* Don't warn that this parameter is unused */
+
+    /*
+     * Default is 16 bits .text segment
+     */
+   if (!name)
+   {
+      *bits = 16;
+      sec = find_section_by_name(".text");
+      if(!sec) sec = alloc_section(".text");
+      sec->org = 0; /* default .text org */
+      current_section = sec->index;
+      return sec->index;
+   }
+
+   p = name;
+   while (*p && !isspace(*p)) p++;
+   if (*p) *p++ = '\0';
+   if (!strcmp(name, ".text")) {
+      sec = find_section_by_name(".text");
+      if(!sec) sec = alloc_section(".text");
+      sec_index = sec->index;
+      sec_align = NULL;
+   } else {
+      sec = find_section_by_name(name);
+      if(!sec) sec = alloc_section(name);
+      sec_index = sec->index;
+      sec_align = &sec->align;
+   }
+
+    if (*p) {
+   if (!nasm_strnicmp(p,"align=",6)) {
+       if (sec_align == NULL)
+      error(ERR_NONFATAL, "cannot specify an alignment to"
+            " the .text section");
+       else if (p[6+strspn(p+6,"0123456789")])
+      error(ERR_NONFATAL, "argument to `align' is not numeric");
+       else {
+      unsigned int align = atoi(p+6);
+      if (!align || ((align-1) & align))
+          error(ERR_NONFATAL, "argument to `align' is not a"
+           " power of two");
+      else
+          *sec_align = align;
+       }
+    }
+   }
+
+   current_section = sec->index;
+   return sec_index;
+}
+
+static long bin_segbase (long segment)
+{
+    return segment;
+}
+
+static int bin_directive (char *directive, char *value, int pass)
+{
+   struct Section *s;
+   int rn_error;
+
+   (void) pass;   /* Don't warn that this parameter is unused */
+
+   if (!nasm_stricmp(directive, "org")) {
+      if(current_section == -1)
+         error(ERR_PANIC, "org of cosmic space specified");
+
+      s = find_section_by_index(current_section);
+      if(!s)
+         error(ERR_PANIC, "current_section points nowhere");
+
+      s->org = readnum (value, &rn_error);
+      if (rn_error)
+          error (ERR_NONFATAL, "argument to ORG should be numeric");
+      return 1;
+   }
+
+   return 0;
+}
+
+static void bin_filename (char *inname, char *outname, efunc error)
+{
+    standard_extension (inname, outname, "", error);
+}
+
+static char *bin_stdmac[] = {
+    "%define __SECT__ [section .text]",
+    "%imacro org 1+.nolist",
+    "[org %1]",
+    "%endmacro",
+    "%macro __NASM_CDecl__ 1",
+    "%endmacro",
+    NULL
+};
+
+static int bin_set_info(enum geninfo type, char **val)
+{
+    return 0;
+}
+
+struct ofmt of_bin = {
+    "flat-form binary files (e.g. DOS .COM, .SYS) multisection support test",
+    "bin",
+    NULL,
+    null_debug_arr,
+    &null_debug_form,
+    bin_stdmac,
+    bin_init,
+    bin_set_info,
+    bin_out,
+    bin_deflabel,
+    bin_secname,
+    bin_segbase,
+    bin_directive,
+    bin_filename,
+    bin_cleanup
+};
+
+#endif /* OF_BIN */
diff --git a/output/outcoff.c b/output/outcoff.c
new file mode 100644 (file)
index 0000000..973d9fe
--- /dev/null
@@ -0,0 +1,779 @@
+/* outcoff.c   output routines for the Netwide Assembler to produce
+ *             COFF object files (for DJGPP and Win32)
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "nasm.h"
+#include "nasmlib.h"
+#include "outform.h"
+
+#if defined(OF_COFF) || defined(OF_WIN32)
+
+/*
+ * Notes on COFF:
+ *
+ * (0) When I say `standard COFF' below, I mean `COFF as output and
+ * used by DJGPP'. I assume DJGPP gets it right.
+ *
+ * (1) Win32 appears to interpret the term `relative relocation'
+ * differently from standard COFF. Standard COFF understands a
+ * relative relocation to mean that during relocation you add the
+ * address of the symbol you're referencing, and subtract the base
+ * address of the section you're in. Win32 COFF, by contrast, seems
+ * to add the address of the symbol and then subtract the address
+ * of THE BYTE AFTER THE RELOCATED DWORD. Hence the two formats are
+ * subtly incompatible.
+ *
+ * (2) Win32 doesn't bother putting any flags in the header flags
+ * field (at offset 0x12 into the file).
+ *
+ * (3) Win32 uses some extra flags into the section header table:
+ * it defines flags 0x80000000 (writable), 0x40000000 (readable)
+ * and 0x20000000 (executable), and uses them in the expected
+ * combinations. It also defines 0x00100000 through 0x00700000 for
+ * section alignments of 1 through 64 bytes.
+ *
+ * (4) Both standard COFF and Win32 COFF seem to use the DWORD
+ * field directly after the section name in the section header
+ * table for something strange: they store what the address of the
+ * section start point _would_ be, if you laid all the sections end
+ * to end starting at zero. Dunno why. Microsoft's documentation
+ * lists this field as "Virtual Size of Section", which doesn't
+ * seem to fit at all. In fact, Win32 even includes non-linked
+ * sections such as .drectve in this calculation.
+ *
+ * (5) Standard COFF does something very strange to common
+ * variables: the relocation point for a common variable is as far
+ * _before_ the variable as its size stretches out _after_ it. So
+ * we must fix up common variable references. Win32 seems to be
+ * sensible on this one.
+ */
+
+/* Flag which version of COFF we are currently outputting. */
+static int win32;
+
+struct Reloc {
+    struct Reloc *next;
+    long address;                     /* relative to _start_ of section */
+    long symbol;                      /* symbol number */
+    enum {
+       SECT_SYMBOLS,
+       ABS_SYMBOL,
+       REAL_SYMBOLS
+    } symbase;                        /* relocation for symbol number :) */
+    int relative;                     /* TRUE or FALSE */
+};
+
+struct Symbol {
+    char name[9];
+    long strpos;                      /* string table position of name */
+    int section;                      /* section number where it's defined
+                                       * - in COFF codes, not NASM codes */
+    int is_global;                    /* is it a global symbol or not? */
+    long value;                               /* address, or COMMON variable size */
+};
+
+static FILE *coffp;
+static efunc error;
+static char coff_infile[FILENAME_MAX];
+
+struct Section {
+    struct SAA *data;
+    unsigned long len;
+    int nrelocs;
+    long index;
+    struct Reloc *head, **tail;
+    unsigned long flags;              /* section flags */
+    char name[9];
+    long pos, relpos;
+};
+
+#define TEXT_FLAGS (win32 ? 0x60500020L : 0x20L)
+#define DATA_FLAGS (win32 ? 0xC0300040L : 0x40L)
+#define BSS_FLAGS (win32 ? 0xC0300080L : 0x80L)
+#define INFO_FLAGS 0x00100A00L
+#define RDATA_FLAGS (win32 ? 0x40400040L : 0x40L)
+
+#define SECT_DELTA 32
+static struct Section **sects;
+static int nsects, sectlen;
+
+static struct SAA *syms;
+static unsigned long nsyms;
+
+static long def_seg;
+
+static int initsym;
+
+static struct RAA *bsym, *symval;
+
+static struct SAA *strs;
+static unsigned long strslen;
+
+static void coff_gen_init(FILE *, efunc);
+static void coff_sect_write (struct Section *, unsigned char *,
+                            unsigned long);
+static void coff_write (void);
+static void coff_section_header (char *, long, long, long, long, int, long);
+static void coff_write_relocs (struct Section *);
+static void coff_write_symbols (void);
+
+static void coff_win32_init(FILE *fp,  efunc errfunc,
+                           ldfunc ldef, evalfunc eval) 
+{
+    win32 = TRUE;
+    (void) ldef;                      /* placate optimisers */
+    coff_gen_init(fp, errfunc);
+}
+
+static void coff_std_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
+{
+    win32 = FALSE;
+    (void) ldef;                      /* placate optimisers */
+    coff_gen_init(fp, errfunc);
+}
+
+static void coff_gen_init(FILE *fp, efunc errfunc) 
+{
+
+    coffp = fp;
+    error = errfunc;
+    sects = NULL;
+    nsects = sectlen = 0;
+    syms = saa_init((long)sizeof(struct Symbol));
+    nsyms = 0;
+    bsym = raa_init();
+    symval = raa_init();
+    strs = saa_init(1L);
+    strslen = 0;
+    def_seg = seg_alloc();
+}
+
+static void coff_cleanup(int debuginfo) 
+{
+    struct Reloc *r;
+    int i;
+
+    (void) debuginfo;
+
+    coff_write();
+    fclose (coffp);
+    for (i=0; i<nsects; i++) {
+       if (sects[i]->data)
+           saa_free (sects[i]->data);
+       while (sects[i]->head) {
+           r = sects[i]->head;
+           sects[i]->head = sects[i]->head->next;
+           nasm_free (r);
+       }
+       nasm_free (sects[i]);
+    }
+    nasm_free (sects);
+    saa_free (syms);
+    raa_free (bsym);
+    raa_free (symval);
+    saa_free (strs);
+}
+
+static int coff_make_section (char *name, unsigned long flags) 
+{
+    struct Section *s;
+
+    s = nasm_malloc (sizeof(*s));
+
+    if (flags != BSS_FLAGS)
+       s->data = saa_init (1L);
+    else
+       s->data = NULL;
+    s->head = NULL;
+    s->tail = &s->head;
+    s->len = 0;
+    s->nrelocs = 0;
+    if (!strcmp(name, ".text"))
+       s->index = def_seg;
+    else
+       s->index = seg_alloc();
+    strncpy (s->name, name, 8);
+    s->name[8] = '\0';
+    s->flags = flags;
+
+    if (nsects >= sectlen)
+       sects = nasm_realloc (sects, (sectlen += SECT_DELTA)*sizeof(*sects));
+    sects[nsects++] = s;
+
+    return nsects-1;
+}
+
+static long coff_section_names (char *name, int pass, int *bits) 
+{
+    char *p;
+    unsigned long flags, align_and = ~0L, align_or = 0L;
+    int i;
+
+    /*
+     * Default is 32 bits.
+     */
+    if (!name)
+       *bits = 32;
+
+    if (!name)
+       return def_seg;
+
+    p = name;
+    while (*p && !isspace(*p)) p++;
+    if (*p) *p++ = '\0';
+    if (strlen(name) > 8) {
+       error (ERR_WARNING, "COFF section names limited to 8 characters:"
+              " truncating");
+       name[8] = '\0';
+    }
+    flags = 0;
+
+    while (*p && isspace(*p)) p++;
+    while (*p) {
+       char *q = p;
+       while (*p && !isspace(*p)) p++;
+       if (*p) *p++ = '\0';
+       while (*p && isspace(*p)) p++;
+
+       if (!nasm_stricmp(q, "code") || !nasm_stricmp(q, "text")) {
+           flags = TEXT_FLAGS;
+       } else if (!nasm_stricmp(q, "data")) {
+           flags = DATA_FLAGS;
+       } else if (!nasm_stricmp(q, "rdata")) {
+           if (win32)
+           flags = RDATA_FLAGS;
+           else {
+               flags = DATA_FLAGS;    /* gotta do something */
+               error (ERR_NONFATAL, "standard COFF does not support"
+                      " read-only data sections");
+           }
+       } else if (!nasm_stricmp(q, "bss")) {
+           flags = BSS_FLAGS;
+       } else if (!nasm_stricmp(q, "info")) {
+           if (win32)
+               flags = INFO_FLAGS;
+           else {
+               flags = DATA_FLAGS;    /* gotta do something */
+               error (ERR_NONFATAL, "standard COFF does not support"
+                      " informational sections");
+           }
+       } else if (!nasm_strnicmp(q,"align=",6)) {
+           if (!win32)
+               error (ERR_NONFATAL, "standard COFF does not support"
+                      " section alignment specification");
+           else {
+               if (q[6+strspn(q+6,"0123456789")])
+                   error(ERR_NONFATAL, "argument to `align' is not numeric");
+               else {
+                   unsigned int align = atoi(q+6);
+                   if (!align || ((align-1) & align))
+                       error(ERR_NONFATAL, "argument to `align' is not a"
+                             " power of two");
+                   else if (align > 64)
+                       error(ERR_NONFATAL, "Win32 cannot align sections"
+                             " to better than 64-byte boundaries");
+                   else {
+                       align_and = ~0x00F00000L;
+                       align_or = (align == 1 ? 0x00100000L :
+                                   align == 2 ? 0x00200000L :
+                                   align == 4 ? 0x00300000L :
+                                   align == 8 ? 0x00400000L :
+                                   align == 16 ? 0x00500000L :
+                                   align == 32 ? 0x00600000L : 0x00700000L);
+                   }
+               }
+           }
+       }
+    }
+
+    for (i=0; i<nsects; i++)
+       if (!strcmp(name, sects[i]->name))
+           break;
+    if (i == nsects) {
+       if (!flags) {
+           if (!strcmp(name, ".data"))
+               flags = DATA_FLAGS;
+           else if (!strcmp(name, ".rdata"))
+               flags = RDATA_FLAGS;
+           else if (!strcmp(name, ".bss"))
+               flags = BSS_FLAGS;
+           else
+               flags = TEXT_FLAGS;
+       }
+       i = coff_make_section (name, flags);
+       if (flags)
+           sects[i]->flags = flags;
+       sects[i]->flags &= align_and;
+       sects[i]->flags |= align_or;
+    } else if (pass == 1) {
+       if (flags)
+           error (ERR_WARNING, "section attributes ignored on"
+                  " redeclaration of section `%s'", name);
+    }
+
+    return sects[i]->index;
+}
+
+static void coff_deflabel (char *name, long segment, long offset,
+                          int is_global, char *special) 
+{
+    int pos = strslen+4;
+    struct Symbol *sym;
+
+    if (special)
+       error (ERR_NONFATAL, "binary format does not support any"
+              " special symbol types");
+
+    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
+       error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
+       return;
+    }
+
+    if (strlen(name) > 8) {
+       saa_wbytes (strs, name, (long)(1+strlen(name)));
+       strslen += 1+strlen(name);
+    } else
+       pos = -1;
+
+    sym = saa_wstruct (syms);
+
+    sym->strpos = pos;
+    if (pos == -1)
+       strcpy (sym->name, name);
+    sym->is_global = !!is_global;
+    if (segment == NO_SEG)
+       sym->section = -1;      /* absolute symbol */
+    else {
+       int i;
+       sym->section = 0;
+       for (i=0; i<nsects; i++)
+           if (segment == sects[i]->index) {
+               sym->section = i+1;
+               break;
+           }
+       if (!sym->section)
+           sym->is_global = TRUE;
+    }
+    if (is_global == 2)
+       sym->value = offset;
+    else
+       sym->value = (sym->section == 0 ? 0 : offset);
+
+    /*
+     * define the references from external-symbol segment numbers
+     * to these symbol records.
+     */
+    if (sym->section == 0)
+       bsym = raa_write (bsym, segment, nsyms);
+
+    if (segment != NO_SEG)
+       symval = raa_write (symval, segment, sym->section ? 0 : sym->value);
+
+    nsyms++;
+}
+
+static long coff_add_reloc (struct Section *sect, long segment,
+                           int relative) 
+{
+    struct Reloc *r;
+
+    r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
+    sect->tail = &r->next;
+    r->next = NULL;
+
+    r->address = sect->len;
+    if (segment == NO_SEG)
+       r->symbol = 0, r->symbase = ABS_SYMBOL;
+    else {
+       int i;
+       r->symbase = REAL_SYMBOLS;
+       for (i=0; i<nsects; i++)
+           if (segment == sects[i]->index) {
+               r->symbol = i*2;
+               r->symbase = SECT_SYMBOLS;
+               break;
+           }
+       if (r->symbase == REAL_SYMBOLS)
+           r->symbol = raa_read (bsym, segment);
+    }
+    r->relative = relative;
+
+    sect->nrelocs++;
+
+    /*
+     * Return the fixup for standard COFF common variables.
+     */
+    if (r->symbase == REAL_SYMBOLS && !win32)
+       return raa_read (symval, segment);
+    else
+       return 0;
+}
+
+static void coff_out (long segto, void *data, unsigned long type,
+                     long segment, long wrt) 
+{
+    struct Section *s;
+    long realbytes = type & OUT_SIZMASK;
+    unsigned char mydata[4], *p;
+    int i;
+
+    if (wrt != NO_SEG) {
+       wrt = NO_SEG;                  /* continue to do _something_ */
+       error (ERR_NONFATAL, "WRT not supported by COFF output formats");
+    }
+
+    type &= OUT_TYPMASK;
+
+    /*
+     * handle absolute-assembly (structure definitions)
+     */
+    if (segto == NO_SEG) {
+       if (type != OUT_RESERVE)
+           error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
+                  " space");
+       return;
+    }
+
+    s = NULL;
+    for (i=0; i<nsects; i++)
+       if (segto == sects[i]->index) {
+           s = sects[i];
+           break;
+       }
+    if (!s) {
+       int tempint;                   /* ignored */
+       if (segto != coff_section_names (".text", 2, &tempint))
+           error (ERR_PANIC, "strange segment conditions in COFF driver");
+       else
+           s = sects[nsects-1];
+    }
+
+    if (!s->data && type != OUT_RESERVE) {
+       error(ERR_WARNING, "attempt to initialise memory in"
+             " BSS section `%s': ignored", s->name);
+       if (type == OUT_REL2ADR)
+           realbytes = 2;
+       else if (type == OUT_REL4ADR)
+           realbytes = 4;
+       s->len += realbytes;
+       return;
+    }
+
+    if (type == OUT_RESERVE) {
+       if (s->data) {
+           error(ERR_WARNING, "uninitialised space declared in"
+                 " non-BSS section `%s': zeroing", s->name);
+           coff_sect_write (s, NULL, realbytes);
+       } else
+           s->len += realbytes;
+    } else if (type == OUT_RAWDATA) {
+       if (segment != NO_SEG)
+           error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
+       coff_sect_write (s, data, realbytes);
+    } else if (type == OUT_ADDRESS) {
+       if (realbytes != 4 && (segment != NO_SEG || wrt != NO_SEG))
+           error(ERR_NONFATAL, "COFF format does not support non-32-bit"
+                 " relocations");
+       else {
+           long fix = 0;
+           if (segment != NO_SEG || wrt != NO_SEG) {
+               if (wrt != NO_SEG) {
+                   error(ERR_NONFATAL, "COFF format does not support"
+                         " WRT types");
+               } else if (segment % 2) {
+                   error(ERR_NONFATAL, "COFF format does not support"
+                         " segment base references");
+               } else
+                   fix = coff_add_reloc (s, segment, FALSE);
+           }
+           p = mydata;
+           WRITELONG (p, *(long *)data + fix);
+           coff_sect_write (s, mydata, realbytes);
+       }
+    } else if (type == OUT_REL2ADR) {
+       error(ERR_NONFATAL, "COFF format does not support 16-bit"
+             " relocations");
+    } else if (type == OUT_REL4ADR) {
+       if (segment == segto)
+           error(ERR_PANIC, "intra-segment OUT_REL4ADR");
+       else if (segment == NO_SEG && win32)
+           error(ERR_NONFATAL, "Win32 COFF does not correctly support"
+                 " relative references to absolute addresses");
+       else {
+           long fix = 0;
+           if (segment != NO_SEG && segment % 2) {
+               error(ERR_NONFATAL, "COFF format does not support"
+                     " segment base references");
+           } else
+               fix = coff_add_reloc (s, segment, TRUE);
+           p = mydata;
+           if (win32) {
+               WRITELONG (p, *(long*)data + 4 - realbytes + fix);
+           } else {
+               WRITELONG (p, *(long*)data-(realbytes + s->len) + fix);
+           }
+           coff_sect_write (s, mydata, 4L);
+       }
+    }
+}
+
+static void coff_sect_write (struct Section *sect,
+                            unsigned char *data, unsigned long len) 
+{
+    saa_wbytes (sect->data, data, len);
+    sect->len += len;
+}
+
+static int coff_directives (char *directive, char *value, int pass) 
+{
+    return 0;
+}
+
+static void coff_write (void) 
+{
+    long pos, sympos, vsize;
+    int i;
+
+    /*
+     * Work out how big the file will get. Calculate the start of
+     * the `real' symbols at the same time.
+     */
+    pos = 0x14 + 0x28 * nsects;
+    initsym = 3;                      /* two for the file, one absolute */
+    for (i=0; i<nsects; i++) {
+       if (sects[i]->data) {
+           sects[i]->pos = pos;
+           pos += sects[i]->len;
+           sects[i]->relpos = pos;
+           pos += 10 * sects[i]->nrelocs;
+       } else
+           sects[i]->pos = sects[i]->relpos = 0L;
+       initsym += 2;                  /* two for each section */
+    }
+    sympos = pos;
+
+    /*
+     * Output the COFF header.
+     */
+    fwriteshort (0x14C, coffp);               /* MACHINE_i386 */
+    fwriteshort (nsects, coffp);       /* number of sections */
+    fwritelong (time(NULL), coffp);    /* time stamp */
+    fwritelong (sympos, coffp);
+    fwritelong (nsyms + initsym, coffp);
+    fwriteshort (0, coffp);           /* no optional header */
+    /* Flags: 32-bit, no line numbers. Win32 doesn't even bother with them. */
+    fwriteshort (win32 ? 0 : 0x104, coffp);
+
+    /*
+     * Output the section headers.
+     */
+    vsize = 0L;
+    for (i=0; i<nsects; i++) {
+       coff_section_header (sects[i]->name, vsize, sects[i]->len,
+                            sects[i]->pos, sects[i]->relpos,
+                            sects[i]->nrelocs, sects[i]->flags);
+       vsize += sects[i]->len;
+    }
+
+    /*
+     * Output the sections and their relocations.
+     */
+    for (i=0; i<nsects; i++)
+       if (sects[i]->data) {
+           saa_fpwrite (sects[i]->data, coffp);
+           coff_write_relocs (sects[i]);
+       }
+
+    /*
+     * Output the symbol and string tables.
+     */
+    coff_write_symbols();
+    fwritelong (strslen+4, coffp);     /* length includes length count */
+    saa_fpwrite (strs, coffp);
+}
+
+static void coff_section_header (char *name, long vsize,
+                                long datalen, long datapos,
+                                long relpos, int nrelocs, long flags) 
+{
+    char padname[8];
+
+    memset (padname, 0, 8);
+    strncpy (padname, name, 8);
+    fwrite (padname, 8, 1, coffp);
+    fwritelong (vsize, coffp);
+    fwritelong (0L, coffp);           /* RVA/offset - we ignore */
+    fwritelong (datalen, coffp);
+    fwritelong (datapos, coffp);
+    fwritelong (relpos, coffp);
+    fwritelong (0L, coffp);           /* no line numbers - we don't do 'em */
+    fwriteshort (nrelocs, coffp);
+    fwriteshort (0, coffp);           /* again, no line numbers */
+    fwritelong (flags, coffp);
+}
+
+static void coff_write_relocs (struct Section *s) 
+{
+    struct Reloc *r;
+
+    for (r = s->head; r; r = r->next) {
+       fwritelong (r->address, coffp);
+       fwritelong (r->symbol + (r->symbase == REAL_SYMBOLS ? initsym :
+                                r->symbase == ABS_SYMBOL ? initsym-1 :
+                                r->symbase == SECT_SYMBOLS ? 2 : 0), coffp);
+       /*
+        * Strange: Microsoft's COFF documentation says 0x03 for an
+        * absolute relocation, but both Visual C++ and DJGPP agree
+        * that in fact it's 0x06. I'll use 0x06 until someone
+        * argues.
+        */
+       fwriteshort (r->relative ? 0x14 : 0x06, coffp);
+    }
+}
+
+static void coff_symbol (char *name, long strpos, long value,
+                        int section, int type, int aux) 
+{
+    char padname[8];
+
+    if (name) {
+       memset (padname, 0, 8);
+       strncpy (padname, name, 8);
+       fwrite (padname, 8, 1, coffp);
+    } else {
+       fwritelong (0L, coffp);
+       fwritelong (strpos, coffp);
+    }
+    fwritelong (value, coffp);
+    fwriteshort (section, coffp);
+    fwriteshort (0, coffp);
+    fputc (type, coffp);
+    fputc (aux, coffp);
+}
+
+static void coff_write_symbols (void)
+{
+    char filename[18];
+    unsigned long i;
+
+    /*
+     * The `.file' record, and the file name auxiliary record.
+     */
+    coff_symbol (".file", 0L, 0L, -2, 0x67, 1);
+    memset (filename, 0, 18);
+    strncpy (filename, coff_infile, 18);
+    fwrite (filename, 18, 1, coffp);
+
+    /*
+     * The section records, with their auxiliaries.
+     */
+    memset (filename, 0, 18);         /* useful zeroed buffer */
+
+    for (i = 0; i < nsects; i++) {
+       coff_symbol (sects[i]->name, 0L, 0L, i+1, 3, 1);
+       fwritelong (sects[i]->len, coffp);
+       fwriteshort (sects[i]->nrelocs, coffp);
+       fwrite (filename, 12, 1, coffp);
+    }
+
+    /*
+     * The absolute symbol, for relative-to-absolute relocations.
+     */
+    coff_symbol (".absolut", 0L, 0L, -1, 3, 0);
+
+    /*
+     * The real symbols.
+     */
+    saa_rewind (syms);
+    for (i = 0; i < nsyms; i++) {
+       struct Symbol *sym = saa_rstruct (syms);
+       coff_symbol (sym->strpos == -1 ? sym->name : NULL,
+                    sym->strpos, sym->value, sym->section,
+                    sym->is_global ? 2 : 3, 0);
+    }
+}
+
+static long coff_segbase (long segment) 
+{
+    return segment;
+}
+
+static void coff_std_filename (char *inname, char *outname, efunc error) 
+{
+    strcpy(coff_infile, inname);
+    standard_extension (inname, outname, ".o", error);
+}
+
+static void coff_win32_filename (char *inname, char *outname, efunc error) 
+{
+    strcpy(coff_infile, inname);
+    standard_extension (inname, outname, ".obj", error);
+}
+
+static char *coff_stdmac[] = {
+    "%define __SECT__ [section .text]",
+    "%macro __NASM_CDecl__ 1",
+    "%endmacro",
+    NULL
+};
+
+static int coff_set_info(enum geninfo type, char **val)
+{
+    return 0;
+}
+#endif /* defined(OF_COFF) || defined(OF_WIN32) */
+
+#ifdef OF_COFF
+
+struct ofmt of_coff = {
+    "COFF (i386) object files (e.g. DJGPP for DOS)",
+    "coff",
+    NULL,
+    null_debug_arr,
+    &null_debug_form,
+    coff_stdmac,
+    coff_std_init,
+    coff_set_info,
+    coff_out,
+    coff_deflabel,
+    coff_section_names,
+    coff_segbase,
+    coff_directives,
+    coff_std_filename,
+    coff_cleanup
+};
+
+#endif
+
+#ifdef OF_WIN32
+
+struct ofmt of_win32 = {
+    "Microsoft Win32 (i386) object files",
+    "win32",
+    NULL,
+    null_debug_arr,
+    &null_debug_form,
+    coff_stdmac,
+    coff_win32_init,
+    coff_set_info,
+    coff_out,
+    coff_deflabel,
+    coff_section_names,
+    coff_segbase,
+    coff_directives,
+    coff_win32_filename,
+    coff_cleanup
+};
+
+#endif
diff --git a/output/outdbg.c b/output/outdbg.c
new file mode 100644 (file)
index 0000000..723e372
--- /dev/null
@@ -0,0 +1,249 @@
+/* outdbg.c    output routines for the Netwide Assembler to produce
+ *             a debugging trace
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "nasm.h"
+#include "nasmlib.h"
+#include "outform.h"
+
+#ifdef OF_DBG
+
+struct Section {
+    struct Section *next;
+    long number;
+    char *name;
+} *dbgsect;
+
+FILE *dbgf;
+efunc dbgef;
+
+struct ofmt of_dbg;
+static void dbg_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
+{
+    (void) eval;
+
+    dbgf = fp;
+    dbgef = errfunc;
+    dbgsect = NULL;
+    (void) ldef;
+    fprintf(fp,"NASM Output format debug dump\n");
+    of_dbg.current_dfmt->init(&of_dbg,0,fp,errfunc);
+    
+}
+
+static void dbg_cleanup(int debuginfo)
+{
+    (void) debuginfo;
+    of_dbg.current_dfmt->cleanup();
+    while (dbgsect) {
+       struct Section *tmp = dbgsect;
+       dbgsect = dbgsect->next;
+       nasm_free (tmp->name);
+       nasm_free (tmp);
+    }
+    fclose(dbgf);
+}
+
+static long dbg_section_names (char *name, int pass, int *bits)
+{
+    int seg;
+
+    /*
+     * We must have an initial default: let's make it 16.
+     */
+    if (!name)
+       *bits = 16;
+
+    if (!name)
+       fprintf(dbgf, "section_name on init: returning %d\n",
+               seg = seg_alloc());
+    else {
+       int n = strcspn(name, " \t");
+       char *sname = nasm_strndup(name, n);
+       struct Section *s;
+
+       seg = NO_SEG;
+       for (s = dbgsect; s; s = s->next)
+           if (!strcmp(s->name, sname))
+               seg = s->number;
+       
+       if (seg == NO_SEG) {
+           s = nasm_malloc(sizeof(*s));
+           s->name = sname;
+           s->number = seg = seg_alloc();
+           s->next = dbgsect;
+           dbgsect = s;
+           fprintf(dbgf, "section_name %s (pass %d): returning %d\n",
+                   name, pass, seg);
+       }
+    }
+    return seg;
+}
+
+static void dbg_deflabel (char *name, long segment, long offset,
+                         int is_global, char *special) 
+{
+    fprintf(dbgf,"deflabel %s := %08lx:%08lx %s (%d)%s%s\n",
+           name, segment, offset,
+           is_global == 2 ? "common" : is_global ? "global" : "local",
+           is_global,
+           special ? ": " : "", special);
+}
+
+static void dbg_out (long segto, void *data, unsigned long type,
+                    long segment, long wrt) 
+{
+    long realbytes = type & OUT_SIZMASK;
+    long ldata;
+    int id;
+
+    type &= OUT_TYPMASK;
+
+    fprintf(dbgf,"out to %lx, len = %ld: ",segto,realbytes);
+
+    switch(type) {
+      case OUT_RESERVE:
+       fprintf(dbgf,"reserved.\n"); break;
+      case OUT_RAWDATA:
+       fprintf(dbgf,"raw data = ");
+       while (realbytes--) {
+           id = *(unsigned char *)data;
+           data = (char *)data + 1;
+           fprintf(dbgf,"%02x ",id);
+       }
+       fprintf(dbgf,"\n"); break;
+      case OUT_ADDRESS:
+       ldata = 0; /* placate gcc */
+       if (realbytes == 1)
+           ldata = *((char *)data);
+       else if (realbytes == 2)
+           ldata = *((short *)data);
+       else if (realbytes == 4)
+           ldata = *((long *)data);
+       fprintf(dbgf,"addr %08lx (seg %08lx, wrt %08lx)\n",ldata,
+               segment,wrt);break;
+      case OUT_REL2ADR:
+       fprintf(dbgf,"rel2adr %04x (seg %08lx)\n",(int)*(short *)data,segment);
+       break;
+      case OUT_REL4ADR:
+       fprintf(dbgf,"rel4adr %08lx (seg %08lx)\n",*(long *)data,segment);
+       break;
+      default:
+       fprintf(dbgf,"unknown\n");
+       break;
+    }
+}
+
+static long dbg_segbase(long segment) 
+{
+    return segment;
+}
+
+static int dbg_directive (char *directive, char *value, int pass) 
+{
+    fprintf(dbgf, "directive [%s] value [%s] (pass %d)\n",
+           directive, value, pass);
+    return 1;
+}
+
+static void dbg_filename (char *inname, char *outname, efunc error) 
+{
+    standard_extension (inname, outname, ".dbg", error);
+}
+
+static int dbg_set_info(enum geninfo type, char **val)
+{
+    (void) type;
+    (void) val;
+    return 0;
+}
+char *types[] = { 
+       "unknown", "label", "byte","word","dword","float","qword","tbyte" 
+};
+void dbgdbg_init(struct ofmt * of, void * id, FILE * fp, efunc error)
+{
+    (void) of;
+    (void) id;
+    (void) fp;
+    (void) error;
+    fprintf(fp,"   With debug info\n");
+}
+static void dbgdbg_cleanup(void)
+{
+}
+
+static void dbgdbg_linnum (const char *lnfname, long lineno, long segto)
+{
+    fprintf(dbgf,"dbglinenum %s(%ld) := %08lx\n",
+       lnfname,lineno,segto);
+}
+static void dbgdbg_deflabel (char *name, long segment,
+                         long offset, int is_global, char *special) 
+{
+    fprintf(dbgf,"dbglabel %s := %08lx:%08lx %s (%d)%s%s\n",
+           name,
+            segment, offset,
+           is_global == 2 ? "common" : is_global ? "global" : "local",
+           is_global,
+           special ? ": " : "", special);
+}
+static void dbgdbg_define(const char *type, const char *params)
+{
+    fprintf(dbgf,"dbgdirective [%s] value [%s]\n",type, params);
+}
+static void dbgdbg_output (int output_type, void *param)
+{
+    (void) output_type;
+    (void) param;
+}
+static void dbgdbg_typevalue(long type)
+{
+       fprintf(dbgf,"new type: %s(%lX)\n",
+           types[TYM_TYPE(type) >> 3], TYM_ELEMENTS(type) );
+}
+static struct dfmt debug_debug_form = {
+    "Trace of all info passed to debug stage",
+    "debug",
+    dbgdbg_init,
+    dbgdbg_linnum,
+    dbgdbg_deflabel,
+    dbgdbg_define,
+    dbgdbg_typevalue,
+    dbgdbg_output,
+    dbgdbg_cleanup,
+};
+
+static struct dfmt *debug_debug_arr[3] = {
+       &debug_debug_form,
+       &null_debug_form,
+       NULL
+};
+struct ofmt of_dbg = {
+    "Trace of all info passed to output stage",
+    "dbg",
+    NULL,
+    debug_debug_arr,
+    &null_debug_form,
+    NULL,
+    dbg_init,
+    dbg_set_info,
+    dbg_out,
+    dbg_deflabel,
+    dbg_section_names,
+    dbg_segbase,
+    dbg_directive,
+    dbg_filename,
+    dbg_cleanup
+};
+
+#endif /* OF_DBG */
diff --git a/output/outelf.c b/output/outelf.c
new file mode 100644 (file)
index 0000000..ddd87fe
--- /dev/null
@@ -0,0 +1,1145 @@
+/* outelf.c    output routines for the Netwide Assembler to produce
+ *             ELF32 (i386 of course) object file format
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "nasm.h"
+#include "nasmlib.h"
+#include "outform.h"
+
+#ifdef OF_ELF
+
+/*
+ * Relocation types.
+ */
+enum reloc_type {
+  R_386_32        =  1,                /* ordinary absolute relocation */
+  R_386_PC32      =  2,                /* PC-relative relocation */
+  R_386_GOT32     =  3,                /* an offset into GOT */
+  R_386_PLT32     =  4,                /* a PC-relative offset into PLT */
+  R_386_COPY      =  5,                /* ??? */
+  R_386_GLOB_DAT  =  6,                /* ??? */
+  R_386_JUMP_SLOT =  7,                /* ??? */
+  R_386_RELATIVE  =  8,                /* ??? */
+  R_386_GOTOFF    =  9,                /* an offset from GOT base */
+  R_386_GOTPC     = 10,                /* a PC-relative offset _to_ GOT */
+  /* These are GNU extensions, but useful */
+  R_386_16        = 20,                /* A 16-bit absolute relocation */
+  R_386_PC16      = 21,                /* A 16-bit PC-relative relocation */
+  R_386_8         = 22,                /* An 8-bit absolute relocation */
+  R_386_PC8       = 23         /* An 8-bit PC-relative relocation */
+};
+
+struct Reloc {
+    struct Reloc *next;
+    long address;                     /* relative to _start_ of section */
+    long symbol;                      /* ELF symbol info thingy */
+    int type;                         /* type of relocation */
+};
+
+struct Symbol {
+    long strpos;                      /* string table position of name */
+    long section;                     /* section ID of the symbol */
+    int type;                         /* symbol type */
+    long value;                               /* address, or COMMON variable align */
+    long size;                        /* size of symbol */
+    long globnum;                     /* symbol table offset if global */
+    struct Symbol *next;              /* list of globals in each section */
+    struct Symbol *nextfwd;           /* list of unresolved-size symbols */
+    char *name;                               /* used temporarily if in above list */
+};
+
+#define SHT_PROGBITS 1
+#define SHT_NOBITS 8
+
+#define SHF_WRITE 1
+#define SHF_ALLOC 2
+#define SHF_EXECINSTR 4
+
+struct Section {
+    struct SAA *data;
+    unsigned long len, size, nrelocs;
+    long index;
+    int type;                         /* SHT_PROGBITS or SHT_NOBITS */
+    int align;                        /* alignment: power of two */
+    unsigned long flags;              /* section flags */
+    char *name;
+    struct SAA *rel;
+    long rellen;
+    struct Reloc *head, **tail;
+    struct Symbol *gsyms;             /* global symbols in section */
+};
+
+#define SECT_DELTA 32
+static struct Section **sects;
+static int nsects, sectlen;
+
+#define SHSTR_DELTA 256
+static char *shstrtab;
+static int shstrtablen, shstrtabsize;
+
+static struct SAA *syms;
+static unsigned long nlocals, nglobs;
+
+static long def_seg;
+
+static struct RAA *bsym;
+
+static struct SAA *strs;
+static unsigned long strslen;
+
+static FILE *elffp;
+static efunc error;
+static evalfunc evaluate;
+
+static struct Symbol *fwds;
+
+static char elf_module[FILENAME_MAX];
+
+extern struct ofmt of_elf;
+
+#define SHN_ABS 0xFFF1
+#define SHN_COMMON 0xFFF2
+#define SHN_UNDEF 0
+
+#define SYM_SECTION 0x04
+#define SYM_GLOBAL 0x10
+#define SYM_DATA 0x01
+#define SYM_FUNCTION 0x02
+
+#define GLOBAL_TEMP_BASE 15           /* bigger than any constant sym id */
+
+#define SEG_ALIGN 16                  /* alignment of sections in file */
+#define SEG_ALIGN_1 (SEG_ALIGN-1)
+
+static const char align_str[SEG_ALIGN] = ""; /* ANSI will pad this with 0s */
+
+#define ELF_MAX_SECTIONS 16           /* really 10, but let's play safe */
+static struct ELF_SECTDATA {
+    void *data;
+    long len;
+    int is_saa;
+} *elf_sects;
+static int elf_nsect;
+static long elf_foffs;
+
+static void elf_write(void);
+static void elf_sect_write(struct Section *, unsigned char *, unsigned long);
+static void elf_section_header (int, int, int, void *, int, long,
+                               int, int, int, int);
+static void elf_write_sections (void);
+static struct SAA *elf_build_symtab (long *, long *);
+static struct SAA *elf_build_reltab (long *, struct Reloc *);
+static void add_sectname (char *, char *);
+
+/*
+ * Special section numbers which are used to define ELF special
+ * symbols, which can be used with WRT to provide PIC relocation
+ * types.
+ */
+static long elf_gotpc_sect, elf_gotoff_sect;
+static long elf_got_sect, elf_plt_sect;
+static long elf_sym_sect;
+
+static void elf_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
+{
+    elffp = fp;
+    error = errfunc;
+    evaluate = eval;
+    (void) ldef;                      /* placate optimisers */
+    sects = NULL;
+    nsects = sectlen = 0;
+    syms = saa_init((long)sizeof(struct Symbol));
+    nlocals = nglobs = 0;
+    bsym = raa_init();
+    strs = saa_init(1L);
+    saa_wbytes (strs, "\0", 1L);
+    saa_wbytes (strs, elf_module, (long)(strlen(elf_module)+1));
+    strslen = 2+strlen(elf_module);
+    shstrtab = NULL;
+    shstrtablen = shstrtabsize = 0;;
+    add_sectname ("", "");
+
+    fwds = NULL;
+
+    elf_gotpc_sect = seg_alloc();
+    ldef("..gotpc", elf_gotpc_sect+1, 0L, NULL, FALSE, FALSE, &of_elf, error);
+    elf_gotoff_sect = seg_alloc();
+    ldef("..gotoff", elf_gotoff_sect+1, 0L, NULL, FALSE, FALSE,&of_elf,error);
+    elf_got_sect = seg_alloc();
+    ldef("..got", elf_got_sect+1, 0L, NULL, FALSE, FALSE, &of_elf, error);
+    elf_plt_sect = seg_alloc();
+    ldef("..plt", elf_plt_sect+1, 0L, NULL, FALSE, FALSE, &of_elf, error);
+    elf_sym_sect = seg_alloc();
+    ldef("..sym", elf_sym_sect+1, 0L, NULL, FALSE, FALSE, &of_elf, error);
+
+    def_seg = seg_alloc();
+}
+
+static void elf_cleanup(int debuginfo) 
+{
+    struct Reloc *r;
+    int i;
+
+    (void) debuginfo;
+
+    elf_write();
+    fclose (elffp);
+    for (i=0; i<nsects; i++) {
+       if (sects[i]->type != SHT_NOBITS)
+           saa_free (sects[i]->data);
+       if (sects[i]->head)
+           saa_free (sects[i]->rel);
+       while (sects[i]->head) {
+           r = sects[i]->head;
+           sects[i]->head = sects[i]->head->next;
+           nasm_free (r);
+       }
+    }
+    nasm_free (sects);
+    saa_free (syms);
+    raa_free (bsym);
+    saa_free (strs);
+}
+
+static void add_sectname (char *firsthalf, char *secondhalf) 
+{
+    int len = strlen(firsthalf)+strlen(secondhalf);
+    while (shstrtablen + len + 1 > shstrtabsize)
+       shstrtab = nasm_realloc (shstrtab, (shstrtabsize += SHSTR_DELTA));
+    strcpy (shstrtab+shstrtablen, firsthalf);
+    strcat (shstrtab+shstrtablen, secondhalf);
+    shstrtablen += len+1;
+}
+
+static int elf_make_section (char *name, int type, int flags, int align) 
+{
+    struct Section *s;
+
+    s = nasm_malloc (sizeof(*s));
+
+    if (type != SHT_NOBITS)
+       s->data = saa_init (1L);
+    s->head = NULL;
+    s->tail = &s->head;
+    s->len = s->size = 0;
+    s->nrelocs = 0;
+    if (!strcmp(name, ".text"))
+       s->index = def_seg;
+    else
+       s->index = seg_alloc();
+    add_sectname ("", name);
+    s->name = nasm_malloc (1+strlen(name));
+    strcpy (s->name, name);
+    s->type = type;
+    s->flags = flags;
+    s->align = align;
+    s->gsyms = NULL;
+
+    if (nsects >= sectlen)
+       sects = nasm_realloc (sects, (sectlen += SECT_DELTA)*sizeof(*sects));
+    sects[nsects++] = s;
+
+    return nsects-1;
+}
+
+static long elf_section_names (char *name, int pass, int *bits) 
+{
+    char *p;
+    int flags_and, flags_or, type, align, i;
+
+    /*
+     * Default is 32 bits.
+     */
+    if (!name) {
+       *bits = 32;
+       return def_seg;
+    }
+
+    p = name;
+    while (*p && !isspace(*p)) p++;
+    if (*p) *p++ = '\0';
+    flags_and = flags_or = type = align = 0;
+
+    while (*p && isspace(*p)) p++;
+    while (*p) {
+       char *q = p;
+       while (*p && !isspace(*p)) p++;
+       if (*p) *p++ = '\0';
+       while (*p && isspace(*p)) p++;
+       
+       if (!nasm_strnicmp(q, "align=", 6)) {
+           align = atoi(q+6);
+           if (align == 0)
+               align = 1;
+           if ( (align-1) & align ) {   /* means it's not a power of two */
+               error (ERR_NONFATAL, "section alignment %d is not"
+                      " a power of two", align);
+               align = 1;
+           }
+       } else if (!nasm_stricmp(q, "alloc")) {
+           flags_and |= SHF_ALLOC;
+           flags_or |= SHF_ALLOC;
+       } else if (!nasm_stricmp(q, "noalloc")) {
+           flags_and |= SHF_ALLOC;
+           flags_or &= ~SHF_ALLOC;
+       } else if (!nasm_stricmp(q, "exec")) {
+           flags_and |= SHF_EXECINSTR;
+           flags_or |= SHF_EXECINSTR;
+       } else if (!nasm_stricmp(q, "noexec")) {
+           flags_and |= SHF_EXECINSTR;
+           flags_or &= ~SHF_EXECINSTR;
+       } else if (!nasm_stricmp(q, "write")) {
+           flags_and |= SHF_WRITE;
+           flags_or |= SHF_WRITE;
+       } else if (!nasm_stricmp(q, "nowrite")) {
+           flags_and |= SHF_WRITE;
+           flags_or &= ~SHF_WRITE;
+       } else if (!nasm_stricmp(q, "progbits")) {
+           type = SHT_PROGBITS;
+       } else if (!nasm_stricmp(q, "nobits")) {
+           type = SHT_NOBITS;
+       }
+    }
+
+    if (!strcmp(name, ".comment") ||
+       !strcmp(name, ".shstrtab") ||
+       !strcmp(name, ".symtab") ||
+       !strcmp(name, ".strtab")) {
+       error (ERR_NONFATAL, "attempt to redefine reserved section"
+              "name `%s'", name);
+       return NO_SEG;
+    }
+
+    for (i=0; i<nsects; i++)
+       if (!strcmp(name, sects[i]->name))
+           break;
+    if (i == nsects) {
+       if (!strcmp(name, ".text"))
+           i = elf_make_section (name, SHT_PROGBITS,
+                                 SHF_ALLOC | SHF_EXECINSTR, 16);
+       else if (!strcmp(name, ".data"))
+           i = elf_make_section (name, SHT_PROGBITS,
+                                 SHF_ALLOC | SHF_WRITE, 4);
+       else if (!strcmp(name, ".bss"))
+           i = elf_make_section (name, SHT_NOBITS,
+                                 SHF_ALLOC | SHF_WRITE, 4);
+       else
+           i = elf_make_section (name, SHT_PROGBITS, SHF_ALLOC, 1);
+       if (type)
+           sects[i]->type = type;
+       if (align)
+           sects[i]->align = align;
+       sects[i]->flags &= ~flags_and;
+       sects[i]->flags |= flags_or;
+    } else if (pass == 1) {
+       if (type || align || flags_and)
+           error (ERR_WARNING, "section attributes ignored on"
+                  " redeclaration of section `%s'", name);
+    }
+
+    return sects[i]->index;
+}
+
+static void elf_deflabel (char *name, long segment, long offset,
+                          int is_global, char *special) 
+{
+    int pos = strslen;
+    struct Symbol *sym;
+    int special_used = FALSE;
+
+#if defined(DEBUG) && DEBUG>2
+fprintf(stderr, " elf_deflabel: %s, seg=%ld, off=%ld, is_global=%d, %s\n",
+      name, segment, offset, is_global, special);
+#endif
+    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
+       /*
+        * This is a NASM special symbol. We never allow it into
+        * the ELF symbol table, even if it's a valid one. If it
+        * _isn't_ a valid one, we should barf immediately.
+        */
+       if (strcmp(name, "..gotpc") && strcmp(name, "..gotoff") &&
+           strcmp(name, "..got") && strcmp(name, "..plt") &&
+           strcmp(name, "..sym"))
+           error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
+       return;
+    }
+
+    if (is_global == 3) {
+       struct Symbol **s;
+       /*
+        * Fix up a forward-reference symbol size from the first
+        * pass.
+        */
+       for (s = &fwds; *s; s = &(*s)->nextfwd)
+           if (!strcmp((*s)->name, name)) {
+               struct tokenval tokval;
+               expr *e;
+               char *p = special;
+
+               while (*p && !isspace(*p)) p++;
+               while (*p && isspace(*p)) p++;
+               stdscan_reset();
+               stdscan_bufptr = p;
+               tokval.t_type = TOKEN_INVALID;
+               e = evaluate(stdscan, NULL, &tokval, NULL, 1, error, NULL);
+               if (e) {
+                   if (!is_simple(e))
+                       error (ERR_NONFATAL, "cannot use relocatable"
+                              " expression as symbol size");
+                   else
+                       (*s)->size = reloc_value(e);
+               }
+
+               /*
+                * Remove it from the list of unresolved sizes.
+                */
+               nasm_free ((*s)->name);
+               *s = (*s)->nextfwd;
+               return;
+           }
+       return;                        /* it wasn't an important one */
+    }
+
+    saa_wbytes (strs, name, (long)(1+strlen(name)));
+    strslen += 1+strlen(name);
+
+    sym = saa_wstruct (syms);
+
+    sym->strpos = pos;
+    sym->type = is_global ? SYM_GLOBAL : 0;
+    sym->size = 0;
+    if (segment == NO_SEG)
+       sym->section = SHN_ABS;
+    else {
+       int i;
+       sym->section = SHN_UNDEF;
+       if (nsects == 0 && segment == def_seg) {
+           int tempint;
+           if (segment != elf_section_names (".text", 2, &tempint))
+               error (ERR_PANIC, "strange segment conditions in ELF driver");
+           sym->section = nsects;
+       } else {
+           for (i=0; i<nsects; i++)
+               if (segment == sects[i]->index) {
+                   sym->section = i+1;
+                   break;
+               }
+       }
+    }
+
+    if (is_global == 2) {
+       sym->size = offset;
+       sym->value = 0;
+       sym->section = SHN_COMMON;
+       /*
+        * We have a common variable. Check the special text to see
+        * if it's a valid number and power of two; if so, store it
+        * as the alignment for the common variable.
+        */
+       if (special) {
+           int err;
+           sym->value = readnum (special, &err);
+           if (err)
+               error(ERR_NONFATAL, "alignment constraint `%s' is not a"
+                     " valid number", special);
+           else if ( (sym->value | (sym->value-1)) != 2*sym->value - 1)
+               error(ERR_NONFATAL, "alignment constraint `%s' is not a"
+                     " power of two", special);
+       }
+       special_used = TRUE;
+    } else
+       sym->value = (sym->section == SHN_UNDEF ? 0 : offset);
+
+    if (sym->type == SYM_GLOBAL) {
+       /*
+        * There's a problem here that needs fixing. 
+        * If sym->section == SHN_ABS, then the first line of the
+        * else section causes a core dump, because its a reference
+        * beyond the end of the section array.
+        * This behaviour is exhibited by this code:
+        *     GLOBAL crash_nasm
+        *     crash_nasm equ 0
+        *
+        * I'm not sure how to procede, because I haven't got the
+        * first clue about how ELF works, so I don't know what to
+        * do with it. Furthermore, I'm not sure what the rest of this
+        * section of code does. Help?
+        *
+        * For now, I'll see if doing absolutely nothing with it will
+        * work...
+        */
+       if (sym->section == SHN_UNDEF || sym->section == SHN_COMMON)
+       {
+           bsym = raa_write (bsym, segment, nglobs);
+       }
+       else if (sym->section != SHN_ABS) 
+       {
+           /*
+            * This is a global symbol; so we must add it to the linked
+            * list of global symbols in its section. We'll push it on
+            * the beginning of the list, because it doesn't matter
+            * much which end we put it on and it's easier like this.
+            *
+            * In addition, we check the special text for symbol
+            * type and size information.
+            */
+           sym->next = sects[sym->section-1]->gsyms;
+           sects[sym->section-1]->gsyms = sym;
+
+           if (special) {
+               int n = strcspn(special, " ");
+
+               if (!nasm_strnicmp(special, "function", n))
+                   sym->type |= SYM_FUNCTION;
+               else if (!nasm_strnicmp(special, "data", n) ||
+                        !nasm_strnicmp(special, "object", n))
+                   sym->type |= SYM_DATA;
+               else
+                   error(ERR_NONFATAL, "unrecognised symbol type `%.*s'",
+                         n, special);
+               if (special[n]) {
+                   struct tokenval tokval;
+                   expr *e;
+                   int fwd = FALSE;
+                   char *saveme=stdscan_bufptr;   /* bugfix? fbk 8/10/00 */
+
+                   while (special[n] && isspace(special[n]))
+                       n++;
+                   /*
+                    * We have a size expression; attempt to
+                    * evaluate it.
+                    */
+                   stdscan_reset();
+                   stdscan_bufptr = special+n;
+                   tokval.t_type = TOKEN_INVALID;
+                   e = evaluate(stdscan, NULL, &tokval, &fwd, 0, error, NULL);
+                   if (fwd) {
+                       sym->nextfwd = fwds;
+                       fwds = sym;
+                       sym->name = nasm_strdup(name);
+                   } else if (e) {
+                       if (!is_simple(e))
+                           error (ERR_NONFATAL, "cannot use relocatable"
+                                  " expression as symbol size");
+                       else
+                           sym->size = reloc_value(e);
+                   }
+                   stdscan_bufptr=saveme;    /* bugfix? fbk 8/10/00 */
+               }
+               special_used = TRUE;
+           }
+       }
+       sym->globnum = nglobs;
+       nglobs++;
+    } else
+       nlocals++;
+
+    if (special && !special_used)
+       error(ERR_NONFATAL, "no special symbol features supported here");
+}
+
+static void elf_add_reloc (struct Section *sect, long segment,
+                          int type) 
+{
+    struct Reloc *r;
+
+    r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
+    sect->tail = &r->next;
+    r->next = NULL;
+
+    r->address = sect->len;
+    if (segment == NO_SEG)
+       r->symbol = 2;
+    else {
+       int i;
+       r->symbol = 0;
+       for (i=0; i<nsects; i++)
+           if (segment == sects[i]->index)
+               r->symbol = i+3;
+       if (!r->symbol)
+           r->symbol = GLOBAL_TEMP_BASE + raa_read(bsym, segment);
+    }
+    r->type = type;
+
+    sect->nrelocs++;
+}
+
+/*
+ * This routine deals with ..got and ..sym relocations: the more
+ * complicated kinds. In shared-library writing, some relocations
+ * with respect to global symbols must refer to the precise symbol
+ * rather than referring to an offset from the base of the section
+ * _containing_ the symbol. Such relocations call to this routine,
+ * which searches the symbol list for the symbol in question.
+ *
+ * R_386_GOT32 references require the _exact_ symbol address to be
+ * used; R_386_32 references can be at an offset from the symbol.
+ * The boolean argument `exact' tells us this.
+ *
+ * Return value is the adjusted value of `addr', having become an
+ * offset from the symbol rather than the section. Should always be
+ * zero when returning from an exact call.
+ *
+ * Limitation: if you define two symbols at the same place,
+ * confusion will occur.
+ *
+ * Inefficiency: we search, currently, using a linked list which
+ * isn't even necessarily sorted.
+ */
+static long elf_add_gsym_reloc (struct Section *sect,
+                               long segment, long offset,
+                               int type, int exact) 
+{
+    struct Reloc *r;
+    struct Section *s;
+    struct Symbol *sym, *sm;
+    int i;
+
+    /*
+     * First look up the segment/offset pair and find a global
+     * symbol corresponding to it. If it's not one of our segments,
+     * then it must be an external symbol, in which case we're fine
+     * doing a normal elf_add_reloc after first sanity-checking
+     * that the offset from the symbol is zero.
+     */
+    s = NULL;
+    for (i=0; i<nsects; i++)
+       if (segment == sects[i]->index) {
+           s = sects[i];
+           break;
+       }
+    if (!s) {
+       if (exact && offset != 0)
+           error (ERR_NONFATAL, "unable to find a suitable global symbol"
+                  " for this reference");
+       else
+           elf_add_reloc (sect, segment, type);
+       return offset;
+    }
+
+    if (exact) {
+       /*
+        * Find a symbol pointing _exactly_ at this one.
+        */
+       for (sym = s->gsyms; sym; sym = sym->next)
+           if (sym->value == offset)
+               break;
+    } else {
+       /*
+        * Find the nearest symbol below this one.
+        */
+       sym = NULL;
+       for (sm = s->gsyms; sm; sm = sm->next)
+           if (sm->value <= offset && (!sym || sm->value > sym->value))
+               sym = sm;
+    }
+    if (!sym && exact) {
+       error (ERR_NONFATAL, "unable to find a suitable global symbol"
+              " for this reference");
+       return 0;
+    }
+
+    r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
+    sect->tail = &r->next;
+    r->next = NULL;
+
+    r->address = sect->len;
+    r->symbol = GLOBAL_TEMP_BASE + sym->globnum;
+    r->type = type;
+
+    sect->nrelocs++;
+
+    return offset - sym->value;
+}
+
+static void elf_out (long segto, void *data, unsigned long type,
+                     long segment, long wrt) 
+{
+    struct Section *s;
+    long realbytes = type & OUT_SIZMASK;
+    long addr;
+    unsigned char mydata[4], *p;
+    int i;
+
+    type &= OUT_TYPMASK;
+
+    /*
+     * handle absolute-assembly (structure definitions)
+     */
+    if (segto == NO_SEG) {
+       if (type != OUT_RESERVE)
+           error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
+                  " space");
+       return;
+    }
+
+    s = NULL;
+    for (i=0; i<nsects; i++)
+       if (segto == sects[i]->index) {
+           s = sects[i];
+           break;
+       }
+    if (!s) {
+       int tempint;                   /* ignored */
+       if (segto != elf_section_names (".text", 2, &tempint))
+           error (ERR_PANIC, "strange segment conditions in ELF driver");
+       else
+           s = sects[nsects-1];
+    }
+
+    if (s->type == SHT_NOBITS && type != OUT_RESERVE) {
+       error(ERR_WARNING, "attempt to initialise memory in"
+             " BSS section `%s': ignored", s->name);
+       if (type == OUT_REL2ADR)
+           realbytes = 2;
+       else if (type == OUT_REL4ADR)
+           realbytes = 4;
+       s->len += realbytes;
+       return;
+    }
+
+    if (type == OUT_RESERVE) {
+       if (s->type == SHT_PROGBITS) {
+           error(ERR_WARNING, "uninitialised space declared in"
+                 " non-BSS section `%s': zeroing", s->name);
+           elf_sect_write (s, NULL, realbytes);
+       } else
+           s->len += realbytes;
+    } else if (type == OUT_RAWDATA) {
+       if (segment != NO_SEG)
+           error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
+       elf_sect_write (s, data, realbytes);
+    } else if (type == OUT_ADDRESS) {
+        int gnu16 = 0;
+       addr = *(long *)data;
+       if (segment != NO_SEG) {
+           if (segment % 2) {
+               error(ERR_NONFATAL, "ELF format does not support"
+                     " segment base references");
+           } else {
+               if (wrt == NO_SEG) {
+                 if ( realbytes == 2 ) {
+                   gnu16 = 1;
+                   elf_add_reloc (s, segment, R_386_16);
+                 } else {
+                   elf_add_reloc (s, segment, R_386_32);
+                 }
+               } else if (wrt == elf_gotpc_sect+1) {
+                   /*
+                    * The user will supply GOT relative to $$. ELF
+                    * will let us have GOT relative to $. So we
+                    * need to fix up the data item by $-$$.
+                    */
+                   addr += s->len;
+                   elf_add_reloc (s, segment, R_386_GOTPC);
+               } else if (wrt == elf_gotoff_sect+1) {
+                   elf_add_reloc (s, segment, R_386_GOTOFF);
+               } else if (wrt == elf_got_sect+1) {
+                   addr = elf_add_gsym_reloc (s, segment, addr,
+                                              R_386_GOT32, TRUE);
+               } else if (wrt == elf_sym_sect+1) {
+                 if ( realbytes == 2 ) {
+                   gnu16 = 1;
+                   addr = elf_add_gsym_reloc (s, segment, addr,
+                                              R_386_16, FALSE);
+                 } else {
+                   addr = elf_add_gsym_reloc (s, segment, addr,
+                                              R_386_32, FALSE);
+                 }
+               } else if (wrt == elf_plt_sect+1) {
+                   error(ERR_NONFATAL, "ELF format cannot produce non-PC-"
+                         "relative PLT references");
+               } else {
+                   error (ERR_NONFATAL, "ELF format does not support this"
+                          " use of WRT");
+                   wrt = NO_SEG;      /* we can at least _try_ to continue */
+               }
+           }
+       }
+       p = mydata;
+       if (gnu16) {
+           error(ERR_WARNING|ERR_WARN_GNUELF,
+                 "16-bit relocations in ELF is a GNU extension");
+         WRITESHORT (p, addr);
+       } else {
+         if (realbytes != 4 && segment != NO_SEG) {
+           error (ERR_NONFATAL, "Unsupported non-32-bit ELF relocation");
+         }
+         WRITELONG (p, addr);
+       }
+       elf_sect_write (s, mydata, realbytes);
+    } else if (type == OUT_REL2ADR) {
+       if (segment == segto)
+           error(ERR_PANIC, "intra-segment OUT_REL2ADR");
+       if (segment != NO_SEG && segment % 2) {
+           error(ERR_NONFATAL, "ELF format does not support"
+                 " segment base references");
+       } else {
+         if (wrt == NO_SEG) {
+               error (ERR_WARNING|ERR_WARN_GNUELF,
+                      "16-bit relocations in ELF is a GNU extension");
+               elf_add_reloc (s, segment, R_386_PC16);
+           } else {
+               error (ERR_NONFATAL, "Unsupported non-32-bit ELF relocation");
+           }
+       }
+       p = mydata;
+       WRITESHORT (p, *(long*)data - realbytes);
+       elf_sect_write (s, mydata, 2L);
+    } else if (type == OUT_REL4ADR) {
+       if (segment == segto)
+           error(ERR_PANIC, "intra-segment OUT_REL4ADR");
+       if (segment != NO_SEG && segment % 2) {
+           error(ERR_NONFATAL, "ELF format does not support"
+                 " segment base references");
+       } else {
+           if (wrt == NO_SEG) {
+               elf_add_reloc (s, segment, R_386_PC32);
+           } else if (wrt == elf_plt_sect+1) {
+               elf_add_reloc (s, segment, R_386_PLT32);
+           } else if (wrt == elf_gotpc_sect+1 ||
+                      wrt == elf_gotoff_sect+1 ||
+                      wrt == elf_got_sect+1) {
+               error(ERR_NONFATAL, "ELF format cannot produce PC-"
+                     "relative GOT references");
+           } else {
+               error (ERR_NONFATAL, "ELF format does not support this"
+                      " use of WRT");
+               wrt = NO_SEG;      /* we can at least _try_ to continue */
+           }
+       }
+       p = mydata;
+       WRITELONG (p, *(long*)data - realbytes);
+       elf_sect_write (s, mydata, 4L);
+    }
+}
+
+static void elf_write(void) 
+{
+    int nsections, align;
+    char *p;
+    int commlen;
+    char comment[64];
+    int i;
+
+    struct SAA *symtab;
+    long symtablen, symtablocal;
+
+    /*
+     * Work out how many sections we will have. We have SHN_UNDEF,
+     * then the flexible user sections, then the four fixed
+     * sections `.comment', `.shstrtab', `.symtab' and `.strtab',
+     * then optionally relocation sections for the user sections.
+     */
+    nsections = 5;                    /* SHN_UNDEF and the fixed ones */
+    add_sectname ("", ".comment");
+    add_sectname ("", ".shstrtab");
+    add_sectname ("", ".symtab");
+    add_sectname ("", ".strtab");
+    for (i=0; i<nsects; i++) {
+       nsections++;                   /* for the section itself */
+       if (sects[i]->head) {
+           nsections++;               /* for its relocations */
+           add_sectname (".rel", sects[i]->name);
+       }
+    }
+
+    /*
+     * Do the comment.
+     */
+    *comment = '\0';
+    commlen = 2+sprintf(comment+1, "The Netwide Assembler %s", NASM_VER);
+
+    /*
+     * Output the ELF header.
+     */
+    fwrite ("\177ELF\1\1\1\0\0\0\0\0\0\0\0\0", 16, 1, elffp);
+    fwriteshort (1, elffp);           /* ET_REL relocatable file */
+    fwriteshort (3, elffp);           /* EM_386 processor ID */
+    fwritelong (1L, elffp);           /* EV_CURRENT file format version */
+    fwritelong (0L, elffp);           /* no entry point */
+    fwritelong (0L, elffp);           /* no program header table */
+    fwritelong (0x40L, elffp);        /* section headers straight after
+                                       * ELF header plus alignment */
+    fwritelong (0L, elffp);           /* 386 defines no special flags */
+    fwriteshort (0x34, elffp);        /* size of ELF header */
+    fwriteshort (0, elffp);           /* no program header table, again */
+    fwriteshort (0, elffp);           /* still no program header table */
+    fwriteshort (0x28, elffp);        /* size of section header */
+    fwriteshort (nsections, elffp);    /* number of sections */
+    fwriteshort (nsects+2, elffp);     /* string table section index for
+                                       * section header table */
+    fwritelong (0L, elffp);           /* align to 0x40 bytes */
+    fwritelong (0L, elffp);
+    fwritelong (0L, elffp);
+
+    /*
+     * Build the symbol table and relocation tables.
+     */
+    symtab = elf_build_symtab (&symtablen, &symtablocal);
+    for (i=0; i<nsects; i++)
+       if (sects[i]->head)
+           sects[i]->rel = elf_build_reltab (&sects[i]->rellen,
+                                             sects[i]->head);
+
+    /*
+     * Now output the section header table.
+     */
+
+    elf_foffs = 0x40 + 0x28 * nsections;
+    align = ((elf_foffs+SEG_ALIGN_1) & ~SEG_ALIGN_1) - elf_foffs;
+    elf_foffs += align;
+    elf_nsect = 0;
+    elf_sects = nasm_malloc(sizeof(*elf_sects) * (2 * nsects + 10));
+
+    elf_section_header (0, 0, 0, NULL, FALSE, 0L, 0, 0, 0, 0); /* SHN_UNDEF */
+    p = shstrtab+1;
+    for (i=0; i<nsects; i++) {
+       elf_section_header (p - shstrtab, sects[i]->type, sects[i]->flags,
+                           (sects[i]->type == SHT_PROGBITS ?
+                            sects[i]->data : NULL), TRUE,
+                           sects[i]->len, 0, 0, sects[i]->align, 0);
+       p += strlen(p)+1;
+    }
+    elf_section_header (p - shstrtab, 1, 0, comment, FALSE,
+                       (long)commlen, 0, 0, 1, 0);/* .comment */
+    p += strlen(p)+1;
+    elf_section_header (p - shstrtab, 3, 0, shstrtab, FALSE,
+                       (long)shstrtablen, 0, 0, 1, 0);/* .shstrtab */
+    p += strlen(p)+1;
+    elf_section_header (p - shstrtab, 2, 0, symtab, TRUE,
+                       symtablen, nsects+4, symtablocal, 4, 16);/* .symtab */
+    p += strlen(p)+1;
+    elf_section_header (p - shstrtab, 3, 0, strs, TRUE,
+                       strslen, 0, 0, 1, 0);       /* .strtab */
+    for (i=0; i<nsects; i++) if (sects[i]->head) {
+       p += strlen(p)+1;
+       elf_section_header (p - shstrtab, 9, 0, sects[i]->rel, TRUE,
+                           sects[i]->rellen, nsects+3, i+1, 4, 8);
+    }
+
+    fwrite (align_str, align, 1, elffp);
+
+    /*
+     * Now output the sections.
+     */
+    elf_write_sections();
+
+    nasm_free (elf_sects);
+    saa_free (symtab);
+}
+
+static struct SAA *elf_build_symtab (long *len, long *local) 
+{
+    struct SAA *s = saa_init(1L);
+    struct Symbol *sym;
+    unsigned char entry[16], *p;
+    int i;
+
+    *len = *local = 0;
+
+    /*
+     * First, an all-zeros entry, required by the ELF spec.
+     */
+    saa_wbytes (s, NULL, 16L);        /* null symbol table entry */
+    *len += 16;
+    (*local)++;
+
+    /*
+     * Next, an entry for the file name.
+     */
+    p = entry;
+    WRITELONG (p, 1);                 /* we know it's 1st thing in strtab */
+    WRITELONG (p, 0);                 /* no value */
+    WRITELONG (p, 0);                 /* no size either */
+    WRITESHORT (p, 4);                /* type FILE */
+    WRITESHORT (p, SHN_ABS);
+    saa_wbytes (s, entry, 16L);
+    *len += 16;
+    (*local)++;
+
+    /*
+     * Now some standard symbols defining the segments, for relocation
+     * purposes.
+     */
+    for (i = 1; i <= nsects+1; i++) {
+       p = entry;
+       WRITELONG (p, 0);              /* no symbol name */
+       WRITELONG (p, 0);              /* offset zero */
+       WRITELONG (p, 0);              /* size zero */
+       WRITESHORT (p, 3);             /* local section-type thing */
+       WRITESHORT (p, (i==1 ? SHN_ABS : i-1));   /* the section id */
+       saa_wbytes (s, entry, 16L);
+       *len += 16;
+       (*local)++;
+    }
+
+    /*
+     * Now the other local symbols.
+     */
+    saa_rewind (syms);
+    while ( (sym = saa_rstruct (syms)) ) {
+       if (sym->type & SYM_GLOBAL)
+           continue;
+       p = entry;
+       WRITELONG (p, sym->strpos);
+       WRITELONG (p, sym->value);
+       WRITELONG (p, sym->size);
+       WRITESHORT (p, sym->type);     /* local non-typed thing */
+       WRITESHORT (p, sym->section);
+       saa_wbytes (s, entry, 16L);
+        *len += 16;
+       (*local)++;
+    }
+
+    /*
+     * Now the global symbols.
+     */
+    saa_rewind (syms);
+    while ( (sym = saa_rstruct (syms)) ) {
+       if (!(sym->type & SYM_GLOBAL))
+           continue;
+       p = entry;
+       WRITELONG (p, sym->strpos);
+       WRITELONG (p, sym->value);
+       WRITELONG (p, sym->size);
+       WRITESHORT (p, sym->type);     /* global non-typed thing */
+       WRITESHORT (p, sym->section);
+       saa_wbytes (s, entry, 16L);
+       *len += 16;
+    }
+
+    return s;
+}
+
+static struct SAA *elf_build_reltab (long *len, struct Reloc *r) {
+    struct SAA *s;
+    unsigned char *p, entry[8];
+
+    if (!r)
+       return NULL;
+
+    s = saa_init(1L);
+    *len = 0;
+
+    while (r) {
+       long sym = r->symbol;
+
+       if (sym >= GLOBAL_TEMP_BASE)
+           sym += -GLOBAL_TEMP_BASE + (nsects+3) + nlocals;
+
+       p = entry;
+       WRITELONG (p, r->address);
+       WRITELONG (p, (sym << 8) + r->type);
+       saa_wbytes (s, entry, 8L);
+       *len += 8;
+
+       r = r->next;
+    }
+
+    return s;
+}
+
+static void elf_section_header (int name, int type, int flags,
+                               void *data, int is_saa, long datalen,
+                               int link, int info, int align, int eltsize) 
+{
+    elf_sects[elf_nsect].data = data;
+    elf_sects[elf_nsect].len = datalen;
+    elf_sects[elf_nsect].is_saa = is_saa;
+    elf_nsect++;
+
+    fwritelong ((long)name, elffp);
+    fwritelong ((long)type, elffp);
+    fwritelong ((long)flags, elffp);
+    fwritelong (0L, elffp);           /* no address, ever, in object files */
+    fwritelong (type == 0 ? 0L : elf_foffs, elffp);
+    fwritelong (datalen, elffp);
+    if (data)
+       elf_foffs += (datalen+SEG_ALIGN_1) & ~SEG_ALIGN_1;
+    fwritelong ((long)link, elffp);
+    fwritelong ((long)info, elffp);
+    fwritelong ((long)align, elffp);
+    fwritelong ((long)eltsize, elffp);
+}
+
+static void elf_write_sections (void) 
+{
+    int i;
+    for (i = 0; i < elf_nsect; i++)
+       if (elf_sects[i].data) {
+           long len = elf_sects[i].len;
+           long reallen = (len+SEG_ALIGN_1) & ~SEG_ALIGN_1;
+           long align = reallen - len;
+           if (elf_sects[i].is_saa)
+               saa_fpwrite (elf_sects[i].data, elffp);
+           else
+               fwrite (elf_sects[i].data, len, 1, elffp);
+           fwrite (align_str, align, 1, elffp);
+       }
+}
+
+static void elf_sect_write (struct Section *sect,
+                            unsigned char *data, unsigned long len) 
+{
+    saa_wbytes (sect->data, data, len);
+    sect->len += len;
+}
+
+static long elf_segbase (long segment) 
+{
+    return segment;
+}
+
+static int elf_directive (char *directive, char *value, int pass) 
+{
+    return 0;
+}
+
+static void elf_filename (char *inname, char *outname, efunc error) 
+{
+    strcpy(elf_module, inname);
+    standard_extension (inname, outname, ".o", error);
+}
+
+static char *elf_stdmac[] = {
+    "%define __SECT__ [section .text]",
+    "%macro __NASM_CDecl__ 1",
+    "%define $_%1 $%1",
+    "%endmacro",
+    NULL
+};
+static int elf_set_info(enum geninfo type, char **val)
+{
+    return 0;
+}
+
+struct ofmt of_elf = {
+    "ELF32 (i386) object files (e.g. Linux)",
+    "elf",
+    NULL,
+    null_debug_arr,
+    &null_debug_form,
+    elf_stdmac,
+    elf_init,
+    elf_set_info,
+    elf_out,
+    elf_deflabel,
+    elf_section_names,
+    elf_segbase,
+    elf_directive,
+    elf_filename,
+    elf_cleanup
+};
+
+#endif /* OF_ELF */
diff --git a/output/outieee.c b/output/outieee.c
new file mode 100644 (file)
index 0000000..9784e79
--- /dev/null
@@ -0,0 +1,1461 @@
+/* outieee.c   output routines for the Netwide Assembler to produce
+ *             IEEE-std object files
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+/* notes: I have tried to make this correspond to the IEEE version
+ * of the standard, specifically the primary ASCII version.  It should
+ * be trivial to create the binary version given this source (which is
+ * one of MANY things that have to be done to make this correspond to
+ * the hp-microtek version of the standard).
+ *
+ * 16-bit support is assumed to use 24-bit addresses
+ * The linker can sort out segmentation-specific stuff
+ * if it keeps track of externals
+ * in terms of being relative to section bases
+ *
+ * A non-standard variable type, the 'Yn' variable, has been introduced.
+ * Basically it is a reference to extern 'n'- denoting the low limit
+ * (L-variable) of the section that extern 'n' is defined in.  Like the
+ * x variable, there may be no explicit assignment to it, it is derived
+ * from the public definition corresponding to the extern name.  This
+ * is required because the one thing the mufom guys forgot to do well was
+ * take into account segmented architectures.
+ *
+ * I use comment classes for various things and these are undefined by
+ * the standard.
+ *
+ * Debug info should be considered totally non-standard (local labels are
+ * standard but linenum records are not covered by the standard.
+ * Type defs have the standard format but absolute meanings for ordinal
+ * types are not covered by the standard.)
+ *
+ * David Lindauer, LADsoft
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <stdarg.h>  /* Note: we need the ANSI version of stdarg.h */
+#include <ctype.h>
+
+#include "nasm.h"
+#include "nasmlib.h"
+#include "outform.h"
+
+#ifdef OF_IEEE
+
+#define ARRAY_BOT 0x1
+
+static char ieee_infile[FILENAME_MAX];
+static int ieee_uppercase;
+
+static efunc error;
+static ldfunc deflabel;
+static FILE *ofp;
+static int any_segs;
+static int arrindex;
+
+#define HUNKSIZE 1024                 /* Size of the data hunk */
+#define EXT_BLKSIZ 512
+#define LDPERLINE 32                   /* bytes per line in output */
+
+struct ieeeSection;
+
+struct LineNumber {
+    struct LineNumber *next;
+    struct ieeeSection *segment;
+    long offset;
+    long lineno;
+};
+
+static struct FileName {
+    struct FileName *next;
+    char *name;
+    long index;
+} *fnhead, **fntail;
+
+static struct Array {
+    struct Array *next;
+    unsigned size;
+    int basetype;
+} *arrhead, **arrtail;
+
+static struct ieeePublic {
+    struct ieeePublic *next;
+    char *name;
+    long offset;
+    long segment;                     /* only if it's far-absolute */
+    long index;
+    int type;                          /* for debug purposes */        
+} *fpubhead, **fpubtail, *last_defined;
+
+static struct ieeeExternal {
+    struct ieeeExternal *next;
+    char *name;
+    long commonsize;
+} *exthead, **exttail;
+
+static int externals;
+
+static struct ExtBack {
+    struct ExtBack *next;
+    int index[EXT_BLKSIZ];
+} *ebhead, **ebtail;
+
+/* NOTE: the first segment MUST be the lineno segment */
+static struct ieeeSection {
+    struct ieeeObjData *data,*datacurr;
+    struct ieeeSection *next;
+    struct ieeeFixupp *fptr, * flptr;
+    long index;                               /* the NASM segment id */
+    long ieee_index;                  /* the OBJ-file segment index */
+    long currentpos;
+    long align;                               /* can be SEG_ABS + absolute addr */
+    long startpos;
+    enum {
+       CMB_PRIVATE = 0,
+       CMB_PUBLIC = 2,
+       CMB_COMMON = 6
+    } combine;
+    long use32;                               /* is this segment 32-bit? */
+    struct ieeePublic *pubhead, **pubtail, *lochead, **loctail;
+    char *name;
+} *seghead, **segtail, *ieee_seg_needs_update;
+
+struct ieeeObjData {
+    struct ieeeObjData *next;
+    unsigned char data[HUNKSIZE];
+};
+
+struct ieeeFixupp {
+    struct ieeeFixupp *next;
+    enum { 
+       FT_SEG = 0,
+       FT_REL = 1,
+       FT_OFS = 2,
+       FT_EXT = 3,
+       FT_WRT = 4,
+       FT_EXTREL = 5,
+       FT_EXTWRT = 6,
+       FT_EXTSEG = 7
+    } ftype;
+    short size;
+    long id1;
+    long id2;
+    long offset;
+    long addend;
+};
+               
+static long ieee_entry_seg, ieee_entry_ofs;
+static int checksum;
+
+extern struct ofmt of_ieee;
+
+static void ieee_data_new(struct ieeeSection *);
+static void ieee_write_fixup (long, long, struct ieeeSection *,
+                               int, unsigned long, long);
+static void ieee_install_fixup(struct ieeeSection *, struct ieeeFixupp *);
+static long ieee_segment (char *, int, int *);
+static void ieee_write_file(int debuginfo);
+static void ieee_write_byte(struct ieeeSection *, int);
+static void ieee_write_word(struct ieeeSection *, int);
+static void ieee_write_dword(struct ieeeSection *, long);
+static void ieee_putascii(char *, ...);
+static void ieee_putcs(int);
+static long ieee_putld(long, long, unsigned char *);
+static long ieee_putlr(struct ieeeFixupp *);
+static void ieee_unqualified_name(char *, char *);
+
+
+/* 
+ * pup init 
+ */
+static void ieee_init (FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
+{
+    (void) eval;
+    ofp = fp;
+    error = errfunc;
+    deflabel = ldef;
+    any_segs = FALSE;
+    fpubhead = NULL;
+    fpubtail = &fpubhead;
+    exthead = NULL;
+    exttail = &exthead;
+    externals = 1;
+    ebhead = NULL;
+    ebtail = &ebhead;
+    seghead = ieee_seg_needs_update = NULL;
+    segtail = &seghead;
+    ieee_entry_seg = NO_SEG;
+    ieee_uppercase = FALSE;
+    checksum = 0;
+    of_ieee.current_dfmt->init (&of_ieee,NULL,fp,errfunc);
+}
+static int ieee_set_info(enum geninfo type, char **val)
+{
+    (void) type;
+    (void) val;
+
+    return 0;
+}
+/*
+ * Rundown
+ */
+static void ieee_cleanup (int debuginfo) 
+{
+    ieee_write_file(debuginfo);
+    of_ieee.current_dfmt->cleanup ();
+    fclose (ofp);
+    while (seghead) {
+       struct ieeeSection *segtmp = seghead;
+       seghead = seghead->next;
+       while (segtmp->pubhead) {
+           struct ieeePublic *pubtmp = segtmp->pubhead;
+           segtmp->pubhead = pubtmp->next;
+           nasm_free (pubtmp);
+       }
+       while (segtmp->fptr) {
+           struct ieeeFixupp *fixtmp = segtmp->fptr;
+           segtmp->fptr = fixtmp->next;
+           nasm_free(fixtmp);
+       }
+       while (segtmp->data) {
+           struct ieeeObjData *dattmp = segtmp->data;
+           segtmp->data = dattmp->next;
+           nasm_free(dattmp);
+       }
+       nasm_free (segtmp);
+    }
+    while (fpubhead) {
+       struct ieeePublic *pubtmp = fpubhead;
+       fpubhead = fpubhead->next;
+       nasm_free (pubtmp);
+    }
+    while (exthead) {
+       struct ieeeExternal *exttmp = exthead;
+       exthead = exthead->next;
+       nasm_free (exttmp);
+    }
+    while (ebhead) {
+       struct ExtBack *ebtmp = ebhead;
+       ebhead = ebhead->next;
+       nasm_free (ebtmp);
+    }
+}
+/*
+ * callback for labels
+ */
+static void ieee_deflabel (char *name, long segment,
+                         long offset, int is_global, char *special) {
+    /*
+     * We have three cases:
+     *
+     * (i) `segment' is a segment-base. If so, set the name field
+     * for the segment structure it refers to, and then
+     * return.
+     *
+     * (ii) `segment' is one of our segments, or a SEG_ABS segment.
+     * Save the label position for later output of a PUBDEF record.
+     * 
+     *
+     * (iii) `segment' is not one of our segments. Save the label
+     * position for later output of an EXTDEF.
+     */
+    struct ieeeExternal *ext;
+    struct ExtBack *eb;
+    struct ieeeSection *seg;
+    int i;
+
+    if (special) {
+        error(ERR_NONFATAL, "unrecognised symbol type `%s'", special);
+    }
+    /*
+     * First check for the double-period, signifying something
+     * unusual.
+     */
+    if (name[0] == '.' && name[1] == '.') {
+       if (!strcmp(name, "..start")) {
+           ieee_entry_seg = segment;
+           ieee_entry_ofs = offset;
+       }
+       return;
+    }
+
+    /*
+     * Case (i):
+     */
+    if (ieee_seg_needs_update) {
+       ieee_seg_needs_update->name = name;
+       return;
+    } 
+    if (segment < SEG_ABS && segment != NO_SEG && segment % 2)
+       return;
+
+    /*
+     * case (ii)
+     */
+    if (segment >= SEG_ABS) {
+       /*
+        * SEG_ABS subcase of (ii).
+        */
+       if (is_global) {
+           struct ieeePublic *pub;
+
+           pub = *fpubtail = nasm_malloc(sizeof(*pub));
+           fpubtail = &pub->next;
+           pub->next = NULL;
+           pub->name = name;
+           pub->offset = offset;
+           pub->segment = segment & ~SEG_ABS;
+       }
+       return;
+    }
+
+    for (seg = seghead; seg && is_global; seg = seg->next)
+       if (seg->index == segment) {
+               struct ieeePublic *pub;
+
+           last_defined = pub = *seg->pubtail = nasm_malloc(sizeof(*pub));
+           seg->pubtail = &pub->next;
+           pub->next = NULL;
+           pub->name = name;
+           pub->offset = offset;
+           pub->index = seg->ieee_index;
+           pub->segment = -1;
+           return;
+       }
+
+    /*
+     * Case (iii).
+     */
+    if (is_global) {
+        ext = *exttail = nasm_malloc(sizeof(*ext));
+        ext->next = NULL;
+        exttail = &ext->next;
+        ext->name = name;
+        if (is_global == 2)
+           ext->commonsize = offset;
+       else
+           ext->commonsize = 0;
+       i = segment/2;
+       eb = ebhead;
+       if (!eb) {
+           eb = *ebtail = nasm_malloc(sizeof(*eb));
+           eb->next = NULL;
+           ebtail = &eb->next;
+        }
+       while (i > EXT_BLKSIZ) {
+           if (eb && eb->next)
+               eb = eb->next;
+           else {
+               eb = *ebtail = nasm_malloc(sizeof(*eb));
+               eb->next = NULL;
+               ebtail = &eb->next;
+           }
+           i -= EXT_BLKSIZ;
+       }
+        eb->index[i] = externals++;
+    }
+       
+}
+
+/*
+ * Put data out
+ */
+static void ieee_out (long segto, void *data, unsigned long type,
+                    long segment, long wrt) {
+    unsigned long size, realtype;
+    unsigned char *ucdata;
+    long ldata;
+    struct ieeeSection *seg;
+
+    /*
+     * handle absolute-assembly (structure definitions)
+     */
+    if (segto == NO_SEG) {
+       if ((type & OUT_TYPMASK) != OUT_RESERVE)
+           error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
+                  " space");
+       return;
+    }
+
+    /*
+     * If `any_segs' is still FALSE, we must define a default
+     * segment.
+     */
+    if (!any_segs) {
+       int tempint;                   /* ignored */
+       if (segto != ieee_segment("__NASMDEFSEG", 2, &tempint))
+           error (ERR_PANIC, "strange segment conditions in IEEE driver");
+    }
+
+    /*
+     * Find the segment we are targetting.
+     */
+    for (seg = seghead; seg; seg = seg->next)
+       if (seg->index == segto)
+           break;
+    if (!seg)
+       error (ERR_PANIC, "code directed to nonexistent segment?");
+
+    size = type & OUT_SIZMASK;
+    realtype = type & OUT_TYPMASK;
+    if (realtype == OUT_RAWDATA) {
+       ucdata = data;
+       while (size--)
+           ieee_write_byte(seg,*ucdata++);
+    } else if (realtype == OUT_ADDRESS || realtype == OUT_REL2ADR ||
+              realtype == OUT_REL4ADR) {
+       if (segment == NO_SEG && realtype != OUT_ADDRESS)
+           error(ERR_NONFATAL, "relative call to absolute address not"
+                 " supported by IEEE format");
+       ldata = *(long *)data;
+       if (realtype == OUT_REL2ADR)
+           ldata += (size-2);
+       if (realtype == OUT_REL4ADR)
+           ldata += (size-4);
+       ieee_write_fixup (segment, wrt, seg, size, realtype,ldata);
+       if (size == 2)
+           ieee_write_word (seg, ldata);
+       else
+           ieee_write_dword (seg, ldata);
+    } 
+    else if (realtype == OUT_RESERVE) {
+       while (size--)
+           ieee_write_byte(seg,0);
+    }
+}
+
+static void ieee_data_new(struct ieeeSection *segto) {
+    
+    if (!segto->data)
+       segto->data = segto->datacurr = nasm_malloc(sizeof(*(segto->datacurr)));
+    else
+       segto->datacurr = segto->datacurr->next = nasm_malloc(sizeof(*(segto->datacurr)));
+    segto->datacurr->next = NULL;
+}
+
+
+/*
+ * this routine is unalduterated bloatware.  I usually don't do this
+ * but I might as well see what it is like on a harmless program.
+ * If anyone wants to optimize this is a good canditate!
+ */
+static void ieee_write_fixup (long segment, long wrt, struct ieeeSection * segto,
+                               int size, unsigned long realtype, long offset) {
+    struct ieeeSection *target;
+    struct ieeeFixupp s;
+
+    /* Don't put a fixup for things NASM can calculate */
+    if (wrt == NO_SEG && segment == NO_SEG)
+       return;
+
+    s.ftype = -1;
+    /* if it is a WRT offset */
+    if (wrt != NO_SEG) {
+       s.ftype = FT_WRT;
+       s.addend = offset;
+       if (wrt >= SEG_ABS)
+           s.id1 = -(wrt-SEG_ABS);
+       else {
+           if (wrt %2 && realtype != OUT_REL2ADR && realtype != OUT_REL4ADR) {
+               wrt--;
+
+               for (target = seghead; target; target = target->next)
+                   if (target->index == wrt)
+                       break;
+               if (target) {
+                   s.id1 = target->ieee_index;
+                   for (target = seghead; target; target = target->next)
+                       if (target->index == segment)
+                           break;
+               
+                   if (target) 
+                       s.id2 = target->ieee_index;
+                   else {
+                       /*
+                        * Now we assume the segment field is being used
+                        * to hold an extern index
+                        */
+                       long i = segment/2;
+                       struct ExtBack *eb = ebhead;
+                       while (i > EXT_BLKSIZ) {
+                           if (eb)
+                               eb = eb->next;
+                           else
+                               break;
+                           i -= EXT_BLKSIZ;
+                       }
+                               /* if we have an extern decide the type and make a record
+                        */
+                       if (eb) {
+                               s.ftype = FT_EXTWRT;
+                               s.addend = 0;
+                               s.id2 = eb->index[i];
+                       }
+                       else
+                           error(ERR_NONFATAL,
+                               "Source of WRT must be an offset");
+                   }
+                       
+               }
+               else 
+                   error(ERR_PANIC,
+                         "unrecognised WRT value in ieee_write_fixup");
+           }
+           else 
+               error(ERR_NONFATAL,"target of WRT must be a section ");
+       }
+       s.size = size;
+       ieee_install_fixup(segto,&s);
+       return;
+    }
+    /* Pure segment fixup ? */
+    if (segment != NO_SEG) {
+       s.ftype = FT_SEG;
+       s.id1 = 0;
+       if (segment >= SEG_ABS) {
+           /* absolute far segment fixup */
+           s.id1 = -(segment -~SEG_ABS);
+       }
+       else if (segment % 2) {
+           /* fixup to named segment */
+           /* look it up */
+           for (target = seghead; target; target = target->next)
+               if (target->index == segment-1)
+                   break;
+           if (target)
+               s.id1 = target->ieee_index;
+           else {
+               /*
+                * Now we assume the segment field is being used
+                * to hold an extern index
+                */
+               long i = segment/2;
+               struct ExtBack *eb = ebhead;
+               while (i > EXT_BLKSIZ) {
+                   if (eb)
+                       eb = eb->next;
+                   else
+                       break;
+                   i -= EXT_BLKSIZ;
+               }
+               /* if we have an extern decide the type and make a record
+                */
+               if (eb) {
+                   if (realtype == OUT_REL2ADR || realtype == OUT_REL4ADR) {
+                       error(ERR_PANIC,"Segment of a rel not supported in ieee_write_fixup");
+                   }
+                   else {
+                               /* If we want the segment */
+                           s.ftype = FT_EXTSEG;
+                           s.addend = 0;
+                           s.id1 = eb->index[i];
+                   }
+                   
+               }
+               else 
+                   /* If we get here the seg value doesn't make sense */
+                   error(ERR_PANIC,
+                         "unrecognised segment value in ieee_write_fixup");
+           }
+
+        } else {
+           /* Assume we are offsetting directly from a section
+            * So look up the target segment
+            */
+           for (target = seghead; target; target = target->next)
+               if (target->index == segment)
+                   break;
+           if (target) {
+               if (realtype == OUT_REL2ADR || realtype == OUT_REL4ADR) {
+                   /* PC rel to a known offset */
+                   s.id1 = target->ieee_index;
+                   s.ftype = FT_REL;
+                   s.size = size;
+                   s.addend = offset;
+               }
+               else {
+                   /* We were offsetting from a seg */
+                   s.id1 = target->ieee_index;
+                   s.ftype = FT_OFS;
+                   s.size = size;
+                   s.addend = offset;
+               }
+           }
+           else {
+               /*
+                * Now we assume the segment field is being used
+                * to hold an extern index
+                */
+               long i = segment/2;
+               struct ExtBack *eb = ebhead;
+               while (i > EXT_BLKSIZ) {
+                   if (eb)
+                       eb = eb->next;
+                   else
+                       break;
+                   i -= EXT_BLKSIZ;
+               }
+               /* if we have an extern decide the type and make a record
+                */
+               if (eb) {
+                   if (realtype == OUT_REL2ADR || realtype == OUT_REL4ADR) {
+                       s.ftype = FT_EXTREL;
+                       s.addend = 0;
+                       s.id1 = eb->index[i];
+                   }
+                   else {
+                           /* else we want the external offset */
+                           s.ftype = FT_EXT;
+                           s.addend = 0;
+                           s.id1 = eb->index[i];
+                   }
+                   
+               }
+               else 
+                   /* If we get here the seg value doesn't make sense */
+                   error(ERR_PANIC,
+                         "unrecognised segment value in ieee_write_fixup");
+           }
+       }
+       if (size != 2 && s.ftype == FT_SEG)
+           error(ERR_NONFATAL, "IEEE format can only handle 2-byte"
+                    " segment base references");
+       s.size = size;
+       ieee_install_fixup(segto,&s);
+       return;
+    }
+    /* should never get here */
+}
+static void ieee_install_fixup(struct ieeeSection *seg, struct ieeeFixupp *fix)
+{
+    struct ieeeFixupp *f;
+    f = nasm_malloc(sizeof(struct ieeeFixupp));
+    memcpy(f,fix,sizeof(struct ieeeFixupp));
+    f->offset = seg->currentpos;
+    seg->currentpos += fix->size;
+    f->next = NULL;
+    if (seg->fptr)
+       seg->flptr = seg->flptr->next = f;
+    else
+       seg->fptr = seg->flptr = f;
+
+}
+
+/*
+ * segment registry
+ */
+static long ieee_segment (char *name, int pass, int *bits) {
+    /*
+     * We call the label manager here to define a name for the new
+     * segment, and when our _own_ label-definition stub gets
+     * called in return, it should register the new segment name
+     * using the pointer it gets passed. That way we save memory,
+     * by sponging off the label manager.
+     */
+    if (!name) {
+       *bits = 16;
+       if (!any_segs)
+               return 0;
+       return seghead->index;
+    } else {
+       struct ieeeSection *seg;
+       int ieee_idx, attrs, rn_error;
+       char *p;
+
+       /*
+        * Look for segment attributes.
+        */
+       attrs = 0;
+       while (*name == '.')
+           name++;                    /* hack, but a documented one */
+       p = name;
+       while (*p && !isspace(*p))
+           p++;
+       if (*p) {
+           *p++ = '\0';
+           while (*p && isspace(*p))
+               *p++ = '\0';
+       }
+       while (*p) {
+           while (*p && !isspace(*p))
+               p++;
+           if (*p) {
+               *p++ = '\0';
+               while (*p && isspace(*p))
+                   *p++ = '\0';
+           }
+
+           attrs++;
+       }
+
+       ieee_idx = 1;
+       for (seg = seghead; seg; seg = seg->next) {
+           ieee_idx++;
+           if (!strcmp(seg->name, name)) {
+               if (attrs > 0 && pass == 1)
+                   error(ERR_WARNING, "segment attributes specified on"
+                         " redeclaration of segment: ignoring");
+               if (seg->use32)
+                   *bits = 32;
+               else
+                   *bits = 16;
+               return seg->index;
+           }
+       }
+
+       *segtail = seg = nasm_malloc(sizeof(*seg));
+       seg->next = NULL;
+       segtail = &seg->next;
+       seg->index = seg_alloc();
+       seg->ieee_index = ieee_idx;
+       any_segs = TRUE;
+       seg->name = NULL;
+       seg->currentpos = 0;
+       seg->align = 1;                /* default */
+       seg->use32 = *bits == 32;      /* default to user spec */
+       seg->combine = CMB_PUBLIC;     /* default */
+       seg->pubhead = NULL;
+       seg->pubtail = &seg->pubhead;
+       seg->data = NULL;
+       seg->fptr = NULL;
+       seg->lochead = NULL;
+       seg->loctail = &seg->lochead;
+
+       /*
+        * Process the segment attributes.
+        */
+       p = name;
+       while (attrs--) {
+           p += strlen(p);
+           while (!*p) p++;
+
+           /*
+            * `p' contains a segment attribute.
+            */
+           if (!nasm_stricmp(p, "private"))
+               seg->combine = CMB_PRIVATE;
+           else if (!nasm_stricmp(p, "public"))
+               seg->combine = CMB_PUBLIC;
+           else if (!nasm_stricmp(p, "common"))
+               seg->combine = CMB_COMMON;
+           else if (!nasm_stricmp(p, "use16"))
+               seg->use32 = FALSE;
+           else if (!nasm_stricmp(p, "use32"))
+               seg->use32 = TRUE;
+           else if (!nasm_strnicmp(p, "align=", 6)) {
+               seg->align = readnum(p+6, &rn_error);
+               if (seg->align == 0)
+                   seg->align = 1;
+               if (rn_error) {
+                   seg->align = 1;
+                   error (ERR_NONFATAL, "segment alignment should be"
+                          " numeric");
+               }
+               switch ((int) seg->align) {
+                 case 1:              /* BYTE */
+                 case 2:              /* WORD */
+                 case 4:              /* DWORD */
+                 case 16:             /* PARA */
+                 case 256:            /* PAGE */
+                 case 8:
+                 case 32:
+                 case 64:
+                 case 128:
+                   break;
+                 default:
+                   error(ERR_NONFATAL, "invalid alignment value %d",
+                         seg->align);
+                   seg->align = 1;
+                   break;
+               }
+           } else if (!nasm_strnicmp(p, "absolute=", 9)) {
+               seg->align = SEG_ABS + readnum(p+9, &rn_error);
+               if (rn_error)
+                   error (ERR_NONFATAL, "argument to `absolute' segment"
+                          " attribute should be numeric");
+           }
+       }
+
+       ieee_seg_needs_update = seg;
+       if (seg->align >= SEG_ABS)
+           deflabel (name, NO_SEG, seg->align - SEG_ABS, 
+                       NULL, FALSE, FALSE, &of_ieee, error);
+       else
+           deflabel (name, seg->index+1, 0L, 
+                       NULL, FALSE, FALSE, &of_ieee, error);
+       ieee_seg_needs_update = NULL;
+
+       if (seg->use32)
+           *bits = 32;
+       else
+           *bits = 16;
+       return seg->index;
+    }
+}
+/*
+ * directives supported
+ */
+static int ieee_directive (char *directive, char *value, int pass) 
+{
+    
+    (void) value;
+    (void) pass;
+    if (!strcmp(directive, "uppercase")) {
+       ieee_uppercase = TRUE;
+       return 1;
+    }
+    return 0;
+}
+/*
+ * Return segment data
+ */
+static long ieee_segbase (long segment) 
+{
+    struct ieeeSection *seg;
+
+    /*
+     * Find the segment in our list.
+     */
+    for (seg = seghead; seg; seg = seg->next)
+       if (seg->index == segment-1)
+           break;
+
+    if (!seg)
+       return segment;                /* not one of ours - leave it alone */
+
+    if (seg->align >= SEG_ABS)
+       return seg->align;             /* absolute segment */
+
+    return segment;                   /* no special treatment */
+}
+/*
+ * filename
+ */
+static void ieee_filename (char *inname, char *outname, efunc error) {
+    strcpy(ieee_infile, inname);
+    standard_extension (inname, outname, ".o", error);
+}
+
+static void ieee_write_file (int debuginfo) {
+    struct tm *thetime;
+    time_t reltime;
+    struct FileName *fn;
+    struct ieeeSection *seg;
+    struct ieeePublic *pub, *loc;
+    struct ieeeExternal *ext;
+    struct ieeeObjData *data;
+    struct ieeeFixupp *fix;
+    struct Array *arr;
+    static char boast[] = "The Netwide Assembler " NASM_VER;
+    int i;
+
+    /*
+     * Write the module header
+     */
+    ieee_putascii("MBFNASM,%02X%s.\r\n",strlen(ieee_infile),ieee_infile);
+
+    /*
+     * Write the NASM boast comment.
+     */
+    ieee_putascii("CO0,%02X%s.\r\n",strlen(boast),boast);
+
+    /* 
+     * write processor-specific information
+     */
+    ieee_putascii("AD8,4,L.\r\n");
+
+    /*
+     * date and time
+     */
+    time(&reltime);
+    thetime = localtime(&reltime);
+    ieee_putascii("DT%04d%02d%02d%02d%02d%02d.\r\n", 
+                       1900+thetime->tm_year,thetime->tm_mon+1,thetime->tm_mday,
+                       thetime->tm_hour, thetime->tm_min, thetime->tm_sec);
+    /* 
+     * if debugging, dump file names
+     */
+    for (fn = fnhead; fn && debuginfo; fn = fn->next) {
+       ieee_putascii("C0105,%02X%s.\r\n",strlen(fn->name),fn->name);
+    }
+     
+    ieee_putascii("CO101,07ENDHEAD.\r\n");
+    /*
+     * the standard doesn't specify when to put checksums,
+     * we'll just do it periodically.
+     */
+    ieee_putcs(FALSE);
+
+    /* 
+     * Write the section headers
+     */
+    seg = seghead;
+    if (!debuginfo && !strcmp(seg->name,"??LINE"))
+       seg = seg->next;
+    while (seg) {
+       char buf[256];
+       char attrib;
+       switch(seg->combine) {
+           case CMB_PUBLIC:
+           default:
+               attrib = 'C';
+               break;
+           case CMB_PRIVATE:
+               attrib = 'S';
+               break;
+           case CMB_COMMON:
+               attrib = 'M';
+               break;
+       }
+       ieee_unqualified_name(buf,seg->name);
+       if (seg->align >= SEG_ABS) {
+           ieee_putascii("ST%X,A,%02X%s.\r\n",seg->ieee_index,strlen(buf), buf);
+           ieee_putascii("ASL%X,%lX.\r\n",seg->ieee_index, (seg->align - SEG_ABS)*16);
+       }
+       else {
+           ieee_putascii("ST%X,%c,%02X%s.\r\n",seg->ieee_index,attrib,strlen(buf), buf);
+           ieee_putascii("SA%X,%lX.\r\n",seg->ieee_index,seg->align);
+           ieee_putascii("ASS%X,%X.\r\n",seg->ieee_index, seg->currentpos);
+       }
+       seg = seg->next;
+    }
+    /*
+     * write the start address if there is one
+     */
+    if (ieee_entry_seg) {
+        for (seg = seghead; seg; seg = seg->next)
+           if (seg->index == ieee_entry_seg)
+               break;
+       if (!seg)
+           error(ERR_PANIC,"Start address records are incorrect");
+       else 
+           ieee_putascii("ASG,R%X,%lX,+.\r\n",seg->ieee_index, ieee_entry_ofs);
+    }  
+
+
+    ieee_putcs(FALSE);
+    /*
+     * Write the publics
+     */
+    i = 1;
+    for (seg = seghead; seg; seg = seg->next) {
+        for (pub = seg->pubhead; pub; pub = pub->next) {
+           char buf[256];
+           ieee_unqualified_name(buf,pub->name);
+                   ieee_putascii("NI%X,%02X%s.\r\n",i, strlen(buf), buf);
+           if (pub->segment == -1)  
+                       ieee_putascii("ASI%X,R%X,%lX,+.\r\n", i, pub->index,pub->offset);
+           else
+                       ieee_putascii("ASI%X,%lX,%lX,+.\r\n", i, pub->segment*16,pub->offset);
+           if (debuginfo) {
+               if (pub->type >= 0x100)
+                   ieee_putascii("ATI%X,T%X.\r\n", i, pub->type - 0x100);
+               else
+                   ieee_putascii("ATI%X,%X.\r\n", i, pub->type);
+           }   
+           i++;
+        }
+    }
+    pub = fpubhead;
+    i = 1;
+    while (pub) {
+       char buf[256];
+       ieee_unqualified_name(buf,pub->name);
+               ieee_putascii("NI%X,%02X%s.\r\n",i, strlen(buf), buf);
+       if (pub->segment == -1)  
+                   ieee_putascii("ASI%X,R%X,%lX,+.\r\n", i, pub->index,pub->offset);
+       else
+                   ieee_putascii("ASI%X,%lX,%lX,+.\r\n", i, pub->segment*16,pub->offset);
+       if (debuginfo) {
+           if (pub->type >= 0x100)
+               ieee_putascii("ATI%X,T%X.\r\n", i, pub->type - 0x100);
+           else
+               ieee_putascii("ATI%X,%X.\r\n", i, pub->type);
+       }
+       i++;
+        pub = pub->next;
+    }
+    /*
+     * Write the externals
+     */
+    ext = exthead;
+    i = 1;
+    while (ext) {
+       char buf[256];
+       ieee_unqualified_name(buf,ext->name);
+               ieee_putascii("NX%X,%02X%s.\r\n",i++, strlen(buf), buf);
+        ext = ext->next;
+    }
+    ieee_putcs(FALSE);
+
+    /*
+     * IEEE doesn't have a standard pass break record
+     * so use the ladsoft variant
+     */
+    ieee_putascii("CO100,06ENDSYM.\r\n");
+
+    /*
+     * now put types
+     */
+    i = ARRAY_BOT;
+    for (arr = arrhead; arr && debuginfo; arr = arr->next) {
+       ieee_putascii("TY%X,20,%X,%lX.\r\n",i++,arr->basetype,arr->size);
+    }
+    /*
+     * now put locals
+     */
+    i = 1;
+    for (seg = seghead; seg && debuginfo; seg = seg->next) {
+        for (loc = seg->lochead; loc; loc = loc->next) {
+           char buf[256];
+           ieee_unqualified_name(buf,loc->name);
+                   ieee_putascii("NN%X,%02X%s.\r\n",i, strlen(buf), buf);
+           if (loc->segment == -1)  
+                       ieee_putascii("ASN%X,R%X,%lX,+.\r\n", i, loc->index,loc->offset);
+           else
+                       ieee_putascii("ASN%X,%lX,%lX,+.\r\n", i, loc->segment*16,loc->offset);
+           if (debuginfo) {
+               if (loc->type >= 0x100)
+                   ieee_putascii("ATN%X,T%X.\r\n", i, loc->type - 0x100);
+               else
+                   ieee_putascii("ATN%X,%X.\r\n", i, loc->type);
+           }
+           i++;
+        }
+    }
+
+    /*
+     *  put out section data;
+     */ 
+    seg = seghead;
+    if (!debuginfo && !strcmp(seg->name,"??LINE"))
+       seg = seg->next;
+    while (seg) {
+       if (seg->currentpos) {
+           long size,org = 0;
+           data = seg->data;
+           ieee_putascii("SB%X.\r\n",seg->ieee_index);
+           fix = seg->fptr;
+           while (fix) {
+               size = HUNKSIZE - (org %HUNKSIZE);
+               size = size +org > seg->currentpos ? seg->currentpos-org : size;
+               size = fix->offset - org > size ? size : fix->offset-org;
+               org = ieee_putld(org,org+size,data->data);
+               if (org % HUNKSIZE == 0)
+                   data = data->next;
+               if (org == fix->offset) {
+                   org += ieee_putlr(fix);
+                   fix = fix->next;
+               }
+           }
+           while (org < seg->currentpos && data) {
+               size = seg->currentpos-org > HUNKSIZE ? HUNKSIZE : seg->currentpos - org;
+               org = ieee_putld(org,org+size,data->data);
+               data = data->next;
+           }
+           ieee_putcs(FALSE);
+               
+       }
+       seg = seg->next;
+    }
+    /*
+     * module end record
+     */
+    ieee_putascii("ME.\r\n");
+}
+
+static void ieee_write_byte(struct ieeeSection *seg, int data) {
+    int temp;
+    if (!(temp = seg->currentpos++ % HUNKSIZE))
+       ieee_data_new(seg);
+    seg->datacurr->data[temp] = data;
+}
+
+static void ieee_write_word(struct ieeeSection *seg, int data) {
+    ieee_write_byte(seg, data & 0xFF);
+    ieee_write_byte(seg,(data >> 8) & 0xFF);
+}
+
+static void ieee_write_dword(struct ieeeSection *seg, long data) {
+    ieee_write_byte(seg, data & 0xFF);
+    ieee_write_byte(seg,(data >> 8) & 0xFF);
+    ieee_write_byte(seg,(data >> 16) & 0xFF);
+    ieee_write_byte(seg,(data >> 24) & 0xFF);
+}
+static void ieee_putascii(char *format, ...)
+{
+       char buffer[256];
+       int i,l;
+       va_list ap;
+
+       va_start(ap, format);
+       vsprintf(buffer, format, ap);
+       l = strlen(buffer);
+       for (i=0; i < l; i++)
+               if ((buffer[i] & 0xff) > 31)
+                       checksum+=buffer[i];
+       va_end(ap);
+       fprintf(ofp,buffer);
+}
+
+/*
+ * put out a checksum record */
+static void ieee_putcs(int toclear)
+{
+       if (toclear) {
+               ieee_putascii("CS.\r\n");
+       }
+       else {
+               checksum += 'C';
+               checksum += 'S';
+               ieee_putascii("CS%02X.\r\n",checksum & 127);
+       }
+       checksum = 0;
+}
+
+static long ieee_putld(long start, long end, unsigned char *buf)
+{
+       long val;
+       if (start == end)
+               return(start);
+       val = start % HUNKSIZE;
+       /* fill up multiple lines */
+       while (end - start >= LDPERLINE) {
+               int i;
+               ieee_putascii("LD");
+               for (i=0; i < LDPERLINE; i++) {
+                       ieee_putascii("%02X",buf[val++]);
+                       start++;
+               }
+               ieee_putascii(".\r\n");
+       }
+       /* if no partial lines */
+       if (start == end)
+               return(start);
+       /* make a partial line */
+       ieee_putascii("LD");
+       while (start < end) {
+               ieee_putascii("%02X",buf[val++]);
+               start++;
+       }
+       ieee_putascii(".\r\n");
+       return(start);
+}
+static long ieee_putlr(struct ieeeFixupp *p)
+{
+/*
+ * To deal with the vagaries of segmentation the LADsoft linker
+ * defines two types of segments: absolute and virtual.  Note that
+ * 'absolute' in this context is a different thing from the IEEE
+ * definition of an absolute segment type, which is also supported. If a
+ * sement is linked in virtual mode the low limit (L-var) is
+ * subtracted from each R,X, and P variable which appears in an
+ * expression, so that we can have relative offsets.  Meanwhile
+ * in the ABSOLUTE mode this subtraction is not done and
+ * so we can use absolute offsets from 0.  In the LADsoft linker
+ * this configuration is not done in the assemblker source but in
+ * a source the linker reads.  Generally this type of thing only
+ * becomes an issue if real mode code is used.  A pure 32-bit linker could
+ * get away without defining the virtual mode...
+ */
+       char buf[40];
+       long size=p->size;
+       switch(p->ftype) {
+           case FT_SEG:
+               if (p->id1 < 0)
+                   sprintf(buf,"%lX",-p->id1);
+               else
+                   sprintf(buf,"L%lX,10,/",p->id1);
+               break;
+           case FT_OFS:
+               sprintf(buf,"R%lX,%lX,+",p->id1,p->addend);
+               break;
+           case FT_REL:
+               sprintf(buf,"R%lX,%lX,+,P,-,%X,-",p->id1,p->addend,p->size);
+               break;
+               
+           case FT_WRT:
+               if (p->id2 < 0)
+                   sprintf(buf,"R%lX,%lX,+,L%lX,+,%lX,-",p->id2,p->addend,p->id2,-p->id1*16);
+               else
+                   sprintf(buf,"R%lX,%lX,+,L%lX,+,L%lX,-",p->id2,p->addend,p->id2,p->id1);
+               break;
+           case FT_EXT:
+               sprintf(buf,"X%lX",p->id1);
+               break;
+           case FT_EXTREL:
+               sprintf(buf,"X%lX,P,-,%lX,-",p->id1,size);
+               break;
+           case FT_EXTSEG:
+               /* We needed a non-ieee hack here.
+                * We introduce the Y variable, which is the low
+                * limit of the native segment the extern resides in
+                */
+               sprintf(buf,"Y%lX,10,/",p->id1);
+               break;
+           case FT_EXTWRT:
+               if (p->id2 < 0)
+                   sprintf(buf,"X%lX,Y%lX,+,%lX,-",p->id2,p->id2,-p->id1*16);
+               else
+                   sprintf(buf,"X%lX,Y%lX,+,L%lX,-",p->id2,p->id2,p->id1);
+               break;
+       }
+       ieee_putascii("LR(%s,%lX).\r\n", buf, size);
+
+       return(size);
+}
+/* Dump all segment data (text and fixups )*/
+
+static void ieee_unqualified_name(char *dest, char *source)
+{
+    if (ieee_uppercase) {
+       while (*source)
+           *dest++ = toupper(*source++);
+        *dest = 0;
+    }
+    else strcpy(dest,source);
+}
+void dbgls_init(struct ofmt * of, void * id, FILE * fp, efunc error)
+{
+    int tempint;
+    (void) of;
+    (void) id;
+    (void) fp;
+    (void) error;
+
+    fnhead = NULL;
+    fntail = &fnhead;
+    arrindex = ARRAY_BOT ;
+    arrhead = NULL;
+    arrtail = &arrhead;
+    ieee_segment("??LINE", 2, &tempint);
+    any_segs = FALSE;
+}
+static void dbgls_cleanup(void)
+{
+    struct ieeeSection *segtmp;
+    while (fnhead) {
+       struct FileName *fntemp = fnhead;
+       fnhead = fnhead->next;
+       nasm_free (fntemp->name);
+       nasm_free (fntemp);
+    }
+    for (segtmp = seghead; segtmp; segtmp = segtmp->next) {
+       while (segtmp->lochead) {
+           struct ieeePublic *loctmp = segtmp->lochead;
+           segtmp->lochead = loctmp->next;
+           nasm_free (loctmp->name);
+           nasm_free (loctmp);
+       }
+    }
+    while (arrhead) {
+       struct Array *arrtmp = arrhead;
+        arrhead = arrhead->next;
+        nasm_free (arrtmp);
+    }
+}
+
+/*
+ * because this routine is not bracketed in
+ * the main program, this routine will be called even if there
+ * is no request for debug info
+ * so, we have to make sure the ??LINE segment is avaialbe
+ * as the first segment when this debug format is selected
+ */
+static void dbgls_linnum (const char *lnfname, long lineno, long segto)
+{
+    struct FileName *fn;
+    struct ieeeSection *seg;
+    int i = 0;
+    if (segto == NO_SEG)
+       return;
+
+    /*
+     * If `any_segs' is still FALSE, we must define a default
+     * segment.
+     */
+    if (!any_segs) {
+       int tempint;                   /* ignored */
+       if (segto != ieee_segment("__NASMDEFSEG", 2, &tempint))
+           error (ERR_PANIC, "strange segment conditions in OBJ driver");
+    }
+
+    /*
+     * Find the segment we are targetting.
+     */
+    for (seg = seghead; seg; seg = seg->next)
+       if (seg->index == segto)
+           break;
+    if (!seg)
+       error (ERR_PANIC, "lineno directed to nonexistent segment?");
+
+    for (fn = fnhead; fn; fn = fnhead->next) {
+       if (!nasm_stricmp(lnfname,fn->name))
+           break;
+        i++;
+    }
+    if (!fn) {
+       fn = nasm_malloc ( sizeof( *fn));
+       fn->name = nasm_malloc ( strlen(lnfname) + 1) ;
+       fn->index = i;
+        strcpy (fn->name,lnfname);
+       fn->next = NULL;
+       *fntail = fn;
+       fntail = &fn->next;
+    }
+    ieee_write_byte(seghead, fn->index);
+    ieee_write_word(seghead, lineno);
+    ieee_write_fixup (segto, NO_SEG, seghead, 4, OUT_ADDRESS, seg->currentpos);
+
+}
+static void dbgls_deflabel (char *name, long segment,
+                         long offset, int is_global, char *special) 
+{
+    struct ieeeSection *seg;
+    int used_special;          /* have we used the special text? */
+
+    /* Keep compiler from warning about special and used_special */
+    used_special = special ? FALSE : FALSE;
+
+    /*
+     * If it's a special-retry from pass two, discard it.
+     */
+    if (is_global == 3)
+       return;
+
+    /*
+     * First check for the double-period, signifying something
+     * unusual.
+     */
+    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
+       return;
+    }
+
+    /*
+     * Case (i):
+     */
+    if (ieee_seg_needs_update)
+       return;
+    if (segment < SEG_ABS && segment != NO_SEG && segment % 2)
+       return;
+
+    if (segment >= SEG_ABS || segment == NO_SEG) {
+       return;
+    }
+
+    /*
+     * If `any_segs' is still FALSE, we might need to define a
+     * default segment, if they're trying to declare a label in
+     * `first_seg'.  But the label should exist due to a prior
+     * call to ieee_deflabel so we can skip that.
+     */
+
+    for (seg = seghead; seg; seg = seg->next)
+       if (seg->index == segment) {
+           struct ieeePublic *loc;
+           /*
+            * Case (ii). Maybe MODPUB someday?
+            */
+           if (!is_global) {
+               last_defined = loc  = nasm_malloc (sizeof(*loc));
+               *seg->loctail = loc;
+               seg->loctail = &loc->next;
+               loc->next = NULL;
+               loc->name = nasm_strdup(name);
+               loc->offset = offset;
+               loc->segment = -1;
+               loc->index = seg->ieee_index;
+           }
+       }
+}
+static void dbgls_typevalue (long type)
+{
+    int elem = TYM_ELEMENTS(type);
+    type = TYM_TYPE(type);
+
+    if (! last_defined)
+       return;
+
+    switch (type) {
+       case TY_BYTE:
+           last_defined->type = 1; /* unsigned char */
+           break;
+       case TY_WORD:
+           last_defined->type = 3; /* unsigned word */
+           break;
+       case TY_DWORD:
+           last_defined->type = 5; /* unsigned dword */
+           break;
+       case TY_FLOAT:
+           last_defined->type = 9; /* float */
+           break;
+       case TY_QWORD:
+           last_defined->type = 10; /* qword */
+           break;
+       case TY_TBYTE:
+           last_defined->type = 11; /* TBYTE */
+           break;
+       default:
+           last_defined->type = 0x10; /* near label */
+           break;
+    }
+               
+    if (elem > 1) {
+        struct Array *arrtmp = nasm_malloc (sizeof(*arrtmp));
+        int vtype = last_defined->type;
+        arrtmp->size = elem;
+        arrtmp->basetype = vtype;
+        arrtmp->next = NULL;
+        last_defined->type = arrindex++ + 0x100;
+        *arrtail = arrtmp;
+        arrtail = & (arrtmp->next);
+    }
+    last_defined = NULL;
+}
+static void dbgls_output (int output_type, void *param)
+{
+    (void) output_type;
+    (void) param;
+}
+static struct dfmt ladsoft_debug_form = {
+    "LADsoft Debug Records",
+    "ladsoft",
+    dbgls_init,
+    dbgls_linnum,
+    dbgls_deflabel,
+    null_debug_routine,
+    dbgls_typevalue,
+    dbgls_output,
+    dbgls_cleanup,
+};
+static struct dfmt *ladsoft_debug_arr[3] = {
+       &ladsoft_debug_form,
+       &null_debug_form,
+       NULL
+};
+struct ofmt of_ieee = {
+    "IEEE-695 (LADsoft variant) object file format",
+    "ieee",
+    NULL,
+    ladsoft_debug_arr,
+    &null_debug_form,
+    NULL,
+    ieee_init,
+    ieee_set_info,
+    ieee_out,
+    ieee_deflabel,
+    ieee_segment,
+    ieee_segbase,
+    ieee_directive,
+    ieee_filename,
+    ieee_cleanup
+};
+
+#endif /* OF_IEEE */
diff --git a/output/outobj.c b/output/outobj.c
new file mode 100644 (file)
index 0000000..4d8b6c9
--- /dev/null
@@ -0,0 +1,2531 @@
+/* outobj.c    output routines for the Netwide Assembler to produce
+ *             .OBJ object files
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "nasm.h"
+#include "nasmlib.h"
+#include "outform.h"
+
+#ifdef OF_OBJ
+
+/*
+ * outobj.c is divided into two sections.  The first section is low level
+ * routines for creating obj records;  It has nearly zero NASM specific
+ * code.  The second section is high level routines for processing calls and
+ * data structures from the rest of NASM into obj format.
+ *
+ * It should be easy (though not zero work) to lift the first section out for
+ * use as an obj file writer for some other assembler or compiler.
+ */
+
+/*
+ * These routines are built around the ObjRecord data struture.  An ObjRecord
+ * holds an object file record that may be under construction or complete.
+ *
+ * A major function of these routines is to support continuation of an obj
+ * record into the next record when the maximum record size is exceeded.  The
+ * high level code does not need to worry about where the record breaks occur.
+ * It does need to do some minor extra steps to make the automatic continuation
+ * work.  Those steps may be skipped for records where the high level knows no
+ * continuation could be required.
+ *
+ * 1) An ObjRecord is allocated and cleared by obj_new, or an existing ObjRecord
+ *    is cleared by obj_clear.
+ *
+ * 2) The caller should fill in .type.
+ *
+ * 3) If the record is continuable and there is processing that must be done at
+ *    the start of each record then the caller should fill in .ori with the
+ *    address of the record initializer routine.
+ *
+ * 4) If the record is continuable and it should be saved (rather than emitted
+ *    immediately) as each record is done, the caller should set .up to be a
+ *    pointer to a location in which the caller keeps the master pointer to the
+ *    ObjRecord.  When the record is continued, the obj_bump routine will then
+ *    allocate a new ObjRecord structure and update the master pointer.
+ *
+ * 5) If the .ori field was used then the caller should fill in the .parm with
+ *    any data required by the initializer.
+ *
+ * 6) The caller uses the routines: obj_byte, obj_word, obj_rword, obj_dword,
+ *    obj_x, obj_index, obj_value and obj_name to fill in the various kinds of
+ *    data required for this record.
+ *
+ * 7) If the record is continuable, the caller should call obj_commit at each
+ *    point where breaking the record is permitted.
+ *
+ * 8) To write out the record, the caller should call obj_emit2.  If the
+ *    caller has called obj_commit for all data written then he can get slightly
+ *    faster code by calling obj_emit instead of obj_emit2.
+ *
+ * Most of these routines return an ObjRecord pointer.  This will be the input
+ * pointer most of the time and will be the new location if the ObjRecord
+ * moved as a result of the call.  The caller may ignore the return value in
+ * three cases:  It is a "Never Reallocates" routine;  or  The caller knows
+ * continuation is not possible;  or  The caller uses the master pointer for the
+ * next operation.
+ */
+
+#define RECORD_MAX 1024-3      /* maximal size of any record except type+reclen */
+#define OBJ_PARMS  3           /* maximum .parm used by any .ori routine */
+
+#define FIX_08_LOW      0x8000 /* location type for various fixup subrecords */
+#define FIX_16_OFFSET   0x8400
+#define FIX_16_SELECTOR 0x8800
+#define FIX_32_POINTER  0x8C00
+#define FIX_08_HIGH     0x9000
+#define FIX_32_OFFSET   0xA400
+#define FIX_48_POINTER  0xAC00
+
+enum RecordID {                               /* record ID codes */
+
+    THEADR = 0x80,                    /* module header */
+    COMENT = 0x88,                    /* comment record */
+
+    LINNUM = 0x94,                     /* line number record */
+    LNAMES = 0x96,                    /* list of names */
+
+    SEGDEF = 0x98,                    /* segment definition */
+    GRPDEF = 0x9A,                    /* group definition */
+    EXTDEF = 0x8C,                    /* external definition */
+    PUBDEF = 0x90,                    /* public definition */
+    COMDEF = 0xB0,                    /* common definition */
+
+    LEDATA = 0xA0,                    /* logical enumerated data */
+    FIXUPP = 0x9C,                    /* fixups (relocations) */
+    FIXU32 = 0x9D,                    /* 32-bit fixups (relocations) */
+
+    MODEND = 0x8A,                    /* module end */
+    MODE32 = 0x8B                     /* module end for 32-bit objects */
+};
+
+enum ComentID {                        /* ID codes for comment records */
+
+     dEXTENDED = 0xA1,                 /* tells that we are using translator-specific extensions */
+     dLINKPASS = 0xA2,                 /* link pass 2 marker */
+     dTYPEDEF = 0xE3,                  /* define a type */
+     dSYM = 0xE6,                      /* symbol debug record */
+     dFILNAME = 0xE8,                  /* file name record */
+     dCOMPDEF = 0xEA                   /* compiler type info */
+
+};
+
+typedef struct ObjRecord ObjRecord;
+typedef void ORI(ObjRecord *orp);
+
+struct ObjRecord {
+    ORI           *ori;                        /* Initialization routine           */
+    int            used;               /* Current data size                */
+    int            committed;          /* Data size at last boundary       */
+    int            x_size;             /* (see obj_x)                      */
+    unsigned int   type;               /* Record type                      */
+    ObjRecord     *child;              /* Associated record below this one */
+    ObjRecord    **up;                 /* Master pointer to this ObjRecord */
+    ObjRecord     *back;               /* Previous part of this record     */
+    unsigned long  parm[OBJ_PARMS];    /* Parameters for ori routine       */
+    unsigned char  buf[RECORD_MAX];
+};
+
+static void obj_fwrite(ObjRecord *orp);
+static void ori_ledata(ObjRecord *orp);
+static void ori_pubdef(ObjRecord *orp);
+static void ori_null(ObjRecord *orp);
+static ObjRecord *obj_commit(ObjRecord *orp);
+
+static int obj_uppercase;              /* Flag: all names in uppercase */
+static int obj_use32;                  /* Flag: at least one segment is 32-bit */
+
+/*
+ * Clear an ObjRecord structure.  (Never reallocates).
+ * To simplify reuse of ObjRecord's, .type, .ori and .parm are not cleared.
+ */
+static ObjRecord *obj_clear(ObjRecord *orp) 
+{
+    orp->used = 0;
+    orp->committed = 0;
+    orp->x_size = 0;
+    orp->child = NULL;
+    orp->up = NULL;
+    orp->back = NULL;
+    return (orp);
+}
+
+/*
+ * Emit an ObjRecord structure.  (Never reallocates).
+ * The record is written out preceeded (recursively) by its previous part (if
+ * any) and followed (recursively) by its child (if any).
+ * The previous part and the child are freed.  The main ObjRecord is cleared,
+ * not freed.
+ */
+static ObjRecord *obj_emit(ObjRecord *orp) 
+{
+    if (orp->back) {
+       obj_emit(orp->back);
+       nasm_free(orp->back);
+    }
+
+    if (orp->committed)
+       obj_fwrite(orp);
+
+    if (orp->child) {
+       obj_emit(orp->child);
+       nasm_free(orp->child);
+    }
+
+    return (obj_clear(orp));
+}
+
+/*
+ * Commit and Emit a record.  (Never reallocates).
+ */
+static ObjRecord *obj_emit2(ObjRecord *orp) 
+{
+    obj_commit(orp);
+    return (obj_emit(orp));
+}
+
+/*
+ * Allocate and clear a new ObjRecord;  Also sets .ori to ori_null
+ */
+static ObjRecord *obj_new(void) 
+{
+    ObjRecord *orp;
+    
+    orp = obj_clear( nasm_malloc(sizeof(ObjRecord)) );
+    orp->ori = ori_null;
+    return (orp);
+}
+    
+/*
+ * Advance to the next record because the existing one is full or its x_size
+ * is incompatible.
+ * Any uncommited data is moved into the next record.
+ */
+static ObjRecord *obj_bump(ObjRecord *orp) 
+{
+    ObjRecord *nxt;
+    int used = orp->used;
+    int committed = orp->committed;
+
+    if (orp->up) {
+       *orp->up = nxt = obj_new();
+       nxt->ori = orp->ori;
+       nxt->type = orp->type;
+       nxt->up = orp->up;
+       nxt->back = orp;
+       memcpy( nxt->parm, orp->parm, sizeof(orp->parm));
+    } else
+       nxt = obj_emit(orp);
+
+    used -= committed;
+    if (used) {
+       nxt->committed = 1;
+       nxt->ori (nxt);
+       nxt->committed = nxt->used;
+       memcpy( nxt->buf + nxt->committed, orp->buf + committed, used);
+       nxt->used = nxt->committed + used;
+    }
+
+    return (nxt);
+}
+
+/*
+ * Advance to the next record if necessary to allow the next field to fit.
+ */
+static ObjRecord *obj_check(ObjRecord *orp, int size) 
+{
+    if (orp->used + size > RECORD_MAX)
+       orp = obj_bump(orp);
+
+    if (!orp->committed) {
+       orp->committed = 1;
+       orp->ori (orp);
+       orp->committed = orp->used;
+    }
+
+    return (orp);
+}
+
+/*
+ * All data written so far is commited to the current record (won't be moved to
+ * the next record in case of continuation).
+ */
+static ObjRecord *obj_commit(ObjRecord *orp) 
+{
+    orp->committed = orp->used;
+    return (orp);
+}
+
+/*
+ * Write a byte
+ */
+static ObjRecord *obj_byte(ObjRecord *orp, unsigned char val) 
+{
+    orp = obj_check(orp, 1);
+    orp->buf[orp->used] = val;
+    orp->used++;
+    return (orp);
+}
+
+/*
+ * Write a word
+ */
+static ObjRecord *obj_word(ObjRecord *orp, unsigned int val) 
+{
+    orp = obj_check(orp, 2);
+    orp->buf[orp->used] = val;
+    orp->buf[orp->used+1] = val >> 8;
+    orp->used += 2;
+    return (orp);
+}
+
+/*
+ * Write a reversed word
+ */
+static ObjRecord *obj_rword(ObjRecord *orp, unsigned int val) 
+{
+    orp = obj_check(orp, 2);
+    orp->buf[orp->used] = val >> 8;
+    orp->buf[orp->used+1] = val;
+    orp->used += 2;
+    return (orp);
+}
+
+/*
+ * Write a dword
+ */
+static ObjRecord *obj_dword(ObjRecord *orp, unsigned long val) 
+{
+    orp = obj_check(orp, 4);
+    orp->buf[orp->used] = val;
+    orp->buf[orp->used+1] = val >> 8;
+    orp->buf[orp->used+2] = val >> 16;
+    orp->buf[orp->used+3] = val >> 24;
+    orp->used += 4;
+    return (orp);
+}
+
+/*
+ * All fields of "size x" in one obj record must be the same size (either 16
+ * bits or 32 bits).  There is a one bit flag in each record which specifies
+ * which.
+ * This routine is used to force the current record to have the desired
+ * x_size.  x_size is normally automatic (using obj_x), so that this
+ * routine should be used outside obj_x, only to provide compatibility with
+ * linkers that have bugs in their processing of the size bit.
+ */
+
+static ObjRecord *obj_force(ObjRecord *orp, int x)
+{
+    if (orp->x_size == (x^48))
+       orp = obj_bump(orp);
+    orp->x_size = x;
+       return (orp);
+}
+
+/*
+ * This routine writes a field of size x.  The caller does not need to worry at
+ * all about whether 16-bits or 32-bits are required.
+ */
+static ObjRecord *obj_x(ObjRecord *orp, unsigned long val) 
+{
+    if (orp->type & 1)
+       orp->x_size = 32;
+    if (val > 0xFFFF)
+       orp = obj_force(orp, 32);
+    if (orp->x_size == 32)
+       return (obj_dword(orp, val));
+    orp->x_size = 16;
+    return (obj_word(orp, val));
+}
+
+/*
+ * Writes an index
+ */
+static ObjRecord *obj_index(ObjRecord *orp, unsigned int val) 
+{
+    if (val < 128)
+       return ( obj_byte(orp, val) );
+    return (obj_word(orp, (val>>8) | (val<<8) | 0x80));
+}
+
+/*
+ * Writes a variable length value
+ */
+static ObjRecord *obj_value(ObjRecord *orp, unsigned long val) 
+{
+    if (val <= 128)
+       return ( obj_byte(orp, val) );
+    if (val <= 0xFFFF) {
+       orp = obj_byte(orp, 129);
+       return ( obj_word(orp, val) );
+    }
+    if (val <= 0xFFFFFF)
+       return ( obj_dword(orp, (val<<8) + 132 ) );
+    orp = obj_byte(orp, 136);
+    return ( obj_dword(orp, val) );
+}
+
+/*
+ * Writes a counted string
+ */
+static ObjRecord *obj_name(ObjRecord *orp, char *name) 
+{
+    int len = strlen(name);
+    unsigned char *ptr;
+
+    orp = obj_check(orp, len+1);
+    ptr = orp->buf + orp->used;
+    *ptr++ = len;
+    orp->used += len+1;
+    if (obj_uppercase)
+       while (--len >= 0) {
+           *ptr++ = toupper(*name);
+           name++;
+    } else
+       memcpy(ptr, name, len);
+    return (orp);
+}
+
+/*
+ * Initializer for an LEDATA record.
+ * parm[0] = offset
+ * parm[1] = segment index
+ * During the use of a LEDATA ObjRecord, parm[0] is constantly updated to
+ * represent the offset that would be required if the record were split at the
+ * last commit point.
+ * parm[2] is a copy of parm[0] as it was when the current record was initted.
+ */
+static void ori_ledata(ObjRecord *orp) 
+{
+    obj_index (orp, orp->parm[1]);
+    orp->parm[2] = orp->parm[0];
+    obj_x (orp, orp->parm[0]);
+}
+
+/*
+ * Initializer for a PUBDEF record.
+ * parm[0] = group index
+ * parm[1] = segment index
+ * parm[2] = frame (only used when both indexes are zero)
+ */
+static void ori_pubdef(ObjRecord *orp) 
+{
+    obj_index (orp, orp->parm[0]);
+    obj_index (orp, orp->parm[1]);
+    if ( !(orp->parm[0] | orp->parm[1]) )
+       obj_word (orp, orp->parm[2]);
+}
+
+/*
+ * Initializer for a LINNUM record.
+ * parm[0] = group index
+ * parm[1] = segment index
+ */
+static void ori_linnum(ObjRecord *orp) 
+{
+    obj_index (orp, orp->parm[0]);
+    obj_index (orp, orp->parm[1]);
+}
+/*
+ * Initializer for a local vars record.
+ */
+static void ori_local(ObjRecord *orp) 
+{
+    obj_byte (orp, 0x40);
+    obj_byte (orp, dSYM);
+}
+
+/*
+ * Null initializer for records that continue without any header info
+ */
+static void ori_null(ObjRecord *orp) 
+{
+    (void) orp;  /* Do nothing */
+}
+
+/*
+ * This concludes the low level section of outobj.c
+ */
+
+static char obj_infile[FILENAME_MAX];
+
+static efunc error;
+static evalfunc evaluate;
+static ldfunc deflabel;
+static FILE *ofp;
+static long first_seg;
+static int any_segs;
+static int passtwo;
+static int arrindex;
+
+#define GROUP_MAX 256                 /* we won't _realistically_ have more
+                                       * than this many segs in a group */
+#define EXT_BLKSIZ 256                /* block size for externals list */
+
+struct Segment;                               /* need to know these structs exist */
+struct Group;
+
+struct LineNumber {
+    struct LineNumber *next;
+    struct Segment *segment;
+    long offset;
+    long lineno;
+};
+
+static struct FileName {
+    struct FileName *next;
+    char *name;
+    struct LineNumber *lnhead, **lntail;
+    int index;
+} *fnhead, **fntail;
+
+static struct Array {
+    struct Array *next;
+    unsigned size;
+    int basetype;
+} *arrhead, **arrtail;
+
+#define ARRAYBOT 31 /* magic number  for first array index */
+
+
+static struct Public {
+    struct Public *next;
+    char *name;
+    long offset;
+    long segment;                     /* only if it's far-absolute */
+    int type;                          /* only for local debug syms */
+} *fpubhead, **fpubtail, *last_defined;
+
+static struct External {
+    struct External *next;
+    char *name;
+    long commonsize;
+    long commonelem;                  /* element size if FAR, else zero */
+    int index;                        /* OBJ-file external index */
+    enum {
+       DEFWRT_NONE,                   /* no unusual default-WRT */
+       DEFWRT_STRING,                 /* a string we don't yet understand */
+       DEFWRT_SEGMENT,                /* a segment */
+       DEFWRT_GROUP                   /* a group */
+    } defwrt_type;
+    union {
+       char *string;
+       struct Segment *seg;
+       struct Group *grp;
+    } defwrt_ptr;
+    struct External *next_dws;        /* next with DEFWRT_STRING */
+} *exthead, **exttail, *dws;
+
+static int externals;
+
+static struct ExtBack {
+    struct ExtBack *next;
+    struct External *exts[EXT_BLKSIZ];
+} *ebhead, **ebtail;
+
+static struct Segment {
+    struct Segment *next;
+    long index;                               /* the NASM segment id */
+    long obj_index;                   /* the OBJ-file segment index */
+    struct Group *grp;                /* the group it belongs to */
+    unsigned long currentpos;
+    long align;                               /* can be SEG_ABS + absolute addr */
+    enum {
+       CMB_PRIVATE = 0,
+       CMB_PUBLIC = 2,
+       CMB_STACK = 5,
+       CMB_COMMON = 6
+    } combine;
+    long use32;                               /* is this segment 32-bit? */
+    struct Public *pubhead, **pubtail, *lochead, **loctail;
+    char *name;
+    char *segclass, *overlay;         /* `class' is a C++ keyword :-) */
+    ObjRecord *orp;
+} *seghead, **segtail, *obj_seg_needs_update;
+
+static struct Group {
+    struct Group *next;
+    char *name;
+    long index;                               /* NASM segment id */
+    long obj_index;                   /* OBJ-file group index */
+    long nentries;                    /* number of elements... */
+    long nindices;                    /* ...and number of index elts... */
+    union {
+       long index;
+       char *name;
+    } segs[GROUP_MAX];                /* ...in this */
+} *grphead, **grptail, *obj_grp_needs_update;
+
+static struct ImpDef {
+    struct ImpDef *next;
+    char *extname;
+    char *libname;
+    unsigned int impindex;
+    char *impname;
+} *imphead, **imptail;
+
+static struct ExpDef {
+    struct ExpDef *next;
+    char *intname;
+    char *extname;
+    unsigned int ordinal;
+    int flags;
+} *exphead, **exptail;
+
+#define EXPDEF_FLAG_ORDINAL  0x80
+#define EXPDEF_FLAG_RESIDENT 0x40
+#define EXPDEF_FLAG_NODATA   0x20
+#define EXPDEF_MASK_PARMCNT  0x1F
+
+static long obj_entry_seg, obj_entry_ofs;
+
+struct ofmt of_obj;
+
+/* The current segment */
+static struct Segment *current_seg;
+
+static long obj_segment (char *, int, int *);
+static void obj_write_file(int debuginfo);
+static int obj_directive (char *, char *, int);
+
+static void obj_init (FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
+{
+    ofp = fp;
+    error = errfunc;
+    evaluate = eval;
+    deflabel = ldef;
+    first_seg = seg_alloc();
+    any_segs = FALSE;
+    fpubhead = NULL;
+    fpubtail = &fpubhead;
+    exthead = NULL;
+    exttail = &exthead;
+    imphead = NULL;
+    imptail = &imphead;
+    exphead = NULL;
+    exptail = &exphead;
+    dws = NULL;
+    externals = 0;
+    ebhead = NULL;
+    ebtail = &ebhead;
+    seghead = obj_seg_needs_update = NULL;
+    segtail = &seghead;
+    grphead = obj_grp_needs_update = NULL;
+    grptail = &grphead;
+    obj_entry_seg = NO_SEG;
+    obj_uppercase = FALSE;
+    obj_use32 = FALSE;
+    passtwo = 0;
+    current_seg = NULL;
+
+    of_obj.current_dfmt->init (&of_obj,NULL,fp,errfunc);
+}
+
+static int obj_set_info(enum geninfo type, char **val)
+{
+    (void) type;
+    (void) val;
+
+    return 0;
+}
+static void obj_cleanup (int debuginfo) 
+{
+    obj_write_file(debuginfo);
+    of_obj.current_dfmt->cleanup();
+    fclose (ofp);
+    while (seghead) {
+       struct Segment *segtmp = seghead;
+       seghead = seghead->next;
+       while (segtmp->pubhead) {
+           struct Public *pubtmp = segtmp->pubhead;
+           segtmp->pubhead = pubtmp->next;
+           nasm_free (pubtmp->name);
+           nasm_free (pubtmp);
+       }
+       nasm_free (segtmp->segclass);
+       nasm_free (segtmp->overlay);
+       nasm_free (segtmp);
+    }
+    while (fpubhead) {
+       struct Public *pubtmp = fpubhead;
+       fpubhead = fpubhead->next;
+       nasm_free (pubtmp->name);
+       nasm_free (pubtmp);
+    }
+    while (exthead) {
+       struct External *exttmp = exthead;
+       exthead = exthead->next;
+       nasm_free (exttmp);
+    }
+    while (imphead) {
+       struct ImpDef *imptmp = imphead;
+       imphead = imphead->next;
+       nasm_free (imptmp->extname);
+       nasm_free (imptmp->libname);
+       nasm_free (imptmp->impname);   /* nasm_free won't mind if it's NULL */
+       nasm_free (imptmp);
+    }
+    while (exphead) {
+       struct ExpDef *exptmp = exphead;
+       exphead = exphead->next;
+       nasm_free (exptmp->extname);
+       nasm_free (exptmp->intname);
+       nasm_free (exptmp);
+    }
+    while (ebhead) {
+       struct ExtBack *ebtmp = ebhead;
+       ebhead = ebhead->next;
+       nasm_free (ebtmp);
+    }
+    while (grphead) {
+       struct Group *grptmp = grphead;
+       grphead = grphead->next;
+       nasm_free (grptmp);
+    }
+}
+
+static void obj_ext_set_defwrt (struct External *ext, char *id) 
+{
+    struct Segment *seg;
+    struct Group *grp;
+
+    for (seg = seghead; seg; seg = seg->next)
+       if (!strcmp(seg->name, id)) {
+           ext->defwrt_type = DEFWRT_SEGMENT;
+           ext->defwrt_ptr.seg = seg;
+           nasm_free (id);
+           return;
+       }
+
+    for (grp = grphead; grp; grp = grp->next)
+       if (!strcmp(grp->name, id)) {
+           ext->defwrt_type = DEFWRT_GROUP;
+           ext->defwrt_ptr.grp = grp;
+           nasm_free (id);
+           return;
+       }
+
+    ext->defwrt_type = DEFWRT_STRING;
+    ext->defwrt_ptr.string = id;
+    ext->next_dws = dws;
+    dws = ext;
+}
+
+static void obj_deflabel (char *name, long segment,
+                         long offset, int is_global, char *special) 
+{
+    /*
+     * We have three cases:
+     *
+     * (i) `segment' is a segment-base. If so, set the name field
+     * for the segment or group structure it refers to, and then
+     * return.
+     *
+     * (ii) `segment' is one of our segments, or a SEG_ABS segment.
+     * Save the label position for later output of a PUBDEF record.
+     * (Or a MODPUB, if we work out how.)
+     *
+     * (iii) `segment' is not one of our segments. Save the label
+     * position for later output of an EXTDEF, and also store a
+     * back-reference so that we can map later references to this
+     * segment number to the external index.
+     */
+    struct External *ext;
+    struct ExtBack *eb;
+    struct Segment *seg;
+    int i;
+    int used_special = FALSE;         /* have we used the special text? */
+
+#if defined(DEBUG) && DEBUG>2
+fprintf(stderr, " obj_deflabel: %s, seg=%ld, off=%ld, is_global=%d, %s\n",
+      name, segment, offset, is_global, special);
+#endif
+
+    /*
+     * If it's a special-retry from pass two, discard it.
+     */
+    if (is_global == 3)
+       return;
+
+    /*
+     * First check for the double-period, signifying something
+     * unusual.
+     */
+    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
+       if (!strcmp(name, "..start")) {
+           obj_entry_seg = segment;
+           obj_entry_ofs = offset;
+           return;
+       }
+       error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
+    }
+
+    /*
+     * Case (i):
+     */
+    if (obj_seg_needs_update) {
+       obj_seg_needs_update->name = name;
+       return;
+    } else if (obj_grp_needs_update) {
+       obj_grp_needs_update->name = name;
+       return;
+    }
+    if (segment < SEG_ABS && segment != NO_SEG && segment % 2)
+       return;
+
+    if (segment >= SEG_ABS || segment == NO_SEG) {
+       /*
+        * SEG_ABS subcase of (ii).
+        */
+       if (is_global) {
+           struct Public *pub;
+
+           pub = *fpubtail = nasm_malloc(sizeof(*pub));
+           fpubtail = &pub->next;
+           pub->next = NULL;
+           pub->name = nasm_strdup(name);
+           pub->offset = offset;
+           pub->segment = (segment == NO_SEG ? 0 : segment & ~SEG_ABS);
+       }
+       if (special)
+           error(ERR_NONFATAL, "OBJ supports no special symbol features"
+                 " for this symbol type");
+       return;
+    }
+
+    /*
+     * If `any_segs' is still FALSE, we might need to define a
+     * default segment, if they're trying to declare a label in
+     * `first_seg'.
+     */
+    if (!any_segs && segment == first_seg) {
+       int tempint;                   /* ignored */
+       if (segment != obj_segment("__NASMDEFSEG", 2, &tempint))
+           error (ERR_PANIC, "strange segment conditions in OBJ driver");
+    }
+
+    for (seg = seghead; seg && is_global; seg = seg->next)
+       if (seg->index == segment) {
+           struct Public *loc = nasm_malloc (sizeof(*loc));
+           /*
+            * Case (ii). Maybe MODPUB someday?
+            */
+           *seg->pubtail = loc;
+           seg->pubtail = &loc->next;
+           loc->next = NULL;
+           loc->name = nasm_strdup(name);
+           loc->offset = offset;
+                  
+           if (special)
+               error(ERR_NONFATAL, "OBJ supports no special symbol features"
+                     " for this symbol type");
+           return;
+       }
+
+    /*
+     * Case (iii).
+     */
+    if (is_global) {
+        ext = *exttail = nasm_malloc(sizeof(*ext));
+        ext->next = NULL;
+        exttail = &ext->next;
+        ext->name = name;
+       /* Place by default all externs into the current segment */
+        ext->defwrt_type = DEFWRT_NONE;
+       if (current_seg) {
+           if (current_seg->grp) {
+               ext->defwrt_type = DEFWRT_GROUP;
+               ext->defwrt_ptr.grp = current_seg->grp;
+           } else {
+               ext->defwrt_type = DEFWRT_SEGMENT;
+               ext->defwrt_ptr.seg = current_seg;
+           }
+       }
+        if (is_global == 2) {
+           ext->commonsize = offset;
+           ext->commonelem = 1;               /* default FAR */
+        } else
+           ext->commonsize = 0;
+    }
+    else
+       return;
+
+    /*
+     * Now process the special text, if any, to find default-WRT
+     * specifications and common-variable element-size and near/far
+     * specifications.
+     */
+    while (special && *special) {
+       used_special = TRUE;
+
+       /*
+        * We might have a default-WRT specification.
+        */
+       if (!nasm_strnicmp(special, "wrt", 3)) {
+           char *p;
+           int len;
+           special += 3;
+           special += strspn(special, " \t");
+           p = nasm_strndup(special, len = strcspn(special, ":"));
+           obj_ext_set_defwrt (ext, p);
+           special += len;
+           if (*special && *special != ':')
+               error(ERR_NONFATAL, "`:' expected in special symbol"
+                     " text for `%s'", ext->name);
+           else if (*special == ':')
+               special++;
+       }
+
+       /*
+        * The NEAR or FAR keywords specify nearness or
+        * farness. FAR gives default element size 1.
+        */
+       if (!nasm_strnicmp(special, "far", 3)) {
+           if (ext->commonsize)
+               ext->commonelem = 1;
+           else
+               error(ERR_NONFATAL, "`%s': `far' keyword may only be applied"
+                     " to common variables\n", ext->name);
+           special += 3;
+           special += strspn(special, " \t");
+       } else if (!nasm_strnicmp(special, "near", 4)) {
+           if (ext->commonsize)
+               ext->commonelem = 0;
+           else
+               error(ERR_NONFATAL, "`%s': `far' keyword may only be applied"
+                     " to common variables\n", ext->name);
+           special += 4;
+           special += strspn(special, " \t");
+       }
+
+       /*
+        * If it's a common, and anything else remains on the line
+        * before a further colon, evaluate it as an expression and
+        * use that as the element size. Forward references aren't
+        * allowed.
+        */
+       if (*special == ':')
+           special++;
+       else if (*special) {
+           if (ext->commonsize) {
+               expr *e;
+               struct tokenval tokval;
+
+               stdscan_reset();
+               stdscan_bufptr = special;
+               tokval.t_type = TOKEN_INVALID;
+               e = evaluate(stdscan, NULL, &tokval, NULL, 1, error, NULL);
+               if (e) {
+                   if (!is_simple(e))
+                       error (ERR_NONFATAL, "cannot use relocatable"
+                              " expression as common-variable element size");
+                   else
+                       ext->commonelem = reloc_value(e);
+               }
+               special = stdscan_bufptr;
+           } else {
+               error (ERR_NONFATAL, "`%s': element-size specifications only"
+                      " apply to common variables", ext->name);
+               while (*special && *special != ':')
+                   special++;
+               if (*special == ':')
+                   special++;
+           }
+       }
+    }
+
+    i = segment/2;
+    eb = ebhead;
+    if (!eb) {
+       eb = *ebtail = nasm_malloc(sizeof(*eb));
+       eb->next = NULL;
+       ebtail = &eb->next;
+    }
+    while (i > EXT_BLKSIZ) {
+       if (eb && eb->next)
+           eb = eb->next;
+       else {
+           eb = *ebtail = nasm_malloc(sizeof(*eb));
+           eb->next = NULL;
+           ebtail = &eb->next;
+       }
+       i -= EXT_BLKSIZ;
+    }
+    eb->exts[i] = ext;
+    ext->index = ++externals;
+
+    if (special && !used_special)
+       error(ERR_NONFATAL, "OBJ supports no special symbol features"
+             " for this symbol type");
+}
+
+/* forward declaration */
+static void obj_write_fixup (ObjRecord *orp, int bytes,
+    int segrel, long seg, long wrt, struct Segment *segto);
+
+static void obj_out (long segto, void *data, unsigned long type,
+                    long segment, long wrt) 
+{
+    unsigned long size, realtype;
+    unsigned char *ucdata;
+    long ldata;
+    struct Segment *seg;
+    ObjRecord *orp;
+
+    /*
+     * handle absolute-assembly (structure definitions)
+     */
+    if (segto == NO_SEG) {
+       if ((type & OUT_TYPMASK) != OUT_RESERVE)
+           error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
+                  " space");
+       return;
+    }
+
+    /*
+     * If `any_segs' is still FALSE, we must define a default
+     * segment.
+     */
+    if (!any_segs) {
+       int tempint;                   /* ignored */
+       if (segto != obj_segment("__NASMDEFSEG", 2, &tempint))
+           error (ERR_PANIC, "strange segment conditions in OBJ driver");
+    }
+
+    /*
+     * Find the segment we are targetting.
+     */
+    for (seg = seghead; seg; seg = seg->next)
+       if (seg->index == segto)
+           break;
+    if (!seg)
+       error (ERR_PANIC, "code directed to nonexistent segment?");
+
+    orp = seg->orp;
+    orp->parm[0] = seg->currentpos;
+
+    size = type & OUT_SIZMASK;
+    realtype = type & OUT_TYPMASK;
+    if (realtype == OUT_RAWDATA) {
+       ucdata = data;
+       while (size > 0) {
+           unsigned int len;
+           orp = obj_check(seg->orp, 1);
+           len = RECORD_MAX - orp->used;
+           if (len > size)
+               len = size;
+           memcpy (orp->buf+orp->used, ucdata, len);
+           orp->committed = orp->used += len;
+           orp->parm[0] = seg->currentpos += len;
+           ucdata += len;
+           size -= len;
+       }
+    }
+    else if (realtype == OUT_ADDRESS || realtype == OUT_REL2ADR ||
+            realtype == OUT_REL4ADR) 
+    {
+       int rsize;
+
+       if (segment == NO_SEG && realtype != OUT_ADDRESS)
+           error(ERR_NONFATAL, "relative call to absolute address not"
+                 " supported by OBJ format");
+       if (segment >= SEG_ABS)
+           error(ERR_NONFATAL, "far-absolute relocations not supported"
+                 " by OBJ format");
+       ldata = *(long *)data;
+       if (realtype == OUT_REL2ADR) {
+           ldata += (size-2);
+           size = 2;
+       }
+       if (realtype == OUT_REL4ADR) {
+           ldata += (size-4);
+           size = 4;
+       }
+       if (size == 2)
+           orp = obj_word (orp, ldata);
+       else
+           orp = obj_dword (orp, ldata);
+       rsize = size;
+       if (segment < SEG_ABS && (segment != NO_SEG && segment % 2) &&
+           size == 4) {
+           /*
+            * This is a 4-byte segment-base relocation such as
+            * `MOV EAX,SEG foo'. OBJ format can't actually handle
+            * these, but if the constant term has the 16 low bits
+            * zero, we can just apply a 2-byte segment-base
+            * relocation to the low word instead.
+            */
+           rsize = 2;
+           if (ldata & 0xFFFF)
+               error(ERR_NONFATAL, "OBJ format cannot handle complex"
+                     " dword-size segment base references");
+       }
+       if (segment != NO_SEG)
+           obj_write_fixup (orp, rsize,
+                            (realtype == OUT_ADDRESS  ? 0x4000 : 0),
+                            segment, wrt, seg);
+       seg->currentpos += size;
+    } else if (realtype == OUT_RESERVE) {
+       if (orp->committed)
+           orp = obj_bump(orp);
+       seg->currentpos += size;
+    }
+    obj_commit(orp);
+}
+
+static void obj_write_fixup (ObjRecord *orp, int bytes,
+    int segrel, long seg, long wrt, struct Segment *segto)
+{
+    int locat, method;
+    int base;
+    long tidx, fidx;
+    struct Segment *s = NULL;
+    struct Group *g = NULL;
+    struct External *e = NULL;
+    ObjRecord *forp;
+
+    if (bytes == 1) {
+       error(ERR_NONFATAL, "`obj' output driver does not support"
+             " one-byte relocations");
+       return;
+    }
+
+    forp = orp->child;
+    if (forp == NULL) {
+       orp->child = forp = obj_new();
+       forp->up = &(orp->child);
+       /* We should choose between FIXUPP and FIXU32 record type */
+       /* If we're targeting a 32-bit segment, use a FIXU32 record */
+       if (segto->use32)
+           forp->type = FIXU32;
+       else
+           forp->type = FIXUPP;
+    }
+
+    if (seg % 2) {
+       base = TRUE;
+       locat = FIX_16_SELECTOR;
+       seg--;
+       if (bytes != 2)
+           error(ERR_PANIC, "OBJ: 4-byte segment base fixup got"
+                 " through sanity check");
+    }
+    else {
+       base = FALSE;
+       locat = (bytes == 2) ? FIX_16_OFFSET : FIX_32_OFFSET;
+       if (!segrel)
+           /*
+            * There is a bug in tlink that makes it process self relative
+            * fixups incorrectly if the x_size doesn't match the location
+            * size.
+            */
+           forp = obj_force(forp, bytes<<3);
+    }
+
+    forp = obj_rword (forp, locat | segrel | (orp->parm[0]-orp->parm[2]));
+
+    tidx = fidx = -1, method = 0;      /* placate optimisers */
+
+    /*
+     * See if we can find the segment ID in our segment list. If
+     * so, we have a T4 (LSEG) target.
+     */
+    for (s = seghead; s; s = s->next)
+       if (s->index == seg)
+           break;
+    if (s)
+       method = 4, tidx = s->obj_index;
+    else {
+       for (g = grphead; g; g = g->next)
+           if (g->index == seg)
+               break;
+       if (g)
+           method = 5, tidx = g->obj_index;
+       else {
+           long i = seg/2;
+           struct ExtBack *eb = ebhead;
+           while (i > EXT_BLKSIZ) {
+               if (eb)
+                   eb = eb->next;
+               else
+                   break;
+               i -= EXT_BLKSIZ;
+           }
+           if (eb)
+               method = 6, e = eb->exts[i], tidx = e->index;
+           else
+               error(ERR_PANIC,
+                     "unrecognised segment value in obj_write_fixup");
+       }
+    }
+
+    /*
+     * If no WRT given, assume the natural default, which is method
+     * F5 unless:
+     *
+     * - we are doing an OFFSET fixup for a grouped segment, in
+     *   which case we require F1 (group).
+     *
+     * - we are doing an OFFSET fixup for an external with a
+     *   default WRT, in which case we must honour the default WRT.
+     */
+    if (wrt == NO_SEG) {
+       if (!base && s && s->grp)
+           method |= 0x10, fidx = s->grp->obj_index;
+       else if (!base && e && e->defwrt_type != DEFWRT_NONE) {
+           if (e->defwrt_type == DEFWRT_SEGMENT)
+               method |= 0x00, fidx = e->defwrt_ptr.seg->obj_index;
+           else if (e->defwrt_type == DEFWRT_GROUP)
+               method |= 0x10, fidx = e->defwrt_ptr.grp->obj_index;
+           else {
+               error(ERR_NONFATAL, "default WRT specification for"
+                     " external `%s' unresolved", e->name);
+               method |= 0x50, fidx = -1; /* got to do _something_ */
+           }
+       } else
+           method |= 0x50, fidx = -1;
+    } else {
+       /*
+        * See if we can find the WRT-segment ID in our segment
+        * list. If so, we have a F0 (LSEG) frame.
+        */
+       for (s = seghead; s; s = s->next)
+           if (s->index == wrt-1)
+               break;
+       if (s)
+           method |= 0x00, fidx = s->obj_index;
+       else {
+           for (g = grphead; g; g = g->next)
+               if (g->index == wrt-1)
+                   break;
+           if (g)
+               method |= 0x10, fidx = g->obj_index;
+           else {
+               long i = wrt/2;
+               struct ExtBack *eb = ebhead;
+               while (i > EXT_BLKSIZ) {
+                   if (eb)
+                       eb = eb->next;
+                   else
+                       break;
+                   i -= EXT_BLKSIZ;
+               }
+               if (eb)
+                   method |= 0x20, fidx = eb->exts[i]->index;
+               else
+                   error(ERR_PANIC,
+                         "unrecognised WRT value in obj_write_fixup");
+           }
+       }
+    }
+
+    forp = obj_byte (forp, method);
+    if (fidx != -1)
+       forp = obj_index (forp, fidx);
+    forp = obj_index (forp, tidx);
+    obj_commit (forp);
+}
+
+static long obj_segment (char *name, int pass, int *bits) 
+{
+    /*
+     * We call the label manager here to define a name for the new
+     * segment, and when our _own_ label-definition stub gets
+     * called in return, it should register the new segment name
+     * using the pointer it gets passed. That way we save memory,
+     * by sponging off the label manager.
+     */
+#if defined(DEBUG) && DEBUG>=3
+fprintf(stderr," obj_segment: < %s >, pass=%d, *bits=%d\n",
+       name, pass, *bits);
+#endif     
+    if (!name) {
+       *bits = 16;
+       current_seg = NULL;
+       return first_seg;
+    } else {
+       struct Segment *seg;
+       struct Group *grp;
+       struct External **extp;
+       int obj_idx, i, attrs, rn_error;
+       char *p;
+
+       /*
+        * Look for segment attributes.
+        */
+       attrs = 0;
+       while (*name == '.')
+           name++;                    /* hack, but a documented one */
+       p = name;
+       while (*p && !isspace(*p))
+           p++;
+       if (*p) {
+           *p++ = '\0';
+           while (*p && isspace(*p))
+               *p++ = '\0';
+       }
+       while (*p) {
+           while (*p && !isspace(*p))
+               p++;
+           if (*p) {
+               *p++ = '\0';
+               while (*p && isspace(*p))
+                   *p++ = '\0';
+           }
+
+           attrs++;
+       }
+
+       obj_idx = 1;
+       for (seg = seghead; seg; seg = seg->next) {
+           obj_idx++;
+           if (!strcmp(seg->name, name)) {
+               if (attrs > 0 && pass == 1)
+                   error(ERR_WARNING, "segment attributes specified on"
+                         " redeclaration of segment: ignoring");
+               if (seg->use32)
+                   *bits = 32;
+               else
+                   *bits = 16;
+               current_seg = seg;
+               return seg->index;
+           }
+       }
+
+       *segtail = seg = nasm_malloc(sizeof(*seg));
+       seg->next = NULL;
+       segtail = &seg->next;
+       seg->index = (any_segs ? seg_alloc() : first_seg);
+       seg->obj_index = obj_idx;
+       seg->grp = NULL;
+       any_segs = TRUE;
+       seg->name = NULL;
+       seg->currentpos = 0;
+       seg->align = 1;                /* default */
+       seg->use32 = FALSE;            /* default */
+       seg->combine = CMB_PUBLIC;     /* default */
+       seg->segclass = seg->overlay = NULL;
+       seg->pubhead = NULL;
+       seg->pubtail = &seg->pubhead;
+       seg->lochead = NULL;
+       seg->loctail = &seg->lochead;
+       seg->orp = obj_new();
+       seg->orp->up = &(seg->orp);
+       seg->orp->ori = ori_ledata;
+       seg->orp->type = LEDATA;
+       seg->orp->parm[1] = obj_idx;
+
+       /*
+        * Process the segment attributes.
+        */
+       p = name;
+       while (attrs--) {
+           p += strlen(p);
+           while (!*p) p++;
+
+           /*
+            * `p' contains a segment attribute.
+            */
+           if (!nasm_stricmp(p, "private"))
+               seg->combine = CMB_PRIVATE;
+           else if (!nasm_stricmp(p, "public"))
+               seg->combine = CMB_PUBLIC;
+           else if (!nasm_stricmp(p, "common"))
+               seg->combine = CMB_COMMON;
+           else if (!nasm_stricmp(p, "stack"))
+               seg->combine = CMB_STACK;
+           else if (!nasm_stricmp(p, "use16"))
+               seg->use32 = FALSE;
+           else if (!nasm_stricmp(p, "use32"))
+               seg->use32 = TRUE;
+           else if (!nasm_stricmp(p, "flat")) {
+               /*
+                * This segment is an OS/2 FLAT segment. That means
+                * that its default group is group FLAT, even if
+                * the group FLAT does not explicitly _contain_ the
+                * segment.
+                * 
+                * When we see this, we must create the group
+                * `FLAT', containing no segments, if it does not
+                * already exist; then we must set the default
+                * group of this segment to be the FLAT group.
+                */
+               struct Group *grp;
+               for (grp = grphead; grp; grp = grp->next)
+                   if (!strcmp(grp->name, "FLAT"))
+                       break;
+               if (!grp) {
+                   obj_directive ("group", "FLAT", 1);
+                   for (grp = grphead; grp; grp = grp->next)
+                       if (!strcmp(grp->name, "FLAT"))
+                           break;
+                   if (!grp)
+                       error (ERR_PANIC, "failure to define FLAT?!");
+               }
+               seg->grp = grp;
+           } else if (!nasm_strnicmp(p, "class=", 6))
+               seg->segclass = nasm_strdup(p+6);
+           else if (!nasm_strnicmp(p, "overlay=", 8))
+               seg->overlay = nasm_strdup(p+8);
+           else if (!nasm_strnicmp(p, "align=", 6)) {
+               seg->align = readnum(p+6, &rn_error);
+               if (rn_error) {
+                   seg->align = 1;
+                   error (ERR_NONFATAL, "segment alignment should be"
+                          " numeric");
+               }
+               switch ((int) seg->align) {
+                 case 1:              /* BYTE */
+                 case 2:              /* WORD */
+                 case 4:              /* DWORD */
+                 case 16:             /* PARA */
+                 case 256:            /* PAGE */
+                 case 4096:           /* PharLap extension */
+                   break;
+                 case 8:
+                   error(ERR_WARNING, "OBJ format does not support alignment"
+                         " of 8: rounding up to 16");
+                   seg->align = 16;
+                   break;
+                 case 32:
+                 case 64:
+                 case 128:
+                   error(ERR_WARNING, "OBJ format does not support alignment"
+                         " of %d: rounding up to 256", seg->align);
+                   seg->align = 256;
+                   break;
+                 case 512:
+                 case 1024:
+                 case 2048:
+                   error(ERR_WARNING, "OBJ format does not support alignment"
+                         " of %d: rounding up to 4096", seg->align);
+                   seg->align = 4096;
+                   break;
+                 default:
+                   error(ERR_NONFATAL, "invalid alignment value %d",
+                         seg->align);
+                   seg->align = 1;
+                   break;
+               }
+           } else if (!nasm_strnicmp(p, "absolute=", 9)) {
+               seg->align = SEG_ABS + readnum(p+9, &rn_error);
+               if (rn_error)
+                   error (ERR_NONFATAL, "argument to `absolute' segment"
+                          " attribute should be numeric");
+           }
+       }
+
+        /* We need to know whenever we have at least one 32-bit segment */
+        obj_use32 |= seg->use32;
+
+       obj_seg_needs_update = seg;
+       if (seg->align >= SEG_ABS)
+           deflabel (name, NO_SEG, seg->align - SEG_ABS,
+                     NULL, FALSE, FALSE, &of_obj, error);
+       else
+           deflabel (name, seg->index+1, 0L,
+                     NULL, FALSE, FALSE, &of_obj, error);
+       obj_seg_needs_update = NULL;
+
+       /*
+        * See if this segment is defined in any groups.
+        */
+       for (grp = grphead; grp; grp = grp->next) {
+           for (i = grp->nindices; i < grp->nentries; i++) {
+               if (!strcmp(grp->segs[i].name, seg->name)) {
+                   nasm_free (grp->segs[i].name);
+                   grp->segs[i] = grp->segs[grp->nindices];
+                   grp->segs[grp->nindices++].index = seg->obj_index;
+                   if (seg->grp)
+                       error(ERR_WARNING, "segment `%s' is already part of"
+                             " a group: first one takes precedence",
+                             seg->name);
+                   else
+                       seg->grp = grp;
+               }
+           }
+       }
+
+       /*
+        * Walk through the list of externals with unresolved
+        * default-WRT clauses, and resolve any that point at this
+        * segment.
+        */
+       extp = &dws;
+       while (*extp) {
+           if ((*extp)->defwrt_type == DEFWRT_STRING &&
+               !strcmp((*extp)->defwrt_ptr.string, seg->name)) {
+               nasm_free((*extp)->defwrt_ptr.string);
+               (*extp)->defwrt_type = DEFWRT_SEGMENT;
+               (*extp)->defwrt_ptr.seg = seg;
+               *extp = (*extp)->next_dws;
+           } else
+               extp = &(*extp)->next_dws;
+       }
+
+       if (seg->use32)
+           *bits = 32;
+       else
+           *bits = 16;
+       current_seg = seg;
+       return seg->index;
+    }
+}
+
+static int obj_directive (char *directive, char *value, int pass) 
+{
+    if (!strcmp(directive, "group")) {
+       char *p, *q, *v;
+       if (pass == 1) {
+           struct Group *grp;
+           struct Segment *seg;
+           struct External **extp;
+           int obj_idx;
+
+           q = value;
+           while (*q == '.')
+               q++;                   /* hack, but a documented one */
+           v = q;
+           while (*q && !isspace(*q))
+               q++;
+           if (isspace(*q)) {
+               *q++ = '\0';
+               while (*q && isspace(*q))
+                   q++;
+           }
+           /*
+            * Here we used to sanity-check the group directive to
+            * ensure nobody tried to declare a group containing no
+            * segments. However, OS/2 does this as standard
+            * practice, so the sanity check has been removed.
+            *
+            * if (!*q) {
+            *     error(ERR_NONFATAL,"GROUP directive contains no segments");
+            *     return 1;
+            * }
+            */
+
+           obj_idx = 1;
+           for (grp = grphead; grp; grp = grp->next) {
+               obj_idx++;
+               if (!strcmp(grp->name, v)) {
+                   error(ERR_NONFATAL, "group `%s' defined twice", v);
+                   return 1;
+               }
+           }
+
+           *grptail = grp = nasm_malloc(sizeof(*grp));
+           grp->next = NULL;
+           grptail = &grp->next;
+           grp->index = seg_alloc();
+           grp->obj_index = obj_idx;
+           grp->nindices = grp->nentries = 0;
+           grp->name = NULL;
+
+           obj_grp_needs_update = grp;
+           deflabel (v, grp->index+1, 0L,
+                     NULL, FALSE, FALSE, &of_obj, error);
+           obj_grp_needs_update = NULL;
+
+           while (*q) {
+               p = q;
+               while (*q && !isspace(*q))
+                   q++;
+               if (isspace(*q)) {
+                   *q++ = '\0';
+                   while (*q && isspace(*q))
+                       q++;
+               }
+               /*
+                * Now p contains a segment name. Find it.
+                */
+               for (seg = seghead; seg; seg = seg->next)
+                   if (!strcmp(seg->name, p))
+                       break;
+               if (seg) {
+                   /*
+                    * We have a segment index. Shift a name entry
+                    * to the end of the array to make room.
+                    */
+                   grp->segs[grp->nentries++] = grp->segs[grp->nindices];
+                   grp->segs[grp->nindices++].index = seg->obj_index;
+                   if (seg->grp)
+                       error(ERR_WARNING, "segment `%s' is already part of"
+                             " a group: first one takes precedence",
+                             seg->name);
+                   else
+                       seg->grp = grp;
+               } else {
+                   /*
+                    * We have an as-yet undefined segment.
+                    * Remember its name, for later.
+                    */
+                   grp->segs[grp->nentries++].name = nasm_strdup(p);
+               }
+           }
+
+           /*
+            * Walk through the list of externals with unresolved
+            * default-WRT clauses, and resolve any that point at
+            * this group.
+            */
+           extp = &dws;
+           while (*extp) {
+               if ((*extp)->defwrt_type == DEFWRT_STRING &&
+                   !strcmp((*extp)->defwrt_ptr.string, grp->name)) {
+                   nasm_free((*extp)->defwrt_ptr.string);
+                   (*extp)->defwrt_type = DEFWRT_GROUP;
+                   (*extp)->defwrt_ptr.grp = grp;
+                   *extp = (*extp)->next_dws;
+           } else
+                   extp = &(*extp)->next_dws;
+           }
+       }
+       return 1;
+    }
+    if (!strcmp(directive, "uppercase")) {
+       obj_uppercase = TRUE;
+       return 1;
+    }
+    if (!strcmp(directive, "import")) {
+       char *q, *extname, *libname, *impname;
+
+       if (pass == 2)
+           return 1;                  /* ignore in pass two */
+       extname = q = value;
+       while (*q && !isspace(*q))
+           q++;
+       if (isspace(*q)) {
+           *q++ = '\0';
+           while (*q && isspace(*q))
+               q++;
+       }
+
+       libname = q;
+       while (*q && !isspace(*q))
+           q++;
+       if (isspace(*q)) {
+           *q++ = '\0';
+           while (*q && isspace(*q))
+               q++;
+       }
+
+       impname = q;
+
+       if (!*extname || !*libname)
+           error(ERR_NONFATAL, "`import' directive requires symbol name"
+                 " and library name");
+       else {
+           struct ImpDef *imp;
+           int err = FALSE;
+
+           imp = *imptail = nasm_malloc(sizeof(struct ImpDef));
+           imptail = &imp->next;
+           imp->next = NULL;
+           imp->extname = nasm_strdup(extname);
+           imp->libname = nasm_strdup(libname);
+           imp->impindex = readnum(impname, &err);
+           if (!*impname || err)
+               imp->impname = nasm_strdup(impname);
+           else
+               imp->impname = NULL;
+       }
+
+       return 1;
+    }
+    if (!strcmp(directive, "export")) {
+       char *q, *extname, *intname, *v;
+       struct ExpDef *export;
+       int flags = 0;
+       unsigned int ordinal = 0;
+
+       if (pass == 2)
+           return 1;                  /* ignore in pass two */
+       intname = q = value;
+       while (*q && !isspace(*q))
+           q++;
+       if (isspace(*q)) {
+           *q++ = '\0';
+           while (*q && isspace(*q))
+               q++;
+       }
+
+       extname = q;
+       while (*q && !isspace(*q))
+           q++;
+       if (isspace(*q)) {
+           *q++ = '\0';
+           while (*q && isspace(*q))
+               q++;
+       }
+
+       if (!*intname) {
+           error(ERR_NONFATAL, "`export' directive requires export name");
+           return 1;
+       }
+       if (!*extname) {
+           extname = intname;
+           intname = "";
+       }
+       while (*q) {
+           v = q;
+           while (*q && !isspace(*q))
+               q++;
+           if (isspace(*q)) {
+               *q++ = '\0';
+               while (*q && isspace(*q))
+                   q++;
+           }
+           if (!nasm_stricmp(v, "resident"))
+               flags |= EXPDEF_FLAG_RESIDENT;
+           else if (!nasm_stricmp(v, "nodata"))
+               flags |= EXPDEF_FLAG_NODATA;
+           else if (!nasm_strnicmp(v, "parm=", 5)) {
+               int err = FALSE;
+               flags |= EXPDEF_MASK_PARMCNT & readnum(v+5, &err);
+               if (err) {
+                   error(ERR_NONFATAL,
+                         "value `%s' for `parm' is non-numeric", v+5);
+                   return 1;
+               }
+           } else {
+               int err = FALSE;
+               ordinal = readnum(v, &err);
+               if (err) {
+                   error(ERR_NONFATAL, "unrecognised export qualifier `%s'",
+                         v);
+                   return 1;
+               }
+               flags |= EXPDEF_FLAG_ORDINAL;
+           }
+       }
+
+       export = *exptail = nasm_malloc(sizeof(struct ExpDef));
+       exptail = &export->next;
+       export->next = NULL;
+       export->extname = nasm_strdup(extname);
+       export->intname = nasm_strdup(intname);
+       export->ordinal = ordinal;
+       export->flags = flags;
+
+       return 1;
+    }
+    return 0;
+}
+
+static long obj_segbase (long segment) 
+{
+    struct Segment *seg;
+
+    /*
+     * Find the segment in our list.
+     */
+    for (seg = seghead; seg; seg = seg->next)
+       if (seg->index == segment-1)
+           break;
+
+    if (!seg) {
+       /*
+        * Might be an external with a default WRT.
+        */
+       long i = segment/2;
+       struct ExtBack *eb = ebhead;
+       struct External *e;
+
+       while (i > EXT_BLKSIZ) {
+           if (eb)
+               eb = eb->next;
+           else
+               break;
+           i -= EXT_BLKSIZ;
+       }
+       if (eb) {
+           e = eb->exts[i];
+           if (e->defwrt_type == DEFWRT_NONE)
+               return segment;        /* fine */
+           else if (e->defwrt_type == DEFWRT_SEGMENT)
+               return e->defwrt_ptr.seg->index+1;
+           else if (e->defwrt_type == DEFWRT_GROUP)
+               return e->defwrt_ptr.grp->index+1;
+           else
+               return NO_SEG;         /* can't tell what it is */
+       }
+
+       return segment;                /* not one of ours - leave it alone */
+    }
+
+    if (seg->align >= SEG_ABS)
+       return seg->align;             /* absolute segment */
+    if (seg->grp)
+       return seg->grp->index+1;      /* grouped segment */
+
+    return segment;                   /* no special treatment */
+}
+
+static void obj_filename (char *inname, char *outname, efunc error) 
+{
+    strcpy(obj_infile, inname);
+    standard_extension (inname, outname, ".obj", error);
+}
+
+static void obj_write_file (int debuginfo) 
+{
+    struct Segment *seg, *entry_seg_ptr = 0;
+    struct FileName *fn;
+    struct LineNumber *ln;
+    struct Group *grp;
+    struct Public *pub, *loc;
+    struct External *ext;
+    struct ImpDef *imp;
+    struct ExpDef *export;
+    static char boast[] = "The Netwide Assembler " NASM_VER;
+    int lname_idx;
+    ObjRecord *orp;
+
+    /*
+     * Write the THEADR module header.
+     */
+    orp = obj_new();
+    orp->type = THEADR;
+    obj_name (orp, obj_infile);
+    obj_emit2 (orp);
+
+    /*
+     * Write the NASM boast comment.
+     */
+    orp->type = COMENT;
+    obj_rword (orp, 0);   /* comment type zero */
+    obj_name (orp, boast);
+    obj_emit2 (orp);
+
+    orp->type = COMENT;
+    /*
+     * Write the IMPDEF records, if any.
+     */
+    for (imp = imphead; imp; imp = imp->next) {
+       obj_rword (orp, 0xA0);   /* comment class A0 */
+       obj_byte (orp, 1);   /* subfunction 1: IMPDEF */
+       if (imp->impname)
+           obj_byte (orp, 0);   /* import by name */
+       else
+           obj_byte (orp, 1);   /* import by ordinal */
+       obj_name (orp, imp->extname);
+       obj_name (orp, imp->libname);
+       if (imp->impname)
+           obj_name (orp, imp->impname);
+       else
+           obj_word (orp, imp->impindex);
+       obj_emit2 (orp);
+    }
+
+    /*
+     * Write the EXPDEF records, if any.
+     */
+    for (export = exphead; export; export = export->next) {
+       obj_rword (orp, 0xA0);   /* comment class A0 */
+       obj_byte (orp, 2);   /* subfunction 2: EXPDEF */
+       obj_byte (orp, export->flags);
+       obj_name (orp, export->extname);
+       obj_name (orp, export->intname);
+       if (export->flags & EXPDEF_FLAG_ORDINAL)
+           obj_word (orp, export->ordinal);
+       obj_emit2 (orp);
+    }
+
+    /* we're using extended OMF if we put in debug info*/
+    if (debuginfo) {
+      orp->type = COMENT;
+      obj_byte (orp, 0x40);
+      obj_byte (orp, dEXTENDED);
+      obj_emit2 (orp);
+    }
+
+    /*
+     * Write the first LNAMES record, containing LNAME one, which
+     * is null. Also initialise the LNAME counter.
+     */
+    orp->type = LNAMES;
+    obj_byte (orp, 0);
+    lname_idx = 1;
+    /*
+     * Write some LNAMES for the segment names
+     */
+    for (seg = seghead; seg; seg = seg->next) {
+       orp = obj_name (orp, seg->name);
+       if (seg->segclass)
+           orp = obj_name (orp, seg->segclass);
+       if (seg->overlay)
+           orp = obj_name (orp, seg->overlay);
+       obj_commit (orp);
+    }
+    /*
+     * Write some LNAMES for the group names
+     */
+    for (grp = grphead; grp; grp = grp->next) {
+       orp = obj_name (orp, grp->name);
+       obj_commit (orp);
+    }
+    obj_emit (orp);
+
+
+    /*
+     * Write the SEGDEF records.
+     */
+    orp->type = SEGDEF;
+    for (seg = seghead; seg; seg = seg->next) {
+       int acbp;
+       unsigned long seglen = seg->currentpos;
+
+       acbp = (seg->combine << 2);    /* C field */
+
+       if (seg->use32)
+           acbp |= 0x01;              /* P bit is Use32 flag */
+       else if (seglen == 0x10000L) {
+           seglen = 0;                /* This special case may be needed for old linkers */
+           acbp |= 0x02;              /* B bit */
+       }
+
+
+       /* A field */
+       if (seg->align >= SEG_ABS)
+           /* acbp |= 0x00 */;
+       else if (seg->align >= 4096) {
+           if (seg->align > 4096)
+               error(ERR_NONFATAL, "segment `%s' requires more alignment"
+                     " than OBJ format supports", seg->name);
+           acbp |= 0xC0;              /* PharLap extension */
+       } else if (seg->align >= 256) {
+           acbp |= 0x80;
+       } else if (seg->align >= 16) {
+           acbp |= 0x60;
+       } else if (seg->align >= 4) {
+           acbp |= 0xA0;
+       } else if (seg->align >= 2) {
+           acbp |= 0x40;
+       } else
+           acbp |= 0x20;
+
+       obj_byte (orp, acbp);
+       if (seg->align & SEG_ABS) {
+           obj_x (orp, seg->align - SEG_ABS);  /* Frame */
+           obj_byte (orp, 0);  /* Offset */
+       }
+       obj_x (orp, seglen);
+       obj_index (orp, ++lname_idx);
+       obj_index (orp, seg->segclass ? ++lname_idx : 1);
+       obj_index (orp, seg->overlay ? ++lname_idx : 1);
+       obj_emit2 (orp);
+    }
+
+    /*
+     * Write the GRPDEF records.
+     */
+    orp->type = GRPDEF;
+    for (grp = grphead; grp; grp = grp->next) {
+       int i;
+
+       if (grp->nindices != grp->nentries) {
+           for (i = grp->nindices; i < grp->nentries; i++) {
+               error(ERR_NONFATAL, "group `%s' contains undefined segment"
+                     " `%s'", grp->name, grp->segs[i].name);
+               nasm_free (grp->segs[i].name);
+               grp->segs[i].name = NULL;
+           }
+       }
+       obj_index (orp, ++lname_idx);
+       for (i = 0; i < grp->nindices; i++) {
+           obj_byte (orp, 0xFF);
+           obj_index (orp, grp->segs[i].index);
+       }
+       obj_emit2 (orp);
+    }
+
+    /*
+     * Write the PUBDEF records: first the ones in the segments,
+     * then the far-absolutes.
+     */
+    orp->type = PUBDEF;
+    orp->ori = ori_pubdef;
+    for (seg = seghead; seg; seg = seg->next) {
+       orp->parm[0] = seg->grp ? seg->grp->obj_index : 0;
+       orp->parm[1] = seg->obj_index;
+       for (pub = seg->pubhead; pub; pub = pub->next) {
+           orp = obj_name (orp, pub->name);
+           orp = obj_x (orp, pub->offset);
+           orp = obj_byte (orp, 0);  /* type index */
+           obj_commit (orp);
+       }
+       obj_emit (orp);
+    }
+    orp->parm[0] = 0;
+    orp->parm[1] = 0;
+    for (pub = fpubhead; pub; pub = pub->next) {   /* pub-crawl :-) */
+       if (orp->parm[2] != pub->segment) {
+           obj_emit (orp);
+           orp->parm[2] = pub->segment;
+       }
+       orp = obj_name (orp, pub->name);
+       orp = obj_x (orp, pub->offset);
+       orp = obj_byte (orp, 0);  /* type index */
+       obj_commit (orp);
+    }
+    obj_emit (orp);
+
+    /*
+     * Write the EXTDEF and COMDEF records, in order.
+     */
+    orp->ori = ori_null;
+    for (ext = exthead; ext; ext = ext->next) {
+       if (ext->commonsize == 0) {
+           if (orp->type != EXTDEF) {
+               obj_emit (orp);
+               orp->type = EXTDEF;
+           }
+           orp = obj_name (orp, ext->name);
+           orp = obj_index (orp, 0);
+       } else {
+           if (orp->type != COMDEF) {
+               obj_emit (orp);
+               orp->type = COMDEF;
+           }
+           orp = obj_name (orp, ext->name);
+           orp = obj_index (orp, 0);
+           if (ext->commonelem) {
+               orp = obj_byte (orp, 0x61);/* far communal */
+               orp = obj_value (orp, (ext->commonsize / ext->commonelem));
+               orp = obj_value (orp, ext->commonelem);
+           } else {
+               orp = obj_byte (orp, 0x62);/* near communal */
+               orp = obj_value (orp, ext->commonsize);
+           }
+       }
+       obj_commit (orp);
+    }
+    obj_emit (orp);
+
+    /*
+     * Write a COMENT record stating that the linker's first pass
+     * may stop processing at this point. Exception is if our
+     * MODEND record specifies a start point, in which case,
+     * according to some variants of the documentation, this COMENT
+     * should be omitted. So we'll omit it just in case.
+     * But, TASM puts it in all the time so if we are using
+     * TASM debug stuff we are putting it in
+     */
+    if (debuginfo || obj_entry_seg == NO_SEG) {
+       orp->type = COMENT;
+        obj_byte (orp, 0x40);
+        obj_byte (orp, dLINKPASS);
+       obj_byte (orp, 1);
+       obj_emit2 (orp);
+    } 
+
+    /*
+     * 1) put out the compiler type
+     * 2) Put out the type info.  The only type we are using is near label #19
+     */
+    if (debuginfo) {
+      int i;
+      struct Array *arrtmp = arrhead;
+      orp->type = COMENT;
+      obj_byte (orp, 0x40);
+      obj_byte (orp, dCOMPDEF);
+      obj_byte (orp, 4);
+      obj_byte (orp, 0);
+      obj_emit2 (orp);
+
+      obj_byte (orp, 0x40);
+      obj_byte (orp, dTYPEDEF);
+      obj_word (orp, 0x18); /* type # for linking */
+      obj_word (orp, 6);    /* size of type */
+      obj_byte (orp, 0x2a); /* absolute type for debugging */
+      obj_emit2 (orp);
+      obj_byte (orp, 0x40);
+      obj_byte (orp, dTYPEDEF);
+      obj_word (orp, 0x19); /* type # for linking */
+      obj_word (orp, 0);    /* size of type */
+      obj_byte (orp, 0x24); /* absolute type for debugging */
+      obj_byte (orp, 0);    /* near/far specifier */
+      obj_emit2 (orp);
+      obj_byte (orp, 0x40);
+      obj_byte (orp, dTYPEDEF);
+      obj_word (orp, 0x1A); /* type # for linking */
+      obj_word (orp, 0);    /* size of type */
+      obj_byte (orp, 0x24); /* absolute type for debugging */
+      obj_byte (orp, 1);    /* near/far specifier */
+      obj_emit2 (orp);
+      obj_byte (orp, 0x40);
+      obj_byte (orp, dTYPEDEF);
+      obj_word (orp, 0x1b); /* type # for linking */
+      obj_word (orp, 0);    /* size of type */
+      obj_byte (orp, 0x23); /* absolute type for debugging */
+      obj_byte (orp, 0);
+      obj_byte (orp, 0);
+      obj_byte (orp, 0);
+      obj_emit2 (orp);
+      obj_byte (orp, 0x40);
+      obj_byte (orp, dTYPEDEF);
+      obj_word (orp, 0x1c); /* type # for linking */
+      obj_word (orp, 0);    /* size of type */
+      obj_byte (orp, 0x23); /* absolute type for debugging */
+      obj_byte (orp, 0);
+      obj_byte (orp, 4);
+      obj_byte (orp, 0);
+      obj_emit2 (orp);
+      obj_byte (orp, 0x40);
+      obj_byte (orp, dTYPEDEF);
+      obj_word (orp, 0x1d); /* type # for linking */
+      obj_word (orp, 0);    /* size of type */
+      obj_byte (orp, 0x23); /* absolute type for debugging */
+      obj_byte (orp, 0);
+      obj_byte (orp, 1);
+      obj_byte (orp, 0);
+      obj_emit2 (orp);
+      obj_byte (orp, 0x40);
+      obj_byte (orp, dTYPEDEF);
+      obj_word (orp, 0x1e); /* type # for linking */
+      obj_word (orp, 0);    /* size of type */
+      obj_byte (orp, 0x23); /* absolute type for debugging */
+      obj_byte (orp, 0);
+      obj_byte (orp, 5);
+      obj_byte (orp, 0);
+      obj_emit2 (orp);
+
+      /* put out the array types */
+      for (i= ARRAYBOT; i < arrindex; i++) {
+        obj_byte (orp, 0x40);
+       obj_byte (orp, dTYPEDEF);
+       obj_word (orp, i ); /* type # for linking */
+       obj_word (orp, arrtmp->size);    /* size of type */
+       obj_byte (orp, 0x1A); /* absolute type for debugging (array)*/
+       obj_byte (orp, arrtmp->basetype ); /* base type */
+       obj_emit2 (orp);
+        arrtmp = arrtmp->next ;
+      }
+    }
+    /*
+     * write out line number info with a LINNUM record
+     * switch records when we switch segments, and output the
+     * file in a pseudo-TASM fashion.  The record switch is naive; that
+     * is that one file may have many records for the same segment
+     * if there are lots of segment switches
+     */
+    if (fnhead && debuginfo) {
+       seg = fnhead->lnhead->segment;
+
+       for (fn = fnhead; fn; fn = fn->next) {
+           /* write out current file name */
+            orp->type = COMENT;
+            orp->ori = ori_null;
+           obj_byte (orp, 0x40);
+           obj_byte (orp, dFILNAME);
+            obj_byte( orp,0);
+            obj_name( orp,fn->name);
+            obj_dword(orp, 0);
+           obj_emit2 (orp);
+
+           /* write out line numbers this file */
+
+            orp->type = LINNUM;
+            orp->ori = ori_linnum;
+           for (ln = fn->lnhead; ln; ln = ln->next) {
+               if (seg != ln->segment) {
+                   /* if we get here have to flush the buffer and start
+                     * a new record for a new segment
+                    */
+                   seg = ln->segment;
+                   obj_emit ( orp );
+               }
+               orp->parm[0] = seg->grp ? seg->grp->obj_index : 0;
+               orp->parm[1] = seg->obj_index;
+               orp = obj_word(orp, ln->lineno);
+                orp = obj_x(orp, ln->offset);
+               obj_commit (orp);
+           }
+           obj_emit (orp);
+       }
+    }
+    /*
+     * we are going to locate the entry point segment now
+     * rather than wait until the MODEND record, because,
+     * then we can output a special symbol to tell where the
+     * entry point is.
+     *
+     */
+    if (obj_entry_seg != NO_SEG) {
+       for (seg = seghead; seg; seg = seg->next) {
+           if (seg->index == obj_entry_seg) {
+                entry_seg_ptr = seg;
+               break;
+           }
+       }
+       if (!seg)
+           error(ERR_NONFATAL, "entry point is not in this module");
+    }
+
+    /*
+     * get ready to put out symbol records
+     */
+    orp->type = COMENT;
+    orp->ori = ori_local;
+   
+    /*
+     * put out a symbol for the entry point
+     * no dots in this symbol, because, borland does
+     * not (officially) support dots in label names
+     * and I don't know what various versions of TLINK will do
+     */
+    if (debuginfo && obj_entry_seg != NO_SEG) {
+        orp = obj_name (orp,"start_of_program");
+       orp = obj_word (orp,0x19);  /* type: near label */
+       orp = obj_index (orp, seg->grp ? seg->grp->obj_index : 0);
+       orp = obj_index (orp, seg->obj_index);
+       orp = obj_x (orp, obj_entry_ofs);
+       obj_commit (orp);
+    } 
+    /*
+     * put out the local labels
+     */
+    for (seg = seghead; seg && debuginfo; seg = seg->next) {
+        /* labels this seg */
+        for (loc = seg->lochead; loc; loc = loc->next) {
+            orp = obj_name (orp,loc->name);
+           orp = obj_word (orp, loc->type);
+           orp = obj_index (orp, seg->grp ? seg->grp->obj_index : 0);
+           orp = obj_index (orp, seg->obj_index);
+           orp = obj_x (orp,loc->offset);
+           obj_commit (orp);
+        }
+    }
+    if (orp->used)
+        obj_emit (orp);
+
+    /*
+     * Write the LEDATA/FIXUPP pairs.
+     */
+    for (seg = seghead; seg; seg = seg->next) {
+       obj_emit (seg->orp);
+       nasm_free (seg->orp);
+    }
+
+    /*
+     * Write the MODEND module end marker.
+     */
+    orp->type = obj_use32 ? MODE32 : MODEND;
+    orp->ori = ori_null;
+    if (entry_seg_ptr) {
+       orp->type = entry_seg_ptr->use32 ? MODE32 : MODEND;
+       obj_byte (orp, 0xC1);
+       seg = entry_seg_ptr;
+       if (seg->grp) {
+           obj_byte (orp, 0x10);
+           obj_index (orp, seg->grp->obj_index);
+       } else {
+           /*
+            * the below changed to prevent TLINK crashing.
+            * Previous more efficient version read:
+            *
+            *  obj_byte (orp, 0x50);
+            */
+           obj_byte (orp, 0x00);
+           obj_index (orp, seg->obj_index);
+       }
+       obj_index (orp, seg->obj_index);
+       obj_x (orp, obj_entry_ofs);
+    } else
+       obj_byte (orp, 0);
+    obj_emit2 (orp);
+    nasm_free (orp);
+}
+
+void obj_fwrite(ObjRecord *orp) 
+{
+    unsigned int cksum, len;
+    unsigned char *ptr;
+
+    cksum = orp->type;
+    if (orp->x_size == 32)
+       cksum |= 1;
+    fputc (cksum, ofp);
+    len = orp->committed+1;
+    cksum += (len & 0xFF) + ((len>>8) & 0xFF);
+    fwriteshort (len, ofp);
+    fwrite (orp->buf, 1, len-1, ofp);
+    for (ptr=orp->buf; --len; ptr++)
+       cksum += *ptr;
+    fputc ( (-cksum) & 0xFF, ofp);
+}
+
+static char *obj_stdmac[] = {
+    "%define __SECT__ [section .text]",
+    "%imacro group 1+.nolist",
+    "[group %1]",
+    "%endmacro",
+    "%imacro uppercase 0+.nolist",
+    "[uppercase %1]",
+    "%endmacro",
+    "%imacro export 1+.nolist",
+    "[export %1]",
+    "%endmacro",
+    "%imacro import 1+.nolist",
+    "[import %1]",
+    "%endmacro",
+    "%macro __NASM_CDecl__ 1",
+    "%endmacro",
+    NULL
+};
+
+void dbgbi_init(struct ofmt * of, void * id, FILE * fp, efunc error)
+{
+    (void) of;
+    (void) id;
+    (void) fp;
+    (void) error;
+
+    fnhead = NULL;
+    fntail = &fnhead;
+    arrindex = ARRAYBOT ;
+    arrhead = NULL;
+    arrtail = &arrhead;
+}
+static void dbgbi_cleanup(void)
+{
+    struct Segment *segtmp;
+    while (fnhead) {
+       struct FileName *fntemp = fnhead;
+       while (fnhead->lnhead) {
+           struct LineNumber *lntemp = fnhead->lnhead;
+           fnhead->lnhead = lntemp->next;
+           nasm_free( lntemp);
+       }
+       fnhead = fnhead->next;
+       nasm_free (fntemp->name);
+       nasm_free (fntemp);
+    }
+    for (segtmp=seghead; segtmp; segtmp=segtmp->next) {
+       while (segtmp->lochead) {
+           struct Public *loctmp = segtmp->lochead;
+           segtmp->lochead = loctmp->next;
+           nasm_free (loctmp->name);
+           nasm_free (loctmp);
+       }
+    }
+    while (arrhead) {
+       struct Array *arrtmp = arrhead;
+        arrhead = arrhead->next;
+        nasm_free (arrtmp);
+    }
+}
+
+static void dbgbi_linnum (const char *lnfname, long lineno, long segto)
+{
+    struct FileName *fn;
+    struct LineNumber *ln;
+    struct Segment *seg;
+
+    if (segto == NO_SEG)
+       return;
+
+    /*
+     * If `any_segs' is still FALSE, we must define a default
+     * segment.
+     */
+    if (!any_segs) {
+       int tempint;                   /* ignored */
+       if (segto != obj_segment("__NASMDEFSEG", 2, &tempint))
+           error (ERR_PANIC, "strange segment conditions in OBJ driver");
+    }
+
+    /*
+     * Find the segment we are targetting.
+     */
+    for (seg = seghead; seg; seg = seg->next)
+       if (seg->index == segto)
+           break;
+    if (!seg)
+       error (ERR_PANIC, "lineno directed to nonexistent segment?");
+
+/*    for (fn = fnhead; fn; fn = fnhead->next) */
+    for (fn = fnhead; fn; fn = fn->next) /* fbk - Austin Lunnen - John Fine*/
+       if (!nasm_stricmp(lnfname,fn->name))
+           break;
+    if (!fn) {
+       fn = nasm_malloc ( sizeof( *fn));
+       fn->name = nasm_malloc ( strlen(lnfname) + 1) ;
+        strcpy (fn->name,lnfname);
+       fn->lnhead = NULL;
+       fn->lntail = & fn->lnhead;
+       fn->next = NULL;
+       *fntail = fn;
+       fntail = &fn->next;
+    }
+    ln = nasm_malloc ( sizeof( *ln));
+    ln->segment = seg;
+    ln->offset = seg->currentpos;
+    ln->lineno = lineno;
+    ln->next = NULL;
+    *fn->lntail = ln;
+    fn->lntail = &ln->next;
+
+}
+static void dbgbi_deflabel (char *name, long segment,
+                         long offset, int is_global, char *special) 
+{
+    struct Segment *seg;
+
+    (void) special;
+
+    /*
+     * If it's a special-retry from pass two, discard it.
+     */
+    if (is_global == 3)
+       return;
+
+    /*
+     * First check for the double-period, signifying something
+     * unusual.
+     */
+    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
+       return;
+    }
+
+    /*
+     * Case (i):
+     */
+    if (obj_seg_needs_update) {
+       return;
+    } else if (obj_grp_needs_update) {
+       return;
+    }
+    if (segment < SEG_ABS && segment != NO_SEG && segment % 2)
+       return;
+
+    if (segment >= SEG_ABS || segment == NO_SEG) {
+       return;
+    }
+
+    /*
+     * If `any_segs' is still FALSE, we might need to define a
+     * default segment, if they're trying to declare a label in
+     * `first_seg'.  But the label should exist due to a prior
+     * call to obj_deflabel so we can skip that.
+     */
+
+    for (seg = seghead; seg; seg = seg->next)
+       if (seg->index == segment) {
+           struct Public *loc = nasm_malloc (sizeof(*loc));
+           /*
+            * Case (ii). Maybe MODPUB someday?
+            */
+           last_defined = *seg->loctail = loc;
+           seg->loctail = &loc->next;
+           loc->next = NULL;
+           loc->name = nasm_strdup(name);
+           loc->offset = offset;
+       }
+}
+static void dbgbi_typevalue (long type)
+{
+    int vsize;
+    int elem = TYM_ELEMENTS(type);
+    type = TYM_TYPE(type);
+
+    if (!last_defined)
+       return;
+
+    switch (type) {
+       case TY_BYTE:
+           last_defined->type = 8; /* unsigned char */
+           vsize = 1;
+           break;
+       case TY_WORD:
+           last_defined->type = 10; /* unsigned word */
+           vsize = 2;
+           break;
+       case TY_DWORD:
+           last_defined->type = 12; /* unsigned dword */
+           vsize = 4;
+           break;
+       case TY_FLOAT:
+           last_defined->type = 14; /* float */
+           vsize = 4;
+           break;
+       case TY_QWORD:
+           last_defined->type = 15; /* qword */
+           vsize = 8;
+           break;
+       case TY_TBYTE:
+           last_defined->type = 16; /* TBYTE */
+           vsize = 10;
+           break;
+       default:
+           last_defined->type = 0x19; /*label */
+           vsize = 0;
+           break;
+    }
+                
+    if (elem > 1) {
+        struct Array *arrtmp = nasm_malloc (sizeof(*arrtmp));
+        int vtype = last_defined->type;
+        arrtmp->size = vsize * elem;
+        arrtmp->basetype = vtype;
+        arrtmp->next = NULL;
+        last_defined->type = arrindex++;
+        *arrtail = arrtmp;
+        arrtail = & (arrtmp->next);
+    }
+    last_defined = NULL;
+}
+static void dbgbi_output (int output_type, void *param)
+{
+    (void) output_type;
+    (void) param;
+}
+static struct dfmt borland_debug_form = {
+    "Borland Debug Records",
+    "borland",
+    dbgbi_init,
+    dbgbi_linnum,
+    dbgbi_deflabel,
+    null_debug_routine,
+    dbgbi_typevalue,
+    dbgbi_output,
+    dbgbi_cleanup,
+};
+
+static struct dfmt *borland_debug_arr[3] = {
+       &borland_debug_form,
+       &null_debug_form,
+       NULL
+};
+
+struct ofmt of_obj = {
+    "MS-DOS 16-bit/32-bit OMF object files",
+    "obj",
+    NULL,
+    borland_debug_arr,
+    &null_debug_form,
+    obj_stdmac,
+    obj_init,
+    obj_set_info,
+    obj_out,
+    obj_deflabel,
+    obj_segment,
+    obj_segbase,
+    obj_directive,
+    obj_filename,
+    obj_cleanup
+};
+#endif /* OF_OBJ */
diff --git a/output/outrdf.c b/output/outrdf.c
new file mode 100644 (file)
index 0000000..d9989e5
--- /dev/null
@@ -0,0 +1,539 @@
+/* outrdf.c    output routines for the Netwide Assembler to produce
+ *             RDOFF format object files (which are intended mainly
+ *             for use in proprietary projects, as the code to load and
+ *             execute them is very simple). They will also be used
+ *             for device drivers and possibly some executable files
+ *             in the MOSCOW operating system. See Rdoff.txt for
+ *             details.
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "nasm.h"
+#include "nasmlib.h"
+#include "outform.h"
+
+/* VERBOSE_WARNINGS: define this to add some extra warnings... */
+#define VERBOSE_WARNINGS     
+
+#ifdef OF_RDF
+
+typedef short int16;   /* not sure if this will be required to be altered
+                          at all... best to typedef it just in case */
+
+static const char *RDOFFId = "RDOFF1"; /* written to start of RDOFF files */
+
+/* the records that can be found in the RDOFF header */
+
+/* Note that whenever a segment is referred to in the RDOFF file, its number
+ * is always half of the segment number that NASM uses to refer to it; this
+ * is because NASM only allocates even numbered segments, so as to not
+ * waste any of the 16 bits of segment number written to the file - this
+ * allows up to 65533 external labels to be defined; otherwise it would be
+ * 32764. */
+
+struct RelocRec {
+  char type;           /* must be 1 */
+  char segment;        /* only 0 for code, or 1 for data supported,
+                        * but add 64 for relative refs (ie do not require
+                        * reloc @ loadtime, only linkage) */
+  long offset;         /* from start of segment in which reference is loc'd */
+  char length;         /* 1 2 or 4 bytes */
+  int16        refseg;         /* segment to which reference refers to */
+};
+
+struct ImportRec {
+  char         type;           /* must be 2 */
+  int16        segment;        /* segment number allocated to the label for reloc
+                        * records - label is assumed to be at offset zero
+                        * in this segment, so linker must fix up with offset
+                        * of segment and of offset within segment */
+  char label[33];      /* zero terminated... should be written to file until
+                        * the zero, but not after it - max len = 32 chars */
+};
+
+struct ExportRec {
+  char type;           /* must be 3 */
+  char segment;        /* segment referred to (0/1) */
+  long offset;         /* offset within segment */
+  char label[33];      /* zero terminated as above. max len = 32 chars */
+};
+
+struct DLLRec {
+  char type;           /* must be 4 */
+  char libname[128];   /* name of library to link with at load time */
+};
+
+struct BSSRec {
+  char type;           /* must be 5 */
+  long amount;         /* number of bytes BSS to reserve */
+};
+
+/* code for managing buffers needed to seperate code and data into individual
+ * sections until they are ready to be written to the file.
+ * We'd better hope that it all fits in memory else we're buggered... */
+
+#define BUF_BLOCK_LEN 4088             /* selected to match page size (4096)
+                                         * on 80x86 machines for efficiency */
+
+typedef struct memorybuffer {
+  int length;
+  char buffer[BUF_BLOCK_LEN];
+  struct memorybuffer *next;
+} memorybuffer;
+
+static memorybuffer * newmembuf(void){
+  memorybuffer * t;
+
+  t = nasm_malloc(sizeof(memorybuffer));
+
+  t->length = 0;
+  t->next = NULL;
+  return t;
+}
+
+static void membufwrite(memorybuffer *b, void *data, int bytes) {
+  int16 w;
+  long l;
+
+  if (b->next) {       /* memory buffer full - use next buffer */
+    membufwrite(b->next,data,bytes);
+    return;
+  }
+  if ((bytes < 0 && b->length - bytes > BUF_BLOCK_LEN)
+      || (bytes > 0 && b->length + bytes > BUF_BLOCK_LEN)) {
+
+    /* buffer full and no next allocated... allocate and initialise next
+     * buffer */
+
+    b->next = newmembuf();
+    membufwrite(b->next,data,bytes);
+    return;
+  }
+
+  switch(bytes) {
+  case -4:             /* convert to little-endian */
+    l = * (long *) data ;
+    b->buffer[b->length++] = l & 0xFF;
+    l >>= 8 ;
+    b->buffer[b->length++] = l & 0xFF;
+    l >>= 8 ;
+    b->buffer[b->length++] = l & 0xFF;
+    l >>= 8 ;
+    b->buffer[b->length++] = l & 0xFF;
+    break;
+
+  case -2:
+    w = * (int16 *) data ;
+    b->buffer[b->length++] = w & 0xFF;
+    w >>= 8 ;
+    b->buffer[b->length++] = w & 0xFF;
+    break;
+
+  default:
+    while(bytes--) {
+      b->buffer[b->length++] = *(* (unsigned char **) &data);
+
+      (* (unsigned char **) &data)++ ;
+    }
+    break;
+  }
+}
+
+static void membufdump(memorybuffer *b,FILE *fp)
+{
+  if (!b) return;
+
+  fwrite (b->buffer, 1, b->length, fp);
+
+  membufdump(b->next,fp);
+}
+
+static int membuflength(memorybuffer *b)
+{
+  if (!b) return 0;
+  return b->length + membuflength(b->next);
+}
+
+static void freemembuf(memorybuffer *b)
+{
+  if (!b) return;
+  freemembuf(b->next);
+  nasm_free(b);
+}
+
+/***********************************************************************
+ * Actual code to deal with RDOFF ouput format begins here...
+ */
+
+/* global variables set during the initialisation phase */
+
+static memorybuffer *seg[2];   /* seg 0 = code, seg 1 = data */
+static memorybuffer *header;   /* relocation/import/export records */
+
+static FILE *ofile;
+
+static efunc error;
+
+static int segtext,segdata,segbss;
+static long bsslength;
+
+static void rdf_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
+{
+  ofile = fp;
+  error = errfunc;
+  seg[0] = newmembuf();
+  seg[1] = newmembuf();
+  header = newmembuf();
+  segtext = seg_alloc();
+  segdata = seg_alloc();
+  segbss = seg_alloc();
+  if (segtext != 0 || segdata != 2 || segbss != 4)
+    error(ERR_PANIC,"rdf segment numbers not allocated as expected (%d,%d,%d)",
+         segtext,segdata,segbss);
+  bsslength=0;
+}
+
+static long rdf_section_names(char *name, int pass, int *bits)
+{
+  /*
+   * Default is 32 bits.
+   */
+  if (!name)
+    *bits = 32;
+
+  if (!name) return 0;
+  if (!strcmp(name, ".text"))          return 0;
+  else if (!strcmp(name, ".data"))     return 2;
+  else if (!strcmp(name, ".bss"))      return 4;
+  else
+    return NO_SEG;
+}
+
+static void write_reloc_rec(struct RelocRec *r)
+{
+  if (r->refseg != NO_SEG && (r->refseg & 1))
+    error (ERR_NONFATAL, "RDF format does not support segment base"
+          " references");
+
+  r->refseg >>= 1;    /* adjust segment nos to RDF rather than NASM */
+
+  membufwrite(header,&r->type,1);
+  membufwrite(header,&r->segment,1);
+  membufwrite(header,&r->offset,-4);
+  membufwrite(header,&r->length,1);
+  membufwrite(header,&r->refseg,-2);   /* 9 bytes written */
+}
+
+static void write_export_rec(struct ExportRec *r)
+{
+  r->segment >>= 1;
+
+  membufwrite(header,&r->type,1);
+  membufwrite(header,&r->segment,1);
+  membufwrite(header,&r->offset,-4);
+  membufwrite(header,r->label,strlen(r->label) + 1);
+}
+
+static void write_import_rec(struct ImportRec *r)
+{
+  r->segment >>= 1;
+
+  membufwrite(header,&r->type,1);
+  membufwrite(header,&r->segment,-2);
+  membufwrite(header,r->label,strlen(r->label) + 1);
+}
+
+static void write_bss_rec(struct BSSRec *r)
+{
+    membufwrite(header,&r->type,1);
+    membufwrite(header,&r->amount,-4);
+}
+
+static void write_dll_rec(struct DLLRec *r)
+{
+    membufwrite(header,&r->type,1);
+    membufwrite(header,r->libname,strlen(r->libname) + 1);
+}
+
+static void rdf_deflabel(char *name, long segment, long offset,
+                        int is_global, char *special)
+{
+  struct ExportRec r;
+  struct ImportRec ri;
+#ifdef VERBOSE_WARNINGS
+  static int warned_common = 0;
+#endif
+
+  if (special)
+    error (ERR_NONFATAL, "RDOFF format does not support any"
+          " special symbol types");
+
+  if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
+    error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
+    return;
+  }
+
+  if (is_global == 2) {
+#ifdef VERBOSE_WARNINGS
+    if (!warned_common) {
+      error(ERR_WARNING,"common declarations not supported: using extern");
+      warned_common = 1;
+    }
+#endif
+    is_global = 1;
+  }
+
+  if (segment > 4) {   /* EXTERN declaration */
+    ri.type = 2;
+    ri.segment = segment;
+    strncpy(ri.label,name,32);
+    ri.label[32] = 0;
+    write_import_rec(&ri);
+  } else if (is_global) {
+    r.type = 3;
+    r.segment = segment;
+    r.offset = offset;
+    strncpy(r.label,name,32);
+    r.label[32] = 0;
+    write_export_rec(&r);
+  }
+}
+
+static void rdf_out (long segto, void *data, unsigned long type,
+                    long segment, long wrt)
+{
+  long bytes = type & OUT_SIZMASK;
+  struct RelocRec rr;
+  unsigned char databuf[4],*pd;
+
+  if (segto == NO_SEG) {
+      if ((type & OUT_TYPMASK) != OUT_RESERVE)
+         error (ERR_NONFATAL, "attempt to assemble code in ABSOLUTE space");
+      return;
+  }
+
+  segto >>= 1;    /* convert NASM segment no to RDF number */
+
+  if (segto != 0 && segto != 1 && segto != 2) {
+    error(ERR_NONFATAL,"specified segment not supported by rdf output format");
+    return;
+  }
+
+  if (wrt != NO_SEG) {
+    wrt = NO_SEG;                     /* continue to do _something_ */
+    error (ERR_NONFATAL, "WRT not supported by rdf output format");
+  }
+
+  type &= OUT_TYPMASK;
+
+  if (segto == 2 && type != OUT_RESERVE)
+  {
+      error(ERR_NONFATAL, "BSS segments may not be initialised");
+
+      /* just reserve the space for now... */
+
+      if (type == OUT_REL2ADR)
+       bytes = 2;
+      else
+       bytes = 4;
+      type = OUT_RESERVE;
+  }
+
+  if (type == OUT_RESERVE) {
+      if (segto == 2)          /* BSS segment space reserverd */
+         bsslength += bytes;
+      else
+       while (bytes --)
+           membufwrite(seg[segto],databuf,1);
+  }
+  else if (type == OUT_RAWDATA) {
+      if (segment != NO_SEG)
+         error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
+      membufwrite(seg[segto],data,bytes);
+  }
+  else if (type == OUT_ADDRESS) {
+
+    /* if segment == NO_SEG then we are writing an address of an
+       object within the same segment - do not produce reloc rec. */
+
+    if (segment != NO_SEG)
+    {
+
+       /* it's an address, so we must write a relocation record */
+
+       rr.type = 1;            /* type signature */
+       rr.segment = segto;             /* segment we're currently in */
+       rr.offset = membuflength(seg[segto]);   /* current offset */
+       rr.length = bytes;              /* length of reference */
+       rr.refseg = segment;    /* segment referred to */
+       write_reloc_rec(&rr);
+    }
+
+    pd = databuf;      /* convert address to little-endian */
+    if (bytes == 2)
+      WRITESHORT (pd, *(long *)data);
+    else
+      WRITELONG (pd, *(long *)data);
+
+    membufwrite(seg[segto],databuf,bytes);
+
+  }
+  else if (type == OUT_REL2ADR)
+  {
+    if (segment == segto)
+      error(ERR_PANIC, "intra-segment OUT_REL2ADR");
+    if (segment != NO_SEG && segment % 2) {
+      error(ERR_NONFATAL, "rdf format does not support segment base refs");
+    }
+
+    rr.type = 1;               /* type signature */
+    rr.segment = segto+64;     /* segment we're currently in + rel flag */
+    rr.offset = membuflength(seg[segto]);      /* current offset */
+    rr.length = 2;             /* length of reference */
+    rr.refseg = segment;       /* segment referred to */
+    write_reloc_rec(&rr);
+
+    /* work out what to put in the code: offset of the end of this operand,
+     * subtracted from any data specified, so that loader can just add
+     * address of imported symbol onto it to get address relative to end of
+     * instruction: import_address + data(offset) - end_of_instrn */
+
+    rr.offset = *(long *)data -(rr.offset + bytes);
+
+    membufwrite(seg[segto],&rr.offset,-2);
+  }
+  else if (type == OUT_REL4ADR)
+  {
+    if (segment == segto)
+      error(ERR_PANIC, "intra-segment OUT_REL4ADR");
+    if (segment != NO_SEG && segment % 2) {
+      error(ERR_NONFATAL, "rdf format does not support segment base refs");
+    }
+
+    rr.type = 1;               /* type signature */
+    rr.segment = segto+64;     /* segment we're currently in + rel tag */
+    rr.offset = membuflength(seg[segto]);      /* current offset */
+    rr.length = 4;             /* length of reference */
+    rr.refseg = segment;       /* segment referred to */
+    write_reloc_rec(&rr);
+
+    rr.offset = *(long *)data -(rr.offset + bytes);
+    membufwrite(seg[segto],&rr.offset,-4);
+  }
+}
+
+static void rdf_cleanup (int debuginfo) {
+  long         l;
+  unsigned char b[4],*d;
+  struct BSSRec        bs;
+
+    (void) debuginfo;
+
+
+  /* should write imported & exported symbol declarations to header here */
+
+  /* generate the output file... */
+  fwrite(RDOFFId,6,1,ofile);   /* file type magic number */
+
+  if (bsslength != 0)          /* reserve BSS */
+  {
+      bs.type = 5;
+      bs.amount = bsslength;
+      write_bss_rec(&bs);
+  }
+
+  l = membuflength(header);d=b;
+  WRITELONG(d,l);
+
+  fwrite(b,4,1,ofile);         /* write length of header */
+  membufdump(header,ofile);    /* dump header */
+
+  l = membuflength(seg[0]);d=b;        /* code segment */
+  WRITELONG(d,l);
+
+  fwrite(b,4,1,ofile);
+  membufdump(seg[0],ofile);
+
+  l = membuflength(seg[1]);d=b;        /* data segment */
+  WRITELONG(d,l);
+
+  fwrite(b,4,1,ofile);
+  membufdump(seg[1],ofile);
+
+  freemembuf(header);
+  freemembuf(seg[0]);
+  freemembuf(seg[1]);
+  fclose(ofile);
+}
+
+static long rdf_segbase (long segment) {
+    return segment;
+}
+
+static int rdf_directive (char *directive, char *value, int pass) {
+    struct DLLRec r;
+    
+    if (! strcmp(directive, "library")) {
+       if (pass == 1) {
+           r.type = 4;
+           strcpy(r.libname, value);
+           write_dll_rec(&r);
+       }
+       return 1;
+    }
+
+    return 0;
+}
+
+static void rdf_filename (char *inname, char *outname, efunc error) {
+  standard_extension(inname,outname,".rdf",error);
+}
+
+static char *rdf_stdmac[] = {
+    "%define __SECT__ [section .text]",
+    "%imacro library 1+.nolist",
+    "[library %1]",
+    "%endmacro",
+    "%macro __NASM_CDecl__ 1",
+    "%endmacro",
+    NULL
+};
+
+static int rdf_set_info(enum geninfo type, char **val)
+{
+    return 0;
+}
+
+struct ofmt of_rdf = {
+  "Relocatable Dynamic Object File Format v1.1",
+#ifdef OF_RDF2
+  "oldrdf",
+#else
+  "rdf",
+#endif
+  NULL,
+  null_debug_arr,
+  &null_debug_form,
+  rdf_stdmac,
+  rdf_init,
+  rdf_set_info,
+  rdf_out,
+  rdf_deflabel,
+  rdf_section_names,
+  rdf_segbase,
+  rdf_directive,
+  rdf_filename,
+  rdf_cleanup
+};
+
+#endif /* OF_RDF */
diff --git a/output/outrdf2.c b/output/outrdf2.c
new file mode 100644 (file)
index 0000000..e098873
--- /dev/null
@@ -0,0 +1,733 @@
+/* outrdf2.c   output routines for the Netwide Assembler to produce
+ *             RDOFF version 2 format object files (which are intended
+ *             mainly for use in proprietary projects, as the code to 
+ *             load and execute them is very simple). They will also be 
+ *             used for device drivers and possibly some executable files
+ *             in the MOSCOW operating system. See Rdoff.txt for
+ *             details.
+ *
+ * The Netwide Assembler is copyright (C) 1996-1998 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "nasm.h"
+#include "nasmlib.h"
+#include "outform.h"
+
+/* VERBOSE_WARNINGS: define this to add some extra warnings... */
+#define VERBOSE_WARNINGS     
+
+#ifdef OF_RDF2
+
+#define RDF_MAXSEGS 64 /* maximum number of segments - user configurable */
+
+typedef unsigned short int16;
+typedef unsigned char byte;
+
+static const char *RDOFF2Id = "RDOFF2";        /* written to start of RDOFF files */
+
+
+/* the records that can be found in the RDOFF header */
+
+/* Note that whenever a segment is referred to in the RDOFF file, its number
+ * is always half of the segment number that NASM uses to refer to it; this
+ * is because NASM only allocates even numbered segments, so as to not
+ * waste any of the 16 bits of segment number written to the file - this
+ * allows up to 65533 external labels to be defined; otherwise it would be
+ * 32764. */
+#define RDFREC_RELOC           1
+#define RDFREC_IMPORT          2
+#define RDFREC_GLOBAL          3
+#define RDFREC_DLL             4
+#define RDFREC_BSS             5
+#define RDFREC_SEGRELOC                6
+#define RDFREC_FARIMPORT       7
+#define RDFREC_MODNAME         8
+#define RDFREC_MULTIBOOTHDR    9
+#define RDFREC_GENERIC         0
+
+
+struct RelocRec {
+  byte type;           /* must be 1, or 6 for segment base ref */
+  byte reclen;         /* set to 8 */
+  byte segment;        /* only 0 for code, or 1 for data supported,
+                        * but add 64 for relative refs (ie do not require
+                        * reloc @ loadtime, only linkage) */
+  long offset;         /* from start of segment in which reference is loc'd */
+  byte length;         /* 1 2 or 4 bytes */
+  int16        refseg;         /* segment to which reference refers to */
+};
+
+struct ImportRec {
+  byte         type;           /* must be 2, or 7 for FAR import */
+  byte reclen;         /* equals 3+label length */
+  int16        segment;        /* segment number allocated to the label for reloc
+                        * records - label is assumed to be at offset zero
+                        * in this segment, so linker must fix up with offset
+                        * of segment and of offset within segment */
+  char label[33];      /* zero terminated... should be written to file until
+                        * the zero, but not after it - max len = 32 chars */
+};
+
+struct ExportRec {
+  byte type;           /* must be 3 */
+  byte  reclen;                /* equals 7+label length */
+  byte  flags;          /* SYM_* flags (see below) */
+  byte segment;        /* segment referred to (0/1) */
+  long offset;         /* offset within segment */
+  char label[33];      /* zero terminated as above. max len = 32 chars */
+};
+
+struct BSSRec {
+  byte type;           /* must be 5 */
+  byte  reclen;                /* equals 4 */
+  long amount;         /* number of bytes BSS to reserve */
+};
+
+struct DLLModRec {
+  byte type;           /* 4 for DLLRec, 8 for ModRec */
+  byte reclen;         /* 1+lib name length for DLLRec, 1+mod name length */
+  char name[128];      /* library to link at load time or module name */
+};
+
+/* Flags for ExportRec */
+#define SYM_DATA       0x01
+#define SYM_FUNCTION   0x02
+#define SYM_GLOBAL     0x04
+
+#define COUNT_SEGTYPES 9
+
+static char * segmenttypes[COUNT_SEGTYPES] = {
+  "null", "text", "code", "data", "comment", "lcomment", "pcomment",
+  "symdebug", "linedebug" 
+};
+
+static int segmenttypenumbers[COUNT_SEGTYPES] = {
+  0, 1, 1, 2, 3, 4, 5, 6, 7
+};
+
+/* code for managing buffers needed to seperate code and data into individual
+ * sections until they are ready to be written to the file.
+ * We'd better hope that it all fits in memory else we're buggered... */
+
+#define BUF_BLOCK_LEN 4088             /* selected to match page size (4096)
+                                         * on 80x86 machines for efficiency */
+
+/***********************************************************************
+ * Actual code to deal with RDOFF2 ouput format begins here...
+ */
+
+/* global variables set during the initialisation phase */
+
+static struct SAA *seg[RDF_MAXSEGS];   /* seg 0 = code, seg 1 = data */
+static struct SAA *header;     /* relocation/import/export records */
+
+static FILE *ofile;
+
+static efunc error;
+
+static struct seginfo {
+  char *segname;
+  int   segnumber;
+  int16 segtype;
+  int16 segreserved;
+  long  seglength;
+} segments[RDF_MAXSEGS];
+
+static int nsegments;
+
+static long bsslength;
+static long headerlength;
+
+static void rdf2_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
+{
+  int segtext, segdata, segbss;
+
+  /* set up the initial segments */
+  segments[0].segname = ".text"; 
+  segments[0].segnumber = 0;
+  segments[0].segtype = 1;
+  segments[0].segreserved = 0;
+  segments[0].seglength = 0;
+
+  segments[1].segname = ".data";
+  segments[1].segnumber = 1;
+  segments[1].segtype = 2;
+  segments[1].segreserved = 0;
+  segments[1].seglength = 0;
+
+  segments[2].segname = ".bss";
+  segments[2].segnumber = 2;
+  segments[2].segtype = 0xFFFF;        /* reserved - should never be produced */
+  segments[2].segreserved = 0;
+  segments[2].seglength = 0;
+
+  nsegments = 3;
+
+  ofile = fp;
+  error = errfunc;
+
+  seg[0] = saa_init(1L);
+  seg[1] = saa_init(1L);
+  seg[2] = NULL;               /* special case! */
+
+  header = saa_init(1L);
+
+  segtext = seg_alloc();
+  segdata = seg_alloc();
+  segbss = seg_alloc();
+  if (segtext != 0 || segdata != 2 || segbss != 4)
+    error(ERR_PANIC,"rdf segment numbers not allocated as expected (%d,%d,%d)",
+         segtext,segdata,segbss);
+  bsslength=0;
+  headerlength = 0;
+}
+
+static long rdf2_section_names(char *name, int pass, int *bits)
+{
+  int  i;
+  char         * p, * q;
+  int  code = -1;
+  int  reserved = 0;
+
+  /*
+   * Default is 32 bits, in the text segment.
+   */
+  if (!name) {
+    *bits = 32;
+    return 0;
+  }
+
+  /* look for segment type code following segment name */
+  p = name;
+  while (*p && !isspace(*p)) p++;
+  if (*p) {    /* we're now in whitespace */
+    *p++ = '\0';
+    while (*p && isspace(80)) *p++ = '\0';
+  }
+  if (*p) {    /* we're now in an attribute value */
+    /*
+     * see if we have an optional ',number' following the type code
+     */
+    if ((q = strchr(p, ','))) {
+      *q++ = '\0';
+
+      reserved = readnum(q, &i);
+      if (i) {
+         error(ERR_NONFATAL, "value following comma must be numeric");
+         reserved = 0;
+      }
+    }
+    /*
+     * check it against the text strings in segmenttypes 
+     */
+
+    for (i = 0; i < COUNT_SEGTYPES; i++)
+      if (!nasm_stricmp(p, segmenttypes[i])) {
+       code = segmenttypenumbers[i];
+       break;
+      }
+    if (code == -1) {  /* didn't find anything */
+      code = readnum(p, &i);
+      if (i) {
+       error(ERR_NONFATAL, "unrecognised RDF segment type (%s)",p);
+       code = 3;
+      }
+    }
+  }    
+  for (i = 0; i < nsegments; i++) {
+    if (!strcmp(name, segments[i].segname)) {
+      if (code != -1 || reserved != 0) 
+       error(ERR_NONFATAL, "segment attributes specified on"
+             " redeclaration of segment");
+      return segments[i].segnumber * 2;
+    }
+  }
+
+  /* declaring a new segment! */
+
+  if (code == -1) {
+    error(ERR_NONFATAL, "new segment declared without type code");
+    code = 3;
+  }
+  if (nsegments == RDF_MAXSEGS) {
+    error(ERR_FATAL, "reached compiled-in maximum segment limit (%d)",
+         RDF_MAXSEGS);
+    return NO_SEG;
+  }
+
+  segments[nsegments].segname = nasm_strdup(name);
+  i = seg_alloc();
+  if (i % 2 != 0)
+    error(ERR_PANIC, "seg_alloc() returned odd number");
+  segments[nsegments].segnumber = i >> 1;
+  segments[nsegments].segtype = code;
+  segments[nsegments].segreserved = reserved;
+  segments[nsegments].seglength = 0;
+
+  seg[nsegments] = saa_init(1L);
+
+  return i;
+}
+
+static void write_reloc_rec(struct RelocRec *r)
+{
+  char buf[4],*b;
+
+  if (r->refseg != (int16)NO_SEG && (r->refseg & 1)) /* segment base ref */
+      r->type = RDFREC_SEGRELOC;
+
+  r->refseg >>= 1;    /* adjust segment nos to RDF rather than NASM */
+
+  saa_wbytes(header,&r->type,1);
+  saa_wbytes(header,&r->reclen,1);
+  saa_wbytes(header,&r->segment,1);
+  b = buf; WRITELONG(b,r->offset);
+  saa_wbytes(header,buf,4);
+  saa_wbytes(header,&r->length,1);
+  b = buf; WRITESHORT(b,r->refseg);
+  saa_wbytes(header,buf,2);
+  headerlength += r->reclen + 2;
+}
+
+static void write_export_rec(struct ExportRec *r)
+{
+  char buf[4], *b;
+
+  r->segment >>= 1;
+
+  saa_wbytes(header,&r->type,1);
+  saa_wbytes(header,&r->reclen,1);
+  saa_wbytes(header,&r->flags,1);
+  saa_wbytes(header,&r->segment,1);
+  b = buf; WRITELONG(b,r->offset);
+  saa_wbytes(header,buf,4);
+  saa_wbytes(header,r->label,strlen(r->label) + 1);
+  headerlength += r->reclen + 2;
+}
+
+static void write_import_rec(struct ImportRec *r)
+{
+  char buf[4], *b;
+
+  r->segment >>= 1;
+
+  saa_wbytes(header,&r->type,1);
+  saa_wbytes(header,&r->reclen,1);
+  b = buf; WRITESHORT(b,r->segment);
+  saa_wbytes(header,buf,2);
+  saa_wbytes(header,r->label,strlen(r->label) + 1);
+  headerlength += r->reclen + 2;
+}
+
+static void write_bss_rec(struct BSSRec *r)
+{
+    char buf[4], *b;
+
+    saa_wbytes(header,&r->type,1);
+    saa_wbytes(header,&r->reclen,1);
+    b = buf; WRITELONG(b,r->amount);
+    saa_wbytes(header,buf,4);
+    headerlength += r->reclen + 2;
+}
+
+/*
+ * Write library record. Also used for module name records.
+ */
+static void write_dllmod_rec(struct DLLModRec *r)
+{
+    saa_wbytes(header,&r->type,1);
+    saa_wbytes(header,&r->reclen,1);
+    saa_wbytes(header,r->name,strlen(r->name) + 1);
+    headerlength += r->reclen + 2;
+}
+
+static void rdf2_deflabel(char *name, long segment, long offset,
+                        int is_global, char *special)
+{
+  struct ExportRec r;
+  struct ImportRec ri;
+  static int farsym = 0;
+  static int i;
+  byte export_flags = 0;
+
+  if (is_global != 1) return;
+
+  if (special) {
+    while(*special == ' ' || *special == '\t') special++;
+    
+    if (!nasm_strnicmp(special, "export", 6)) {
+      special += 6;
+      export_flags |= SYM_GLOBAL;  
+    }
+
+    if (*special) {
+      while(isspace(*special)) special++;
+      if (!nasm_stricmp(special, "far")) {
+        farsym = 1;
+      }
+      else if (!nasm_stricmp(special, "near")) {
+        farsym = 0;
+      }
+      else if (!nasm_stricmp(special, "proc") || 
+               !nasm_stricmp(special, "function")) {
+        export_flags |= SYM_FUNCTION;  
+      }
+      else if (!nasm_stricmp(special, "data") ||
+               !nasm_stricmp(special, "object")) {
+        export_flags |= SYM_DATA;
+      }
+      else
+        error(ERR_NONFATAL, "unrecognised symbol type `%s'", special);
+    }  
+  }
+
+  if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
+    error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
+    return;
+  }
+
+  for (i = 0; i < nsegments; i++) {
+    if (segments[i].segnumber == segment>>1) break;
+  }
+  if (i >= nsegments) {   /* EXTERN declaration */
+    if (farsym)
+      ri.type = RDFREC_FARIMPORT;
+    else
+      ri.type = RDFREC_IMPORT;
+    ri.segment = segment;
+    strncpy(ri.label,name,32);
+    ri.label[32] = 0;
+    ri.reclen = 3 + strlen(ri.label);
+    write_import_rec(&ri);
+  } else if (is_global) {
+    r.type = RDFREC_GLOBAL;
+    r.flags = export_flags;
+    r.segment = segment;
+    r.offset = offset;
+    strncpy(r.label,name,32);
+    r.label[32] = 0;
+    r.reclen = 7 + strlen(r.label);
+    write_export_rec(&r);
+  }
+}
+
+static void membufwrite(int segment, void * data, int bytes)
+{
+  int i;
+  char buf[4], * b;
+
+  for (i = 0; i < nsegments; i++) {
+    if (segments[i].segnumber == segment) break;
+  }
+  if (i == nsegments)
+    error(ERR_PANIC, "can't find segment %d", segment);
+  
+  if (bytes < 0) {
+    b = buf;
+    if (bytes == -2)
+      WRITESHORT(b,*(short *)data);
+    else
+      WRITELONG(b,*(long *)data);
+    data = buf;
+    bytes = -bytes;
+  }
+  segments[i].seglength += bytes;
+  saa_wbytes(seg[i],data,bytes);
+}
+
+static int getsegmentlength(int segment)
+{
+  int i;
+  for (i = 0; i < nsegments; i++) {
+    if (segments[i].segnumber == segment) break;
+  }
+  if (i == nsegments)
+    error(ERR_PANIC, "can't find segment %d", segment);
+
+  return segments[i].seglength;
+}
+    
+static void rdf2_out (long segto, void *data, unsigned long type,
+                    long segment, long wrt)
+{
+  long bytes = type & OUT_SIZMASK;
+  struct RelocRec rr;
+  unsigned char databuf[4],*pd;
+  int seg;
+
+  if (segto == NO_SEG) {
+      if ((type & OUT_TYPMASK) != OUT_RESERVE)
+         error (ERR_NONFATAL, "attempt to assemble code in ABSOLUTE space");
+      return;
+  }
+
+  segto >>= 1;    /* convert NASM segment no to RDF number */
+
+  for (seg = 0; seg < nsegments; seg++) {
+    if (segments[seg].segnumber == segto) break;
+  }
+  if (seg >= nsegments) {
+    error(ERR_NONFATAL,"specified segment not supported by rdf output format");
+    return;
+  }
+
+  if (wrt != NO_SEG) {
+    wrt = NO_SEG;                     /* continue to do _something_ */
+    error (ERR_NONFATAL, "WRT not supported by rdf output format");
+  }
+
+  type &= OUT_TYPMASK;
+
+  if (segto == 2 && type != OUT_RESERVE)
+  {
+      error(ERR_NONFATAL, "BSS segments may not be initialised");
+
+      /* just reserve the space for now... */
+
+      if (type == OUT_REL2ADR)
+       bytes = 2;
+      else
+       bytes = 4;
+      type = OUT_RESERVE;
+  }
+
+  if (type == OUT_RESERVE) {
+      if (segto == 2)          /* BSS segment space reserverd */
+         bsslength += bytes;
+      else
+       while (bytes --)
+           membufwrite(segto,databuf,1);
+  }
+  else if (type == OUT_RAWDATA) {
+      if (segment != NO_SEG)
+         error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
+
+      membufwrite(segto,data,bytes);
+  }
+  else if (type == OUT_ADDRESS) {
+
+    /* if segment == NO_SEG then we are writing an address of an
+       object within the same segment - do not produce reloc rec. */
+
+    /* FIXME - is this behaviour sane? at first glance it doesn't
+       appear to be. Must test this thoroughly...! */
+
+    if (segment != NO_SEG)
+    {
+       /* it's an address, so we must write a relocation record */
+
+       rr.type = RDFREC_RELOC;                 /* type signature */
+       rr.reclen = 8;
+       rr.segment = segto;                     /* segment we're currently in */
+       rr.offset = getsegmentlength(segto);    /* current offset */
+       rr.length = bytes;                      /* length of reference */
+       rr.refseg = segment;                    /* segment referred to */
+       write_reloc_rec(&rr);
+    }
+
+    pd = databuf;      /* convert address to little-endian */
+    if (bytes == 2)
+      WRITESHORT (pd, *(long *)data);
+    else
+      WRITELONG (pd, *(long *)data);
+
+    membufwrite(segto,databuf,bytes);
+
+  }
+  else if (type == OUT_REL2ADR)
+  {
+    if (segment == segto)
+      error(ERR_PANIC, "intra-segment OUT_REL2ADR");
+
+    rr.reclen = 8;
+    rr.offset = getsegmentlength(segto);       /* current offset */
+    rr.length = 2;             /* length of reference */
+    rr.refseg = segment;       /* segment referred to (will be >>1'd)*/
+
+    if (segment != NO_SEG && segment % 2) {
+      rr.type = RDFREC_SEGRELOC;
+      rr.segment = segto;      /* memory base refs *aren't ever* relative! */
+      write_reloc_rec(&rr);
+
+      /* what do we put in the code? Simply the data. This should almost
+       * always be zero, unless someone's doing segment arithmetic...
+       */
+      rr.offset = *(long *) data;
+    }
+    else
+    {
+      rr.type = RDFREC_RELOC;  /* type signature */
+      rr.segment = segto+64;   /* segment we're currently in + rel flag */
+      write_reloc_rec(&rr);
+
+      /* work out what to put in the code: offset of the end of this operand,
+       * subtracted from any data specified, so that loader can just add
+       * address of imported symbol onto it to get address relative to end of
+       * instruction: import_address + data(offset) - end_of_instrn */
+
+      rr.offset = *(long *)data -(rr.offset + bytes);
+    }
+    
+    membufwrite(segto,&rr.offset,-2);
+  }
+  else if (type == OUT_REL4ADR)
+  {
+    if (segment == segto)
+      error(ERR_PANIC, "intra-segment OUT_REL4ADR");
+    if (segment != NO_SEG && segment % 2) {
+      error(ERR_PANIC, "erm... 4 byte segment base ref?");
+    }
+
+    rr.type = RDFREC_RELOC;    /* type signature */
+    rr.segment = segto+64;     /* segment we're currently in + rel tag */
+    rr.offset = getsegmentlength(segto);       /* current offset */
+    rr.length = 4;             /* length of reference */
+    rr.refseg = segment;       /* segment referred to */
+    rr.reclen = 8;
+    write_reloc_rec(&rr);
+
+    rr.offset = *(long *)data -(rr.offset + bytes);
+
+    membufwrite(segto,&rr.offset,-4);
+  }
+}
+
+static void rdf2_cleanup (int debuginfo) {
+  long         l;
+  struct BSSRec        bs;
+  int          i;
+
+    (void) debuginfo;
+
+  /* should write imported & exported symbol declarations to header here */
+
+  /* generate the output file... */
+  fwrite(RDOFF2Id,6,1,ofile);  /* file type magic number */
+
+  if (bsslength != 0)          /* reserve BSS */
+  {
+      bs.type = RDFREC_BSS;
+      bs.amount = bsslength;
+      bs.reclen = 4;
+      write_bss_rec(&bs);
+  }
+
+  /*
+   * calculate overall length of the output object
+   */
+  l = headerlength + 4;
+  
+  for (i = 0; i < nsegments; i++) {
+    if (i == 2) continue;      /* skip BSS segment */
+    l += 10 + segments[i].seglength;
+  }
+  l += 10;     /* null segment */
+
+  fwritelong(l, ofile);
+
+  fwritelong(headerlength, ofile);
+  saa_fpwrite(header,ofile);   /* dump header */
+  saa_free(header);
+
+  for (i = 0; i < nsegments; i++) {
+    if (i == 2) continue;
+
+    fwriteshort(segments[i].segtype, ofile);
+    fwriteshort(segments[i].segnumber, ofile);
+    fwriteshort(segments[i].segreserved, ofile);
+    fwritelong(segments[i].seglength, ofile);
+
+    saa_fpwrite(seg[i], ofile);
+    saa_free(seg[i]);
+  }
+
+  /* null segment - write 10 bytes of zero */
+  fwritelong(0,ofile);
+  fwritelong(0,ofile);
+  fwriteshort(0,ofile);
+
+  fclose(ofile);
+}
+
+static long rdf2_segbase (long segment) {
+    return segment;
+}
+
+static int rdf2_directive (char *directive, char *value, int pass) {
+    struct DLLModRec r;
+
+    if (! strcmp(directive, "library")) {
+       if (pass == 1) {
+           r.type = RDFREC_DLL;
+           r.reclen=strlen(value)+1;
+           strcpy(r.name, value);
+           write_dllmod_rec(&r);
+       }
+       return 1;
+    }
+
+    if (! strcmp(directive, "module")) {
+       if (pass == 1) {
+           r.type = RDFREC_MODNAME;
+           r.reclen=strlen(value)+1;
+           strcpy(r.name, value);
+           write_dllmod_rec(&r);
+       }
+       return 1;
+    }
+    
+    return 0;
+}
+
+static void rdf2_filename (char *inname, char *outname, efunc error) {
+  standard_extension(inname,outname,".rdf",error);
+}
+
+static char *rdf2_stdmac[] = {
+    "%define __SECT__ [section .text]",
+    "%imacro library 1+.nolist",
+    "[library %1]",
+    "%endmacro",
+    "%imacro module 1+.nolist",
+    "[module %1]",
+    "%endmacro",
+    "%macro __NASM_CDecl__ 1",
+    "%endmacro",
+    NULL
+};
+
+static int rdf2_set_info(enum geninfo type, char **val)
+{
+    return 0;
+}
+
+
+struct ofmt of_rdf2 = {
+  "Relocatable Dynamic Object File Format v2.0",
+  "rdf",
+  NULL,
+  null_debug_arr,
+  &null_debug_form,
+  rdf2_stdmac,
+  rdf2_init,
+  rdf2_set_info,
+  rdf2_out,
+  rdf2_deflabel,
+  rdf2_section_names,
+  rdf2_segbase,
+  rdf2_directive,
+  rdf2_filename,
+  rdf2_cleanup
+};
+
+#endif /* OF_RDF2 */
diff --git a/outrdf.c b/outrdf.c
deleted file mode 100644 (file)
index d9989e5..0000000
--- a/outrdf.c
+++ /dev/null
@@ -1,539 +0,0 @@
-/* outrdf.c    output routines for the Netwide Assembler to produce
- *             RDOFF format object files (which are intended mainly
- *             for use in proprietary projects, as the code to load and
- *             execute them is very simple). They will also be used
- *             for device drivers and possibly some executable files
- *             in the MOSCOW operating system. See Rdoff.txt for
- *             details.
- *
- * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
- * Julian Hall. All rights reserved. The software is
- * redistributable under the licence given in the file "Licence"
- * distributed in the NASM archive.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include "nasm.h"
-#include "nasmlib.h"
-#include "outform.h"
-
-/* VERBOSE_WARNINGS: define this to add some extra warnings... */
-#define VERBOSE_WARNINGS     
-
-#ifdef OF_RDF
-
-typedef short int16;   /* not sure if this will be required to be altered
-                          at all... best to typedef it just in case */
-
-static const char *RDOFFId = "RDOFF1"; /* written to start of RDOFF files */
-
-/* the records that can be found in the RDOFF header */
-
-/* Note that whenever a segment is referred to in the RDOFF file, its number
- * is always half of the segment number that NASM uses to refer to it; this
- * is because NASM only allocates even numbered segments, so as to not
- * waste any of the 16 bits of segment number written to the file - this
- * allows up to 65533 external labels to be defined; otherwise it would be
- * 32764. */
-
-struct RelocRec {
-  char type;           /* must be 1 */
-  char segment;        /* only 0 for code, or 1 for data supported,
-                        * but add 64 for relative refs (ie do not require
-                        * reloc @ loadtime, only linkage) */
-  long offset;         /* from start of segment in which reference is loc'd */
-  char length;         /* 1 2 or 4 bytes */
-  int16        refseg;         /* segment to which reference refers to */
-};
-
-struct ImportRec {
-  char         type;           /* must be 2 */
-  int16        segment;        /* segment number allocated to the label for reloc
-                        * records - label is assumed to be at offset zero
-                        * in this segment, so linker must fix up with offset
-                        * of segment and of offset within segment */
-  char label[33];      /* zero terminated... should be written to file until
-                        * the zero, but not after it - max len = 32 chars */
-};
-
-struct ExportRec {
-  char type;           /* must be 3 */
-  char segment;        /* segment referred to (0/1) */
-  long offset;         /* offset within segment */
-  char label[33];      /* zero terminated as above. max len = 32 chars */
-};
-
-struct DLLRec {
-  char type;           /* must be 4 */
-  char libname[128];   /* name of library to link with at load time */
-};
-
-struct BSSRec {
-  char type;           /* must be 5 */
-  long amount;         /* number of bytes BSS to reserve */
-};
-
-/* code for managing buffers needed to seperate code and data into individual
- * sections until they are ready to be written to the file.
- * We'd better hope that it all fits in memory else we're buggered... */
-
-#define BUF_BLOCK_LEN 4088             /* selected to match page size (4096)
-                                         * on 80x86 machines for efficiency */
-
-typedef struct memorybuffer {
-  int length;
-  char buffer[BUF_BLOCK_LEN];
-  struct memorybuffer *next;
-} memorybuffer;
-
-static memorybuffer * newmembuf(void){
-  memorybuffer * t;
-
-  t = nasm_malloc(sizeof(memorybuffer));
-
-  t->length = 0;
-  t->next = NULL;
-  return t;
-}
-
-static void membufwrite(memorybuffer *b, void *data, int bytes) {
-  int16 w;
-  long l;
-
-  if (b->next) {       /* memory buffer full - use next buffer */
-    membufwrite(b->next,data,bytes);
-    return;
-  }
-  if ((bytes < 0 && b->length - bytes > BUF_BLOCK_LEN)
-      || (bytes > 0 && b->length + bytes > BUF_BLOCK_LEN)) {
-
-    /* buffer full and no next allocated... allocate and initialise next
-     * buffer */
-
-    b->next = newmembuf();
-    membufwrite(b->next,data,bytes);
-    return;
-  }
-
-  switch(bytes) {
-  case -4:             /* convert to little-endian */
-    l = * (long *) data ;
-    b->buffer[b->length++] = l & 0xFF;
-    l >>= 8 ;
-    b->buffer[b->length++] = l & 0xFF;
-    l >>= 8 ;
-    b->buffer[b->length++] = l & 0xFF;
-    l >>= 8 ;
-    b->buffer[b->length++] = l & 0xFF;
-    break;
-
-  case -2:
-    w = * (int16 *) data ;
-    b->buffer[b->length++] = w & 0xFF;
-    w >>= 8 ;
-    b->buffer[b->length++] = w & 0xFF;
-    break;
-
-  default:
-    while(bytes--) {
-      b->buffer[b->length++] = *(* (unsigned char **) &data);
-
-      (* (unsigned char **) &data)++ ;
-    }
-    break;
-  }
-}
-
-static void membufdump(memorybuffer *b,FILE *fp)
-{
-  if (!b) return;
-
-  fwrite (b->buffer, 1, b->length, fp);
-
-  membufdump(b->next,fp);
-}
-
-static int membuflength(memorybuffer *b)
-{
-  if (!b) return 0;
-  return b->length + membuflength(b->next);
-}
-
-static void freemembuf(memorybuffer *b)
-{
-  if (!b) return;
-  freemembuf(b->next);
-  nasm_free(b);
-}
-
-/***********************************************************************
- * Actual code to deal with RDOFF ouput format begins here...
- */
-
-/* global variables set during the initialisation phase */
-
-static memorybuffer *seg[2];   /* seg 0 = code, seg 1 = data */
-static memorybuffer *header;   /* relocation/import/export records */
-
-static FILE *ofile;
-
-static efunc error;
-
-static int segtext,segdata,segbss;
-static long bsslength;
-
-static void rdf_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
-{
-  ofile = fp;
-  error = errfunc;
-  seg[0] = newmembuf();
-  seg[1] = newmembuf();
-  header = newmembuf();
-  segtext = seg_alloc();
-  segdata = seg_alloc();
-  segbss = seg_alloc();
-  if (segtext != 0 || segdata != 2 || segbss != 4)
-    error(ERR_PANIC,"rdf segment numbers not allocated as expected (%d,%d,%d)",
-         segtext,segdata,segbss);
-  bsslength=0;
-}
-
-static long rdf_section_names(char *name, int pass, int *bits)
-{
-  /*
-   * Default is 32 bits.
-   */
-  if (!name)
-    *bits = 32;
-
-  if (!name) return 0;
-  if (!strcmp(name, ".text"))          return 0;
-  else if (!strcmp(name, ".data"))     return 2;
-  else if (!strcmp(name, ".bss"))      return 4;
-  else
-    return NO_SEG;
-}
-
-static void write_reloc_rec(struct RelocRec *r)
-{
-  if (r->refseg != NO_SEG && (r->refseg & 1))
-    error (ERR_NONFATAL, "RDF format does not support segment base"
-          " references");
-
-  r->refseg >>= 1;    /* adjust segment nos to RDF rather than NASM */
-
-  membufwrite(header,&r->type,1);
-  membufwrite(header,&r->segment,1);
-  membufwrite(header,&r->offset,-4);
-  membufwrite(header,&r->length,1);
-  membufwrite(header,&r->refseg,-2);   /* 9 bytes written */
-}
-
-static void write_export_rec(struct ExportRec *r)
-{
-  r->segment >>= 1;
-
-  membufwrite(header,&r->type,1);
-  membufwrite(header,&r->segment,1);
-  membufwrite(header,&r->offset,-4);
-  membufwrite(header,r->label,strlen(r->label) + 1);
-}
-
-static void write_import_rec(struct ImportRec *r)
-{
-  r->segment >>= 1;
-
-  membufwrite(header,&r->type,1);
-  membufwrite(header,&r->segment,-2);
-  membufwrite(header,r->label,strlen(r->label) + 1);
-}
-
-static void write_bss_rec(struct BSSRec *r)
-{
-    membufwrite(header,&r->type,1);
-    membufwrite(header,&r->amount,-4);
-}
-
-static void write_dll_rec(struct DLLRec *r)
-{
-    membufwrite(header,&r->type,1);
-    membufwrite(header,r->libname,strlen(r->libname) + 1);
-}
-
-static void rdf_deflabel(char *name, long segment, long offset,
-                        int is_global, char *special)
-{
-  struct ExportRec r;
-  struct ImportRec ri;
-#ifdef VERBOSE_WARNINGS
-  static int warned_common = 0;
-#endif
-
-  if (special)
-    error (ERR_NONFATAL, "RDOFF format does not support any"
-          " special symbol types");
-
-  if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
-    error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
-    return;
-  }
-
-  if (is_global == 2) {
-#ifdef VERBOSE_WARNINGS
-    if (!warned_common) {
-      error(ERR_WARNING,"common declarations not supported: using extern");
-      warned_common = 1;
-    }
-#endif
-    is_global = 1;
-  }
-
-  if (segment > 4) {   /* EXTERN declaration */
-    ri.type = 2;
-    ri.segment = segment;
-    strncpy(ri.label,name,32);
-    ri.label[32] = 0;
-    write_import_rec(&ri);
-  } else if (is_global) {
-    r.type = 3;
-    r.segment = segment;
-    r.offset = offset;
-    strncpy(r.label,name,32);
-    r.label[32] = 0;
-    write_export_rec(&r);
-  }
-}
-
-static void rdf_out (long segto, void *data, unsigned long type,
-                    long segment, long wrt)
-{
-  long bytes = type & OUT_SIZMASK;
-  struct RelocRec rr;
-  unsigned char databuf[4],*pd;
-
-  if (segto == NO_SEG) {
-      if ((type & OUT_TYPMASK) != OUT_RESERVE)
-         error (ERR_NONFATAL, "attempt to assemble code in ABSOLUTE space");
-      return;
-  }
-
-  segto >>= 1;    /* convert NASM segment no to RDF number */
-
-  if (segto != 0 && segto != 1 && segto != 2) {
-    error(ERR_NONFATAL,"specified segment not supported by rdf output format");
-    return;
-  }
-
-  if (wrt != NO_SEG) {
-    wrt = NO_SEG;                     /* continue to do _something_ */
-    error (ERR_NONFATAL, "WRT not supported by rdf output format");
-  }
-
-  type &= OUT_TYPMASK;
-
-  if (segto == 2 && type != OUT_RESERVE)
-  {
-      error(ERR_NONFATAL, "BSS segments may not be initialised");
-
-      /* just reserve the space for now... */
-
-      if (type == OUT_REL2ADR)
-       bytes = 2;
-      else
-       bytes = 4;
-      type = OUT_RESERVE;
-  }
-
-  if (type == OUT_RESERVE) {
-      if (segto == 2)          /* BSS segment space reserverd */
-         bsslength += bytes;
-      else
-       while (bytes --)
-           membufwrite(seg[segto],databuf,1);
-  }
-  else if (type == OUT_RAWDATA) {
-      if (segment != NO_SEG)
-         error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
-      membufwrite(seg[segto],data,bytes);
-  }
-  else if (type == OUT_ADDRESS) {
-
-    /* if segment == NO_SEG then we are writing an address of an
-       object within the same segment - do not produce reloc rec. */
-
-    if (segment != NO_SEG)
-    {
-
-       /* it's an address, so we must write a relocation record */
-
-       rr.type = 1;            /* type signature */
-       rr.segment = segto;             /* segment we're currently in */
-       rr.offset = membuflength(seg[segto]);   /* current offset */
-       rr.length = bytes;              /* length of reference */
-       rr.refseg = segment;    /* segment referred to */
-       write_reloc_rec(&rr);
-    }
-
-    pd = databuf;      /* convert address to little-endian */
-    if (bytes == 2)
-      WRITESHORT (pd, *(long *)data);
-    else
-      WRITELONG (pd, *(long *)data);
-
-    membufwrite(seg[segto],databuf,bytes);
-
-  }
-  else if (type == OUT_REL2ADR)
-  {
-    if (segment == segto)
-      error(ERR_PANIC, "intra-segment OUT_REL2ADR");
-    if (segment != NO_SEG && segment % 2) {
-      error(ERR_NONFATAL, "rdf format does not support segment base refs");
-    }
-
-    rr.type = 1;               /* type signature */
-    rr.segment = segto+64;     /* segment we're currently in + rel flag */
-    rr.offset = membuflength(seg[segto]);      /* current offset */
-    rr.length = 2;             /* length of reference */
-    rr.refseg = segment;       /* segment referred to */
-    write_reloc_rec(&rr);
-
-    /* work out what to put in the code: offset of the end of this operand,
-     * subtracted from any data specified, so that loader can just add
-     * address of imported symbol onto it to get address relative to end of
-     * instruction: import_address + data(offset) - end_of_instrn */
-
-    rr.offset = *(long *)data -(rr.offset + bytes);
-
-    membufwrite(seg[segto],&rr.offset,-2);
-  }
-  else if (type == OUT_REL4ADR)
-  {
-    if (segment == segto)
-      error(ERR_PANIC, "intra-segment OUT_REL4ADR");
-    if (segment != NO_SEG && segment % 2) {
-      error(ERR_NONFATAL, "rdf format does not support segment base refs");
-    }
-
-    rr.type = 1;               /* type signature */
-    rr.segment = segto+64;     /* segment we're currently in + rel tag */
-    rr.offset = membuflength(seg[segto]);      /* current offset */
-    rr.length = 4;             /* length of reference */
-    rr.refseg = segment;       /* segment referred to */
-    write_reloc_rec(&rr);
-
-    rr.offset = *(long *)data -(rr.offset + bytes);
-    membufwrite(seg[segto],&rr.offset,-4);
-  }
-}
-
-static void rdf_cleanup (int debuginfo) {
-  long         l;
-  unsigned char b[4],*d;
-  struct BSSRec        bs;
-
-    (void) debuginfo;
-
-
-  /* should write imported & exported symbol declarations to header here */
-
-  /* generate the output file... */
-  fwrite(RDOFFId,6,1,ofile);   /* file type magic number */
-
-  if (bsslength != 0)          /* reserve BSS */
-  {
-      bs.type = 5;
-      bs.amount = bsslength;
-      write_bss_rec(&bs);
-  }
-
-  l = membuflength(header);d=b;
-  WRITELONG(d,l);
-
-  fwrite(b,4,1,ofile);         /* write length of header */
-  membufdump(header,ofile);    /* dump header */
-
-  l = membuflength(seg[0]);d=b;        /* code segment */
-  WRITELONG(d,l);
-
-  fwrite(b,4,1,ofile);
-  membufdump(seg[0],ofile);
-
-  l = membuflength(seg[1]);d=b;        /* data segment */
-  WRITELONG(d,l);
-
-  fwrite(b,4,1,ofile);
-  membufdump(seg[1],ofile);
-
-  freemembuf(header);
-  freemembuf(seg[0]);
-  freemembuf(seg[1]);
-  fclose(ofile);
-}
-
-static long rdf_segbase (long segment) {
-    return segment;
-}
-
-static int rdf_directive (char *directive, char *value, int pass) {
-    struct DLLRec r;
-    
-    if (! strcmp(directive, "library")) {
-       if (pass == 1) {
-           r.type = 4;
-           strcpy(r.libname, value);
-           write_dll_rec(&r);
-       }
-       return 1;
-    }
-
-    return 0;
-}
-
-static void rdf_filename (char *inname, char *outname, efunc error) {
-  standard_extension(inname,outname,".rdf",error);
-}
-
-static char *rdf_stdmac[] = {
-    "%define __SECT__ [section .text]",
-    "%imacro library 1+.nolist",
-    "[library %1]",
-    "%endmacro",
-    "%macro __NASM_CDecl__ 1",
-    "%endmacro",
-    NULL
-};
-
-static int rdf_set_info(enum geninfo type, char **val)
-{
-    return 0;
-}
-
-struct ofmt of_rdf = {
-  "Relocatable Dynamic Object File Format v1.1",
-#ifdef OF_RDF2
-  "oldrdf",
-#else
-  "rdf",
-#endif
-  NULL,
-  null_debug_arr,
-  &null_debug_form,
-  rdf_stdmac,
-  rdf_init,
-  rdf_set_info,
-  rdf_out,
-  rdf_deflabel,
-  rdf_section_names,
-  rdf_segbase,
-  rdf_directive,
-  rdf_filename,
-  rdf_cleanup
-};
-
-#endif /* OF_RDF */
diff --git a/outrdf2.c b/outrdf2.c
deleted file mode 100644 (file)
index e098873..0000000
--- a/outrdf2.c
+++ /dev/null
@@ -1,733 +0,0 @@
-/* outrdf2.c   output routines for the Netwide Assembler to produce
- *             RDOFF version 2 format object files (which are intended
- *             mainly for use in proprietary projects, as the code to 
- *             load and execute them is very simple). They will also be 
- *             used for device drivers and possibly some executable files
- *             in the MOSCOW operating system. See Rdoff.txt for
- *             details.
- *
- * The Netwide Assembler is copyright (C) 1996-1998 Simon Tatham and
- * Julian Hall. All rights reserved. The software is
- * redistributable under the licence given in the file "Licence"
- * distributed in the NASM archive.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include "nasm.h"
-#include "nasmlib.h"
-#include "outform.h"
-
-/* VERBOSE_WARNINGS: define this to add some extra warnings... */
-#define VERBOSE_WARNINGS     
-
-#ifdef OF_RDF2
-
-#define RDF_MAXSEGS 64 /* maximum number of segments - user configurable */
-
-typedef unsigned short int16;
-typedef unsigned char byte;
-
-static const char *RDOFF2Id = "RDOFF2";        /* written to start of RDOFF files */
-
-
-/* the records that can be found in the RDOFF header */
-
-/* Note that whenever a segment is referred to in the RDOFF file, its number
- * is always half of the segment number that NASM uses to refer to it; this
- * is because NASM only allocates even numbered segments, so as to not
- * waste any of the 16 bits of segment number written to the file - this
- * allows up to 65533 external labels to be defined; otherwise it would be
- * 32764. */
-#define RDFREC_RELOC           1
-#define RDFREC_IMPORT          2
-#define RDFREC_GLOBAL          3
-#define RDFREC_DLL             4
-#define RDFREC_BSS             5
-#define RDFREC_SEGRELOC                6
-#define RDFREC_FARIMPORT       7
-#define RDFREC_MODNAME         8
-#define RDFREC_MULTIBOOTHDR    9
-#define RDFREC_GENERIC         0
-
-
-struct RelocRec {
-  byte type;           /* must be 1, or 6 for segment base ref */
-  byte reclen;         /* set to 8 */
-  byte segment;        /* only 0 for code, or 1 for data supported,
-                        * but add 64 for relative refs (ie do not require
-                        * reloc @ loadtime, only linkage) */
-  long offset;         /* from start of segment in which reference is loc'd */
-  byte length;         /* 1 2 or 4 bytes */
-  int16        refseg;         /* segment to which reference refers to */
-};
-
-struct ImportRec {
-  byte         type;           /* must be 2, or 7 for FAR import */
-  byte reclen;         /* equals 3+label length */
-  int16        segment;        /* segment number allocated to the label for reloc
-                        * records - label is assumed to be at offset zero
-                        * in this segment, so linker must fix up with offset
-                        * of segment and of offset within segment */
-  char label[33];      /* zero terminated... should be written to file until
-                        * the zero, but not after it - max len = 32 chars */
-};
-
-struct ExportRec {
-  byte type;           /* must be 3 */
-  byte  reclen;                /* equals 7+label length */
-  byte  flags;          /* SYM_* flags (see below) */
-  byte segment;        /* segment referred to (0/1) */
-  long offset;         /* offset within segment */
-  char label[33];      /* zero terminated as above. max len = 32 chars */
-};
-
-struct BSSRec {
-  byte type;           /* must be 5 */
-  byte  reclen;                /* equals 4 */
-  long amount;         /* number of bytes BSS to reserve */
-};
-
-struct DLLModRec {
-  byte type;           /* 4 for DLLRec, 8 for ModRec */
-  byte reclen;         /* 1+lib name length for DLLRec, 1+mod name length */
-  char name[128];      /* library to link at load time or module name */
-};
-
-/* Flags for ExportRec */
-#define SYM_DATA       0x01
-#define SYM_FUNCTION   0x02
-#define SYM_GLOBAL     0x04
-
-#define COUNT_SEGTYPES 9
-
-static char * segmenttypes[COUNT_SEGTYPES] = {
-  "null", "text", "code", "data", "comment", "lcomment", "pcomment",
-  "symdebug", "linedebug" 
-};
-
-static int segmenttypenumbers[COUNT_SEGTYPES] = {
-  0, 1, 1, 2, 3, 4, 5, 6, 7
-};
-
-/* code for managing buffers needed to seperate code and data into individual
- * sections until they are ready to be written to the file.
- * We'd better hope that it all fits in memory else we're buggered... */
-
-#define BUF_BLOCK_LEN 4088             /* selected to match page size (4096)
-                                         * on 80x86 machines for efficiency */
-
-/***********************************************************************
- * Actual code to deal with RDOFF2 ouput format begins here...
- */
-
-/* global variables set during the initialisation phase */
-
-static struct SAA *seg[RDF_MAXSEGS];   /* seg 0 = code, seg 1 = data */
-static struct SAA *header;     /* relocation/import/export records */
-
-static FILE *ofile;
-
-static efunc error;
-
-static struct seginfo {
-  char *segname;
-  int   segnumber;
-  int16 segtype;
-  int16 segreserved;
-  long  seglength;
-} segments[RDF_MAXSEGS];
-
-static int nsegments;
-
-static long bsslength;
-static long headerlength;
-
-static void rdf2_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
-{
-  int segtext, segdata, segbss;
-
-  /* set up the initial segments */
-  segments[0].segname = ".text"; 
-  segments[0].segnumber = 0;
-  segments[0].segtype = 1;
-  segments[0].segreserved = 0;
-  segments[0].seglength = 0;
-
-  segments[1].segname = ".data";
-  segments[1].segnumber = 1;
-  segments[1].segtype = 2;
-  segments[1].segreserved = 0;
-  segments[1].seglength = 0;
-
-  segments[2].segname = ".bss";
-  segments[2].segnumber = 2;
-  segments[2].segtype = 0xFFFF;        /* reserved - should never be produced */
-  segments[2].segreserved = 0;
-  segments[2].seglength = 0;
-
-  nsegments = 3;
-
-  ofile = fp;
-  error = errfunc;
-
-  seg[0] = saa_init(1L);
-  seg[1] = saa_init(1L);
-  seg[2] = NULL;               /* special case! */
-
-  header = saa_init(1L);
-
-  segtext = seg_alloc();
-  segdata = seg_alloc();
-  segbss = seg_alloc();
-  if (segtext != 0 || segdata != 2 || segbss != 4)
-    error(ERR_PANIC,"rdf segment numbers not allocated as expected (%d,%d,%d)",
-         segtext,segdata,segbss);
-  bsslength=0;
-  headerlength = 0;
-}
-
-static long rdf2_section_names(char *name, int pass, int *bits)
-{
-  int  i;
-  char         * p, * q;
-  int  code = -1;
-  int  reserved = 0;
-
-  /*
-   * Default is 32 bits, in the text segment.
-   */
-  if (!name) {
-    *bits = 32;
-    return 0;
-  }
-
-  /* look for segment type code following segment name */
-  p = name;
-  while (*p && !isspace(*p)) p++;
-  if (*p) {    /* we're now in whitespace */
-    *p++ = '\0';
-    while (*p && isspace(80)) *p++ = '\0';
-  }
-  if (*p) {    /* we're now in an attribute value */
-    /*
-     * see if we have an optional ',number' following the type code
-     */
-    if ((q = strchr(p, ','))) {
-      *q++ = '\0';
-
-      reserved = readnum(q, &i);
-      if (i) {
-         error(ERR_NONFATAL, "value following comma must be numeric");
-         reserved = 0;
-      }
-    }
-    /*
-     * check it against the text strings in segmenttypes 
-     */
-
-    for (i = 0; i < COUNT_SEGTYPES; i++)
-      if (!nasm_stricmp(p, segmenttypes[i])) {
-       code = segmenttypenumbers[i];
-       break;
-      }
-    if (code == -1) {  /* didn't find anything */
-      code = readnum(p, &i);
-      if (i) {
-       error(ERR_NONFATAL, "unrecognised RDF segment type (%s)",p);
-       code = 3;
-      }
-    }
-  }    
-  for (i = 0; i < nsegments; i++) {
-    if (!strcmp(name, segments[i].segname)) {
-      if (code != -1 || reserved != 0) 
-       error(ERR_NONFATAL, "segment attributes specified on"
-             " redeclaration of segment");
-      return segments[i].segnumber * 2;
-    }
-  }
-
-  /* declaring a new segment! */
-
-  if (code == -1) {
-    error(ERR_NONFATAL, "new segment declared without type code");
-    code = 3;
-  }
-  if (nsegments == RDF_MAXSEGS) {
-    error(ERR_FATAL, "reached compiled-in maximum segment limit (%d)",
-         RDF_MAXSEGS);
-    return NO_SEG;
-  }
-
-  segments[nsegments].segname = nasm_strdup(name);
-  i = seg_alloc();
-  if (i % 2 != 0)
-    error(ERR_PANIC, "seg_alloc() returned odd number");
-  segments[nsegments].segnumber = i >> 1;
-  segments[nsegments].segtype = code;
-  segments[nsegments].segreserved = reserved;
-  segments[nsegments].seglength = 0;
-
-  seg[nsegments] = saa_init(1L);
-
-  return i;
-}
-
-static void write_reloc_rec(struct RelocRec *r)
-{
-  char buf[4],*b;
-
-  if (r->refseg != (int16)NO_SEG && (r->refseg & 1)) /* segment base ref */
-      r->type = RDFREC_SEGRELOC;
-
-  r->refseg >>= 1;    /* adjust segment nos to RDF rather than NASM */
-
-  saa_wbytes(header,&r->type,1);
-  saa_wbytes(header,&r->reclen,1);
-  saa_wbytes(header,&r->segment,1);
-  b = buf; WRITELONG(b,r->offset);
-  saa_wbytes(header,buf,4);
-  saa_wbytes(header,&r->length,1);
-  b = buf; WRITESHORT(b,r->refseg);
-  saa_wbytes(header,buf,2);
-  headerlength += r->reclen + 2;
-}
-
-static void write_export_rec(struct ExportRec *r)
-{
-  char buf[4], *b;
-
-  r->segment >>= 1;
-
-  saa_wbytes(header,&r->type,1);
-  saa_wbytes(header,&r->reclen,1);
-  saa_wbytes(header,&r->flags,1);
-  saa_wbytes(header,&r->segment,1);
-  b = buf; WRITELONG(b,r->offset);
-  saa_wbytes(header,buf,4);
-  saa_wbytes(header,r->label,strlen(r->label) + 1);
-  headerlength += r->reclen + 2;
-}
-
-static void write_import_rec(struct ImportRec *r)
-{
-  char buf[4], *b;
-
-  r->segment >>= 1;
-
-  saa_wbytes(header,&r->type,1);
-  saa_wbytes(header,&r->reclen,1);
-  b = buf; WRITESHORT(b,r->segment);
-  saa_wbytes(header,buf,2);
-  saa_wbytes(header,r->label,strlen(r->label) + 1);
-  headerlength += r->reclen + 2;
-}
-
-static void write_bss_rec(struct BSSRec *r)
-{
-    char buf[4], *b;
-
-    saa_wbytes(header,&r->type,1);
-    saa_wbytes(header,&r->reclen,1);
-    b = buf; WRITELONG(b,r->amount);
-    saa_wbytes(header,buf,4);
-    headerlength += r->reclen + 2;
-}
-
-/*
- * Write library record. Also used for module name records.
- */
-static void write_dllmod_rec(struct DLLModRec *r)
-{
-    saa_wbytes(header,&r->type,1);
-    saa_wbytes(header,&r->reclen,1);
-    saa_wbytes(header,r->name,strlen(r->name) + 1);
-    headerlength += r->reclen + 2;
-}
-
-static void rdf2_deflabel(char *name, long segment, long offset,
-                        int is_global, char *special)
-{
-  struct ExportRec r;
-  struct ImportRec ri;
-  static int farsym = 0;
-  static int i;
-  byte export_flags = 0;
-
-  if (is_global != 1) return;
-
-  if (special) {
-    while(*special == ' ' || *special == '\t') special++;
-    
-    if (!nasm_strnicmp(special, "export", 6)) {
-      special += 6;
-      export_flags |= SYM_GLOBAL;  
-    }
-
-    if (*special) {
-      while(isspace(*special)) special++;
-      if (!nasm_stricmp(special, "far")) {
-        farsym = 1;
-      }
-      else if (!nasm_stricmp(special, "near")) {
-        farsym = 0;
-      }
-      else if (!nasm_stricmp(special, "proc") || 
-               !nasm_stricmp(special, "function")) {
-        export_flags |= SYM_FUNCTION;  
-      }
-      else if (!nasm_stricmp(special, "data") ||
-               !nasm_stricmp(special, "object")) {
-        export_flags |= SYM_DATA;
-      }
-      else
-        error(ERR_NONFATAL, "unrecognised symbol type `%s'", special);
-    }  
-  }
-
-  if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
-    error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
-    return;
-  }
-
-  for (i = 0; i < nsegments; i++) {
-    if (segments[i].segnumber == segment>>1) break;
-  }
-  if (i >= nsegments) {   /* EXTERN declaration */
-    if (farsym)
-      ri.type = RDFREC_FARIMPORT;
-    else
-      ri.type = RDFREC_IMPORT;
-    ri.segment = segment;
-    strncpy(ri.label,name,32);
-    ri.label[32] = 0;
-    ri.reclen = 3 + strlen(ri.label);
-    write_import_rec(&ri);
-  } else if (is_global) {
-    r.type = RDFREC_GLOBAL;
-    r.flags = export_flags;
-    r.segment = segment;
-    r.offset = offset;
-    strncpy(r.label,name,32);
-    r.label[32] = 0;
-    r.reclen = 7 + strlen(r.label);
-    write_export_rec(&r);
-  }
-}
-
-static void membufwrite(int segment, void * data, int bytes)
-{
-  int i;
-  char buf[4], * b;
-
-  for (i = 0; i < nsegments; i++) {
-    if (segments[i].segnumber == segment) break;
-  }
-  if (i == nsegments)
-    error(ERR_PANIC, "can't find segment %d", segment);
-  
-  if (bytes < 0) {
-    b = buf;
-    if (bytes == -2)
-      WRITESHORT(b,*(short *)data);
-    else
-      WRITELONG(b,*(long *)data);
-    data = buf;
-    bytes = -bytes;
-  }
-  segments[i].seglength += bytes;
-  saa_wbytes(seg[i],data,bytes);
-}
-
-static int getsegmentlength(int segment)
-{
-  int i;
-  for (i = 0; i < nsegments; i++) {
-    if (segments[i].segnumber == segment) break;
-  }
-  if (i == nsegments)
-    error(ERR_PANIC, "can't find segment %d", segment);
-
-  return segments[i].seglength;
-}
-    
-static void rdf2_out (long segto, void *data, unsigned long type,
-                    long segment, long wrt)
-{
-  long bytes = type & OUT_SIZMASK;
-  struct RelocRec rr;
-  unsigned char databuf[4],*pd;
-  int seg;
-
-  if (segto == NO_SEG) {
-      if ((type & OUT_TYPMASK) != OUT_RESERVE)
-         error (ERR_NONFATAL, "attempt to assemble code in ABSOLUTE space");
-      return;
-  }
-
-  segto >>= 1;    /* convert NASM segment no to RDF number */
-
-  for (seg = 0; seg < nsegments; seg++) {
-    if (segments[seg].segnumber == segto) break;
-  }
-  if (seg >= nsegments) {
-    error(ERR_NONFATAL,"specified segment not supported by rdf output format");
-    return;
-  }
-
-  if (wrt != NO_SEG) {
-    wrt = NO_SEG;                     /* continue to do _something_ */
-    error (ERR_NONFATAL, "WRT not supported by rdf output format");
-  }
-
-  type &= OUT_TYPMASK;
-
-  if (segto == 2 && type != OUT_RESERVE)
-  {
-      error(ERR_NONFATAL, "BSS segments may not be initialised");
-
-      /* just reserve the space for now... */
-
-      if (type == OUT_REL2ADR)
-       bytes = 2;
-      else
-       bytes = 4;
-      type = OUT_RESERVE;
-  }
-
-  if (type == OUT_RESERVE) {
-      if (segto == 2)          /* BSS segment space reserverd */
-         bsslength += bytes;
-      else
-       while (bytes --)
-           membufwrite(segto,databuf,1);
-  }
-  else if (type == OUT_RAWDATA) {
-      if (segment != NO_SEG)
-         error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
-
-      membufwrite(segto,data,bytes);
-  }
-  else if (type == OUT_ADDRESS) {
-
-    /* if segment == NO_SEG then we are writing an address of an
-       object within the same segment - do not produce reloc rec. */
-
-    /* FIXME - is this behaviour sane? at first glance it doesn't
-       appear to be. Must test this thoroughly...! */
-
-    if (segment != NO_SEG)
-    {
-       /* it's an address, so we must write a relocation record */
-
-       rr.type = RDFREC_RELOC;                 /* type signature */
-       rr.reclen = 8;
-       rr.segment = segto;                     /* segment we're currently in */
-       rr.offset = getsegmentlength(segto);    /* current offset */
-       rr.length = bytes;                      /* length of reference */
-       rr.refseg = segment;                    /* segment referred to */
-       write_reloc_rec(&rr);
-    }
-
-    pd = databuf;      /* convert address to little-endian */
-    if (bytes == 2)
-      WRITESHORT (pd, *(long *)data);
-    else
-      WRITELONG (pd, *(long *)data);
-
-    membufwrite(segto,databuf,bytes);
-
-  }
-  else if (type == OUT_REL2ADR)
-  {
-    if (segment == segto)
-      error(ERR_PANIC, "intra-segment OUT_REL2ADR");
-
-    rr.reclen = 8;
-    rr.offset = getsegmentlength(segto);       /* current offset */
-    rr.length = 2;             /* length of reference */
-    rr.refseg = segment;       /* segment referred to (will be >>1'd)*/
-
-    if (segment != NO_SEG && segment % 2) {
-      rr.type = RDFREC_SEGRELOC;
-      rr.segment = segto;      /* memory base refs *aren't ever* relative! */
-      write_reloc_rec(&rr);
-
-      /* what do we put in the code? Simply the data. This should almost
-       * always be zero, unless someone's doing segment arithmetic...
-       */
-      rr.offset = *(long *) data;
-    }
-    else
-    {
-      rr.type = RDFREC_RELOC;  /* type signature */
-      rr.segment = segto+64;   /* segment we're currently in + rel flag */
-      write_reloc_rec(&rr);
-
-      /* work out what to put in the code: offset of the end of this operand,
-       * subtracted from any data specified, so that loader can just add
-       * address of imported symbol onto it to get address relative to end of
-       * instruction: import_address + data(offset) - end_of_instrn */
-
-      rr.offset = *(long *)data -(rr.offset + bytes);
-    }
-    
-    membufwrite(segto,&rr.offset,-2);
-  }
-  else if (type == OUT_REL4ADR)
-  {
-    if (segment == segto)
-      error(ERR_PANIC, "intra-segment OUT_REL4ADR");
-    if (segment != NO_SEG && segment % 2) {
-      error(ERR_PANIC, "erm... 4 byte segment base ref?");
-    }
-
-    rr.type = RDFREC_RELOC;    /* type signature */
-    rr.segment = segto+64;     /* segment we're currently in + rel tag */
-    rr.offset = getsegmentlength(segto);       /* current offset */
-    rr.length = 4;             /* length of reference */
-    rr.refseg = segment;       /* segment referred to */
-    rr.reclen = 8;
-    write_reloc_rec(&rr);
-
-    rr.offset = *(long *)data -(rr.offset + bytes);
-
-    membufwrite(segto,&rr.offset,-4);
-  }
-}
-
-static void rdf2_cleanup (int debuginfo) {
-  long         l;
-  struct BSSRec        bs;
-  int          i;
-
-    (void) debuginfo;
-
-  /* should write imported & exported symbol declarations to header here */
-
-  /* generate the output file... */
-  fwrite(RDOFF2Id,6,1,ofile);  /* file type magic number */
-
-  if (bsslength != 0)          /* reserve BSS */
-  {
-      bs.type = RDFREC_BSS;
-      bs.amount = bsslength;
-      bs.reclen = 4;
-      write_bss_rec(&bs);
-  }
-
-  /*
-   * calculate overall length of the output object
-   */
-  l = headerlength + 4;
-  
-  for (i = 0; i < nsegments; i++) {
-    if (i == 2) continue;      /* skip BSS segment */
-    l += 10 + segments[i].seglength;
-  }
-  l += 10;     /* null segment */
-
-  fwritelong(l, ofile);
-
-  fwritelong(headerlength, ofile);
-  saa_fpwrite(header,ofile);   /* dump header */
-  saa_free(header);
-
-  for (i = 0; i < nsegments; i++) {
-    if (i == 2) continue;
-
-    fwriteshort(segments[i].segtype, ofile);
-    fwriteshort(segments[i].segnumber, ofile);
-    fwriteshort(segments[i].segreserved, ofile);
-    fwritelong(segments[i].seglength, ofile);
-
-    saa_fpwrite(seg[i], ofile);
-    saa_free(seg[i]);
-  }
-
-  /* null segment - write 10 bytes of zero */
-  fwritelong(0,ofile);
-  fwritelong(0,ofile);
-  fwriteshort(0,ofile);
-
-  fclose(ofile);
-}
-
-static long rdf2_segbase (long segment) {
-    return segment;
-}
-
-static int rdf2_directive (char *directive, char *value, int pass) {
-    struct DLLModRec r;
-
-    if (! strcmp(directive, "library")) {
-       if (pass == 1) {
-           r.type = RDFREC_DLL;
-           r.reclen=strlen(value)+1;
-           strcpy(r.name, value);
-           write_dllmod_rec(&r);
-       }
-       return 1;
-    }
-
-    if (! strcmp(directive, "module")) {
-       if (pass == 1) {
-           r.type = RDFREC_MODNAME;
-           r.reclen=strlen(value)+1;
-           strcpy(r.name, value);
-           write_dllmod_rec(&r);
-       }
-       return 1;
-    }
-    
-    return 0;
-}
-
-static void rdf2_filename (char *inname, char *outname, efunc error) {
-  standard_extension(inname,outname,".rdf",error);
-}
-
-static char *rdf2_stdmac[] = {
-    "%define __SECT__ [section .text]",
-    "%imacro library 1+.nolist",
-    "[library %1]",
-    "%endmacro",
-    "%imacro module 1+.nolist",
-    "[module %1]",
-    "%endmacro",
-    "%macro __NASM_CDecl__ 1",
-    "%endmacro",
-    NULL
-};
-
-static int rdf2_set_info(enum geninfo type, char **val)
-{
-    return 0;
-}
-
-
-struct ofmt of_rdf2 = {
-  "Relocatable Dynamic Object File Format v2.0",
-  "rdf",
-  NULL,
-  null_debug_arr,
-  &null_debug_form,
-  rdf2_stdmac,
-  rdf2_init,
-  rdf2_set_info,
-  rdf2_out,
-  rdf2_deflabel,
-  rdf2_section_names,
-  rdf2_segbase,
-  rdf2_directive,
-  rdf2_filename,
-  rdf2_cleanup
-};
-
-#endif /* OF_RDF2 */
index 23d32926441cbea5fdfbedb717614dda29a6352b..653f8a69f1606e7440fa0b3129137226286caf32 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -122,7 +122,7 @@ insn *parse_line (int pass, char *buffer, insn *result,
            expr *value;
 
            i = stdscan(NULL, &tokval);
-           value = evaluate (stdscan, NULL, &tokval, NULL, pass, error, NULL);
+           value = evaluate (stdscan, NULL, &tokval, NULL, pass0, error, NULL);
            i = tokval.t_type;
            if (!value) {              /* but, error in evaluator */
                result->opcode = -1;   /* unrecoverable parse error: */
@@ -189,9 +189,10 @@ insn *parse_line (int pass, char *buffer, insn *result,
        result->opcode == I_RESD ||
        result->opcode == I_RESQ ||
        result->opcode == I_REST ||
-       result->opcode == I_EQU)
+       result->opcode == I_EQU ||
+        result->opcode == I_INCBIN)  /* fbk */
     {
-       critical = pass;
+       critical = pass0;
     }
     else
        critical = (pass==2 ? 2 : 0);
diff --git a/rdoff/Makefile.dj b/rdoff/Makefile.dj
deleted file mode 100644 (file)
index 2099739..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-# Generated automatically from Makefile.in by configure.
-#
-# Auto-configuring Makefile for RDOFF object file utils; part of the
-# Netwide Assembler
-#
-# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
-# Julian Hall. All rights reserved. The software is
-# redistributable under the licence given in the file "Licence"
-# distributed in the NASM archive.
-
-# You may need to adjust these values.
-
-prefix = /djgpp
-CC = gcc -s
-CFLAGS = -O2 -I..
-
-# You _shouldn't_ need to adjust anything below this line.
-
-exec_prefix = ${prefix}
-bindir = ${exec_prefix}/bin
-mandir = ${prefix}/man
-
-INSTALL = /usr/bin/install -c
-INSTALL_PROGRAM = ${INSTALL}
-INSTALL_DATA = ${INSTALL} -m 644
-LN_S = ln -s
-
-LDRDFLIBS = rdoff.o ../nasmlib.o symtab.o hash.o collectn.o rdlib.o segtab.o
-RDXLIBS = rdoff.o rdfload.o symtab.o hash.o collectn.o
-
-.c.o:
-       $(CC) -c $(CFLAGS) $*.c
-
-all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
-
-rdfdump: rdfdump.o
-       $(CC) -o rdfdump rdfdump.o
-
-ldrdf: ldrdf.o $(LDRDFLIBS)
-       $(CC) -o ldrdf ldrdf.o $(LDRDFLIBS)
-rdx: rdx.o $(RDXLIBS)
-       $(CC) -o rdx rdx.o $(RDXLIBS)
-rdflib: rdflib.o
-       $(CC) -o rdflib rdflib.o
-rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
-       $(CC) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o
-rdf2com:
-       $(LN_S) rdf2bin rdf2com
-
-rdf2bin.o: rdf2bin.c
-rdfdump.o: rdfdump.c
-rdoff.o: rdoff.c rdoff.h
-ldrdf.o: ldrdf.c rdoff.h ../nasmlib.h symtab.h collectn.h rdlib.h
-symtab.o: symtab.c symtab.h hash.h
-collectn.o: collectn.c collectn.h
-rdx.o: rdx.c rdoff.h rdfload.h symtab.h
-rdfload.o: rdfload.c rdfload.h rdoff.h collectn.h symtab.h
-rdlib.o: rdlib.c rdlib.h
-rdflib.o: rdflib.c
-hash.o: hash.c hash.h
-segtab.o: segtab.c segtab.h
-
-nasmlib.o: ../nasmlib.c ../nasmlib.h ../names.c ../nasm.h
-       $(CC) -c $(CFLAGS) ../nasmlib.c
-
-clean:
-       rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com
-
-install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
-       $(INSTALL_PROGRAM) rdfdump $(bindir)/rdfdump
-       $(INSTALL_PROGRAM) ldrdf $(bindir)/ldrdf
-       $(INSTALL_PROGRAM) rdx $(bindir)/rdx
-       $(INSTALL_PROGRAM) rdflib $(bindir)/rdflib
-       $(INSTALL_PROGRAM) rdf2bin $(bindir)/rdf2bin
-       cd $(bindir); $(LN_S) rdf2bin rdf2com
diff --git a/rdoff/Makefile.emx b/rdoff/Makefile.emx
deleted file mode 100644 (file)
index fbaa934..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-# Generated automatically from Makefile.in by configure.
-# $Id$
-#
-# Auto-configuring Makefile for RDOFF object file utils; part of the
-# Netwide Assembler
-#
-# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
-# Julian Hall. All rights reserved. The software is
-# redistributable under the licence given in the file "Licence"
-# distributed in the NASM archive.
-
-top_srcdir     = ..
-srcdir         = .
-prefix         = /usr/local
-exec_prefix    = ${prefix}
-bindir         = ${exec_prefix}/bin
-mandir         = ${prefix}/man
-
-CC             = gcc
-CFLAGS         = -s -Zomf -O2 -fomit-frame-pointer -Wall -ansi -pedantic -I$(srcdir) -I$(top_srcdir)
-LDFLAGS                = -s -Zomf -Zexe -Zcrtdll
-LIBS           = -lgcc
-
-INSTALL                = .././install-sh -c
-INSTALL_PROGRAM        = ${INSTALL}
-INSTALL_DATA   = ${INSTALL} -m 644
-
-LDRDFLIBS      = rdoff.o nasmlib.o symtab.o collectn.o rdlib.o segtab.o hash.o
-RDXLIBS        = rdoff.o rdfload.o symtab.o collectn.o hash.o
-
-.c.o:
-       $(CC) -c $(CFLAGS) -o $@ $<
-
-all: rdfdump ldrdf rdx rdflib rdf2bin
-
-rdfdump: rdfdump.o
-       $(CC) $(LDFLAGS) -o rdfdump rdfdump.o $(LIBS)
-ldrdf: ldrdf.o $(LDRDFLIBS)
-       $(CC) $(LDFLAGS) -o ldrdf ldrdf.o $(LDRDFLIBS) $(LIBS)
-rdx: rdx.o $(RDXLIBS)
-       $(CC) $(LDFLAGS) -o rdx rdx.o $(RDXLIBS) $(LIBS)
-rdflib: rdflib.o
-       $(CC) $(LDFLAGS) -o rdflib rdflib.o $(LIBS)
-rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
-       $(CC) $(LDFLAGS) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o $(LIBS)
-
-rdf2bin.o: rdf2bin.c
-rdfdump.o: rdfdump.c
-rdoff.o: rdoff.c rdoff.h
-ldrdf.o: ldrdf.c rdoff.h $(top_srcdir)/nasmlib.h symtab.h collectn.h rdlib.h
-symtab.o: symtab.c symtab.h
-collectn.o: collectn.c collectn.h
-rdx.o: rdx.c rdoff.h rdfload.h symtab.h
-rdfload.o: rdfload.c rdfload.h rdoff.h collectn.h symtab.h
-rdlib.o: rdlib.c rdlib.h
-rdflib.o: rdflib.c
-segtab.o: segtab.c
-
-nasmlib.o: $(top_srcdir)/nasmlib.c
-       $(CC) -c $(CFLAGS) -o $@ $(top_srcdir)/nasmlib.c
-
-clean:
-       rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com
-
-spotless: clean
-       rm -f Makefile
-
-distclean: spotless
-
-install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
-       $(INSTALL_PROGRAM) rdfdump $(INSTALLROOT)$(bindir)/rdfdump
-       $(INSTALL_PROGRAM) ldrdf $(INSTALLROOT)$(bindir)/ldrdf
-       $(INSTALL_PROGRAM) rdx $(INSTALLROOT)$(bindir)/rdx
-       $(INSTALL_PROGRAM) rdflib $(INSTALLROOT)$(bindir)/rdflib
-       $(INSTALL_PROGRAM) rdf2bin $(INSTALLROOT)$(bindir)/rdf2bin
-       cd $(INSTALLROOT)$(bindir) && rm -f rdf2com && $(LN_S) rdf2bin rdf2com
diff --git a/rdoff/Makefile.sc b/rdoff/Makefile.sc
deleted file mode 100644 (file)
index 7b45fe7..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-# Makefile for RDOFF object file utils; part of the Netwide Assembler
-#
-# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
-# Julian Hall. All rights reserved. The software is
-# redistributable under the licence given in the file "Licence"
-# distributed in the NASM archive.
-#
-# This Makefile is designed for use under Unix (probably fairly
-# portably).
-
-CC = sc
-CCFLAGS = -I..\ -c -a1 -mn -Nc -w2 -w7 -o+time -5
-LINK = link
-LINKFLAGS = /noi /exet:NT /su:console
-
-OBJ=obj
-EXE=.exe
-
-NASMLIB = ..\nasmlib.$(OBJ)
-NASMLIB_H = ..\nasmlib.h
-LDRDFLIBS = rdoff.$(OBJ) $(NASMLIB) symtab.$(OBJ) collectn.$(OBJ) rdlib.$(OBJ)
-RDXLIBS = rdoff.$(OBJ) rdfload.$(OBJ) symtab.$(OBJ) collectn.$(OBJ)
-
-.c.$(OBJ):
-       $(CC) $(CCFLAGS) $*.c
-
-all : rdfdump$(EXE) ldrdf$(EXE) rdx$(EXE) rdflib$(EXE) rdf2bin$(EXE) rdf2com$(EXE)
-
-rdfdump$(EXE)   : rdfdump.$(OBJ)
-        $(LINK) $(LINKFLAGS) rdfdump.$(OBJ), rdfdump$(EXE);
-ldrdf$(EXE)     : ldrdf.$(OBJ) $(LDRDFLIBS)
-        $(LINK) $(LINKFLAGS) ldrdf.$(OBJ) $(LDRDFLIBS), ldrdf$(EXE);
-rdx$(EXE)       : rdx.$(OBJ) $(RDXLIBS)
-        $(LINK) $(LINKFLAGS) rdx.$(OBJ) $(RDXLIBS), rdx$(EXE);
-rdflib$(EXE)    : rdflib.$(OBJ)
-        $(LINK) $(LINKFLAGS) rdflib.$(OBJ), rdflib$(EXE);
-rdf2bin$(EXE)   : rdf2bin.$(OBJ) $(RDXLIBS) $(NASMLIB)
-        $(LINK) $(LINKFLAGS) rdf2bin.$(OBJ) $(RDXLIBS) $(NASMLIB), rdf2bin$(EXE);
-rdf2com$(EXE)   : rdf2bin$(EXE)
-        copy rdf2bin$(EXE) rdf2com$(EXE)
-
-rdf2bin.$(OBJ)  : rdf2bin.c
-rdfdump.$(OBJ)  : rdfdump.c
-rdoff.$(OBJ)    : rdoff.c rdoff.h
-ldrdf.$(OBJ)    : ldrdf.c rdoff.h $(NASMLIB_H) symtab.h collectn.h rdlib.h
-symtab.$(OBJ)   : symtab.c symtab.h
-collectn.$(OBJ) : collectn.c collectn.h
-rdx.$(OBJ)      : rdx.c rdoff.h rdfload.h symtab.h
-rdfload.$(OBJ)  : rdfload.c rdfload.h rdoff.h collectn.h symtab.h
-rdlib.$(OBJ)    : rdlib.c rdlib.h
-rdflib.$(OBJ)   : rdflib.c
-
-clean :
-        del *.$(OBJ) rdfdump$(EXE) ldrdf$(EXE) rdx$(EXE) rdflib$(EXE) rdf2bin$(EXE)
-
-
diff --git a/rdoff/Makefile.unx b/rdoff/Makefile.unx
deleted file mode 100644 (file)
index 89d439f..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-# Generated automatically from Makefile.in by configure.
-#
-# Auto-configuring Makefile for RDOFF object file utils; part of the
-# Netwide Assembler
-#
-# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
-# Julian Hall. All rights reserved. The software is
-# redistributable under the licence given in the file "Licence"
-# distributed in the NASM archive.
-
-# You may need to adjust these values.
-
-prefix = /usr/local
-CC = cc
-CFLAGS = -O -I..
-
-# You _shouldn't_ need to adjust anything below this line.
-
-exec_prefix = ${prefix}
-bindir = ${exec_prefix}/bin
-mandir = ${prefix}/man
-
-INSTALL = /usr/bin/install -c
-INSTALL_PROGRAM = ${INSTALL}
-INSTALL_DATA = ${INSTALL} -m 644
-LN_S = ln -s
-
-LDRDFLIBS = rdoff.o ../nasmlib.o symtab.o hash.o collectn.o rdlib.o segtab.o
-RDXLIBS = rdoff.o rdfload.o symtab.o hash.o collectn.o
-
-.c.o:
-       $(CC) -c $(CFLAGS) $*.c
-
-all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
-
-rdfdump: rdfdump.o
-       $(CC) -o rdfdump rdfdump.o
-
-ldrdf: ldrdf.o $(LDRDFLIBS)
-       $(CC) -o ldrdf ldrdf.o $(LDRDFLIBS)
-rdx: rdx.o $(RDXLIBS)
-       $(CC) -o rdx rdx.o $(RDXLIBS)
-rdflib: rdflib.o
-       $(CC) -o rdflib rdflib.o
-rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
-       $(CC) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o
-rdf2com:
-       $(LN_S) rdf2bin rdf2com
-
-rdf2bin.o: rdf2bin.c
-rdfdump.o: rdfdump.c
-rdoff.o: rdoff.c rdoff.h
-ldrdf.o: ldrdf.c rdoff.h ../nasmlib.h symtab.h collectn.h rdlib.h
-symtab.o: symtab.c symtab.h hash.h
-collectn.o: collectn.c collectn.h
-rdx.o: rdx.c rdoff.h rdfload.h symtab.h
-rdfload.o: rdfload.c rdfload.h rdoff.h collectn.h symtab.h
-rdlib.o: rdlib.c rdlib.h
-rdflib.o: rdflib.c
-hash.o: hash.c hash.h
-segtab.o: segtab.c segtab.h
-
-nasmlib.o: ../nasmlib.c ../nasmlib.h ../names.c ../nasm.h
-       $(CC) -c $(CFLAGS) ../nasmlib.c
-
-clean:
-       rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com
-
-install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
-       $(INSTALL_PROGRAM) rdfdump $(bindir)/rdfdump
-       $(INSTALL_PROGRAM) ldrdf $(bindir)/ldrdf
-       $(INSTALL_PROGRAM) rdx $(bindir)/rdx
-       $(INSTALL_PROGRAM) rdflib $(bindir)/rdflib
-       $(INSTALL_PROGRAM) rdf2bin $(bindir)/rdf2bin
-       cd $(bindir); $(LN_S) rdf2bin rdf2com
index 520bb193057cf3ec4a9bc61c9b4791a5a1210ffe..91bffa52da8aa4712505ac8e012588ff4c9fb95c 100644 (file)
@@ -1,5 +1,5 @@
 #! /bin/sh
-
 [ $1 ] || {
     echo "Usage: $0 <library name> <module> [...]"
     exit 1
diff --git a/zoutieee.c b/zoutieee.c
deleted file mode 100644 (file)
index 9784e79..0000000
+++ /dev/null
@@ -1,1461 +0,0 @@
-/* outieee.c   output routines for the Netwide Assembler to produce
- *             IEEE-std object files
- *
- * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
- * Julian Hall. All rights reserved. The software is
- * redistributable under the licence given in the file "Licence"
- * distributed in the NASM archive.
- */
-
-/* notes: I have tried to make this correspond to the IEEE version
- * of the standard, specifically the primary ASCII version.  It should
- * be trivial to create the binary version given this source (which is
- * one of MANY things that have to be done to make this correspond to
- * the hp-microtek version of the standard).
- *
- * 16-bit support is assumed to use 24-bit addresses
- * The linker can sort out segmentation-specific stuff
- * if it keeps track of externals
- * in terms of being relative to section bases
- *
- * A non-standard variable type, the 'Yn' variable, has been introduced.
- * Basically it is a reference to extern 'n'- denoting the low limit
- * (L-variable) of the section that extern 'n' is defined in.  Like the
- * x variable, there may be no explicit assignment to it, it is derived
- * from the public definition corresponding to the extern name.  This
- * is required because the one thing the mufom guys forgot to do well was
- * take into account segmented architectures.
- *
- * I use comment classes for various things and these are undefined by
- * the standard.
- *
- * Debug info should be considered totally non-standard (local labels are
- * standard but linenum records are not covered by the standard.
- * Type defs have the standard format but absolute meanings for ordinal
- * types are not covered by the standard.)
- *
- * David Lindauer, LADsoft
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <stdarg.h>  /* Note: we need the ANSI version of stdarg.h */
-#include <ctype.h>
-
-#include "nasm.h"
-#include "nasmlib.h"
-#include "outform.h"
-
-#ifdef OF_IEEE
-
-#define ARRAY_BOT 0x1
-
-static char ieee_infile[FILENAME_MAX];
-static int ieee_uppercase;
-
-static efunc error;
-static ldfunc deflabel;
-static FILE *ofp;
-static int any_segs;
-static int arrindex;
-
-#define HUNKSIZE 1024                 /* Size of the data hunk */
-#define EXT_BLKSIZ 512
-#define LDPERLINE 32                   /* bytes per line in output */
-
-struct ieeeSection;
-
-struct LineNumber {
-    struct LineNumber *next;
-    struct ieeeSection *segment;
-    long offset;
-    long lineno;
-};
-
-static struct FileName {
-    struct FileName *next;
-    char *name;
-    long index;
-} *fnhead, **fntail;
-
-static struct Array {
-    struct Array *next;
-    unsigned size;
-    int basetype;
-} *arrhead, **arrtail;
-
-static struct ieeePublic {
-    struct ieeePublic *next;
-    char *name;
-    long offset;
-    long segment;                     /* only if it's far-absolute */
-    long index;
-    int type;                          /* for debug purposes */        
-} *fpubhead, **fpubtail, *last_defined;
-
-static struct ieeeExternal {
-    struct ieeeExternal *next;
-    char *name;
-    long commonsize;
-} *exthead, **exttail;
-
-static int externals;
-
-static struct ExtBack {
-    struct ExtBack *next;
-    int index[EXT_BLKSIZ];
-} *ebhead, **ebtail;
-
-/* NOTE: the first segment MUST be the lineno segment */
-static struct ieeeSection {
-    struct ieeeObjData *data,*datacurr;
-    struct ieeeSection *next;
-    struct ieeeFixupp *fptr, * flptr;
-    long index;                               /* the NASM segment id */
-    long ieee_index;                  /* the OBJ-file segment index */
-    long currentpos;
-    long align;                               /* can be SEG_ABS + absolute addr */
-    long startpos;
-    enum {
-       CMB_PRIVATE = 0,
-       CMB_PUBLIC = 2,
-       CMB_COMMON = 6
-    } combine;
-    long use32;                               /* is this segment 32-bit? */
-    struct ieeePublic *pubhead, **pubtail, *lochead, **loctail;
-    char *name;
-} *seghead, **segtail, *ieee_seg_needs_update;
-
-struct ieeeObjData {
-    struct ieeeObjData *next;
-    unsigned char data[HUNKSIZE];
-};
-
-struct ieeeFixupp {
-    struct ieeeFixupp *next;
-    enum { 
-       FT_SEG = 0,
-       FT_REL = 1,
-       FT_OFS = 2,
-       FT_EXT = 3,
-       FT_WRT = 4,
-       FT_EXTREL = 5,
-       FT_EXTWRT = 6,
-       FT_EXTSEG = 7
-    } ftype;
-    short size;
-    long id1;
-    long id2;
-    long offset;
-    long addend;
-};
-               
-static long ieee_entry_seg, ieee_entry_ofs;
-static int checksum;
-
-extern struct ofmt of_ieee;
-
-static void ieee_data_new(struct ieeeSection *);
-static void ieee_write_fixup (long, long, struct ieeeSection *,
-                               int, unsigned long, long);
-static void ieee_install_fixup(struct ieeeSection *, struct ieeeFixupp *);
-static long ieee_segment (char *, int, int *);
-static void ieee_write_file(int debuginfo);
-static void ieee_write_byte(struct ieeeSection *, int);
-static void ieee_write_word(struct ieeeSection *, int);
-static void ieee_write_dword(struct ieeeSection *, long);
-static void ieee_putascii(char *, ...);
-static void ieee_putcs(int);
-static long ieee_putld(long, long, unsigned char *);
-static long ieee_putlr(struct ieeeFixupp *);
-static void ieee_unqualified_name(char *, char *);
-
-
-/* 
- * pup init 
- */
-static void ieee_init (FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) 
-{
-    (void) eval;
-    ofp = fp;
-    error = errfunc;
-    deflabel = ldef;
-    any_segs = FALSE;
-    fpubhead = NULL;
-    fpubtail = &fpubhead;
-    exthead = NULL;
-    exttail = &exthead;
-    externals = 1;
-    ebhead = NULL;
-    ebtail = &ebhead;
-    seghead = ieee_seg_needs_update = NULL;
-    segtail = &seghead;
-    ieee_entry_seg = NO_SEG;
-    ieee_uppercase = FALSE;
-    checksum = 0;
-    of_ieee.current_dfmt->init (&of_ieee,NULL,fp,errfunc);
-}
-static int ieee_set_info(enum geninfo type, char **val)
-{
-    (void) type;
-    (void) val;
-
-    return 0;
-}
-/*
- * Rundown
- */
-static void ieee_cleanup (int debuginfo) 
-{
-    ieee_write_file(debuginfo);
-    of_ieee.current_dfmt->cleanup ();
-    fclose (ofp);
-    while (seghead) {
-       struct ieeeSection *segtmp = seghead;
-       seghead = seghead->next;
-       while (segtmp->pubhead) {
-           struct ieeePublic *pubtmp = segtmp->pubhead;
-           segtmp->pubhead = pubtmp->next;
-           nasm_free (pubtmp);
-       }
-       while (segtmp->fptr) {
-           struct ieeeFixupp *fixtmp = segtmp->fptr;
-           segtmp->fptr = fixtmp->next;
-           nasm_free(fixtmp);
-       }
-       while (segtmp->data) {
-           struct ieeeObjData *dattmp = segtmp->data;
-           segtmp->data = dattmp->next;
-           nasm_free(dattmp);
-       }
-       nasm_free (segtmp);
-    }
-    while (fpubhead) {
-       struct ieeePublic *pubtmp = fpubhead;
-       fpubhead = fpubhead->next;
-       nasm_free (pubtmp);
-    }
-    while (exthead) {
-       struct ieeeExternal *exttmp = exthead;
-       exthead = exthead->next;
-       nasm_free (exttmp);
-    }
-    while (ebhead) {
-       struct ExtBack *ebtmp = ebhead;
-       ebhead = ebhead->next;
-       nasm_free (ebtmp);
-    }
-}
-/*
- * callback for labels
- */
-static void ieee_deflabel (char *name, long segment,
-                         long offset, int is_global, char *special) {
-    /*
-     * We have three cases:
-     *
-     * (i) `segment' is a segment-base. If so, set the name field
-     * for the segment structure it refers to, and then
-     * return.
-     *
-     * (ii) `segment' is one of our segments, or a SEG_ABS segment.
-     * Save the label position for later output of a PUBDEF record.
-     * 
-     *
-     * (iii) `segment' is not one of our segments. Save the label
-     * position for later output of an EXTDEF.
-     */
-    struct ieeeExternal *ext;
-    struct ExtBack *eb;
-    struct ieeeSection *seg;
-    int i;
-
-    if (special) {
-        error(ERR_NONFATAL, "unrecognised symbol type `%s'", special);
-    }
-    /*
-     * First check for the double-period, signifying something
-     * unusual.
-     */
-    if (name[0] == '.' && name[1] == '.') {
-       if (!strcmp(name, "..start")) {
-           ieee_entry_seg = segment;
-           ieee_entry_ofs = offset;
-       }
-       return;
-    }
-
-    /*
-     * Case (i):
-     */
-    if (ieee_seg_needs_update) {
-       ieee_seg_needs_update->name = name;
-       return;
-    } 
-    if (segment < SEG_ABS && segment != NO_SEG && segment % 2)
-       return;
-
-    /*
-     * case (ii)
-     */
-    if (segment >= SEG_ABS) {
-       /*
-        * SEG_ABS subcase of (ii).
-        */
-       if (is_global) {
-           struct ieeePublic *pub;
-
-           pub = *fpubtail = nasm_malloc(sizeof(*pub));
-           fpubtail = &pub->next;
-           pub->next = NULL;
-           pub->name = name;
-           pub->offset = offset;
-           pub->segment = segment & ~SEG_ABS;
-       }
-       return;
-    }
-
-    for (seg = seghead; seg && is_global; seg = seg->next)
-       if (seg->index == segment) {
-               struct ieeePublic *pub;
-
-           last_defined = pub = *seg->pubtail = nasm_malloc(sizeof(*pub));
-           seg->pubtail = &pub->next;
-           pub->next = NULL;
-           pub->name = name;
-           pub->offset = offset;
-           pub->index = seg->ieee_index;
-           pub->segment = -1;
-           return;
-       }
-
-    /*
-     * Case (iii).
-     */
-    if (is_global) {
-        ext = *exttail = nasm_malloc(sizeof(*ext));
-        ext->next = NULL;
-        exttail = &ext->next;
-        ext->name = name;
-        if (is_global == 2)
-           ext->commonsize = offset;
-       else
-           ext->commonsize = 0;
-       i = segment/2;
-       eb = ebhead;
-       if (!eb) {
-           eb = *ebtail = nasm_malloc(sizeof(*eb));
-           eb->next = NULL;
-           ebtail = &eb->next;
-        }
-       while (i > EXT_BLKSIZ) {
-           if (eb && eb->next)
-               eb = eb->next;
-           else {
-               eb = *ebtail = nasm_malloc(sizeof(*eb));
-               eb->next = NULL;
-               ebtail = &eb->next;
-           }
-           i -= EXT_BLKSIZ;
-       }
-        eb->index[i] = externals++;
-    }
-       
-}
-
-/*
- * Put data out
- */
-static void ieee_out (long segto, void *data, unsigned long type,
-                    long segment, long wrt) {
-    unsigned long size, realtype;
-    unsigned char *ucdata;
-    long ldata;
-    struct ieeeSection *seg;
-
-    /*
-     * handle absolute-assembly (structure definitions)
-     */
-    if (segto == NO_SEG) {
-       if ((type & OUT_TYPMASK) != OUT_RESERVE)
-           error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
-                  " space");
-       return;
-    }
-
-    /*
-     * If `any_segs' is still FALSE, we must define a default
-     * segment.
-     */
-    if (!any_segs) {
-       int tempint;                   /* ignored */
-       if (segto != ieee_segment("__NASMDEFSEG", 2, &tempint))
-           error (ERR_PANIC, "strange segment conditions in IEEE driver");
-    }
-
-    /*
-     * Find the segment we are targetting.
-     */
-    for (seg = seghead; seg; seg = seg->next)
-       if (seg->index == segto)
-           break;
-    if (!seg)
-       error (ERR_PANIC, "code directed to nonexistent segment?");
-
-    size = type & OUT_SIZMASK;
-    realtype = type & OUT_TYPMASK;
-    if (realtype == OUT_RAWDATA) {
-       ucdata = data;
-       while (size--)
-           ieee_write_byte(seg,*ucdata++);
-    } else if (realtype == OUT_ADDRESS || realtype == OUT_REL2ADR ||
-              realtype == OUT_REL4ADR) {
-       if (segment == NO_SEG && realtype != OUT_ADDRESS)
-           error(ERR_NONFATAL, "relative call to absolute address not"
-                 " supported by IEEE format");
-       ldata = *(long *)data;
-       if (realtype == OUT_REL2ADR)
-           ldata += (size-2);
-       if (realtype == OUT_REL4ADR)
-           ldata += (size-4);
-       ieee_write_fixup (segment, wrt, seg, size, realtype,ldata);
-       if (size == 2)
-           ieee_write_word (seg, ldata);
-       else
-           ieee_write_dword (seg, ldata);
-    } 
-    else if (realtype == OUT_RESERVE) {
-       while (size--)
-           ieee_write_byte(seg,0);
-    }
-}
-
-static void ieee_data_new(struct ieeeSection *segto) {
-    
-    if (!segto->data)
-       segto->data = segto->datacurr = nasm_malloc(sizeof(*(segto->datacurr)));
-    else
-       segto->datacurr = segto->datacurr->next = nasm_malloc(sizeof(*(segto->datacurr)));
-    segto->datacurr->next = NULL;
-}
-
-
-/*
- * this routine is unalduterated bloatware.  I usually don't do this
- * but I might as well see what it is like on a harmless program.
- * If anyone wants to optimize this is a good canditate!
- */
-static void ieee_write_fixup (long segment, long wrt, struct ieeeSection * segto,
-                               int size, unsigned long realtype, long offset) {
-    struct ieeeSection *target;
-    struct ieeeFixupp s;
-
-    /* Don't put a fixup for things NASM can calculate */
-    if (wrt == NO_SEG && segment == NO_SEG)
-       return;
-
-    s.ftype = -1;
-    /* if it is a WRT offset */
-    if (wrt != NO_SEG) {
-       s.ftype = FT_WRT;
-       s.addend = offset;
-       if (wrt >= SEG_ABS)
-           s.id1 = -(wrt-SEG_ABS);
-       else {
-           if (wrt %2 && realtype != OUT_REL2ADR && realtype != OUT_REL4ADR) {
-               wrt--;
-
-               for (target = seghead; target; target = target->next)
-                   if (target->index == wrt)
-                       break;
-               if (target) {
-                   s.id1 = target->ieee_index;
-                   for (target = seghead; target; target = target->next)
-                       if (target->index == segment)
-                           break;
-               
-                   if (target) 
-                       s.id2 = target->ieee_index;
-                   else {
-                       /*
-                        * Now we assume the segment field is being used
-                        * to hold an extern index
-                        */
-                       long i = segment/2;
-                       struct ExtBack *eb = ebhead;
-                       while (i > EXT_BLKSIZ) {
-                           if (eb)
-                               eb = eb->next;
-                           else
-                               break;
-                           i -= EXT_BLKSIZ;
-                       }
-                               /* if we have an extern decide the type and make a record
-                        */
-                       if (eb) {
-                               s.ftype = FT_EXTWRT;
-                               s.addend = 0;
-                               s.id2 = eb->index[i];
-                       }
-                       else
-                           error(ERR_NONFATAL,
-                               "Source of WRT must be an offset");
-                   }
-                       
-               }
-               else 
-                   error(ERR_PANIC,
-                         "unrecognised WRT value in ieee_write_fixup");
-           }
-           else 
-               error(ERR_NONFATAL,"target of WRT must be a section ");
-       }
-       s.size = size;
-       ieee_install_fixup(segto,&s);
-       return;
-    }
-    /* Pure segment fixup ? */
-    if (segment != NO_SEG) {
-       s.ftype = FT_SEG;
-       s.id1 = 0;
-       if (segment >= SEG_ABS) {
-           /* absolute far segment fixup */
-           s.id1 = -(segment -~SEG_ABS);
-       }
-       else if (segment % 2) {
-           /* fixup to named segment */
-           /* look it up */
-           for (target = seghead; target; target = target->next)
-               if (target->index == segment-1)
-                   break;
-           if (target)
-               s.id1 = target->ieee_index;
-           else {
-               /*
-                * Now we assume the segment field is being used
-                * to hold an extern index
-                */
-               long i = segment/2;
-               struct ExtBack *eb = ebhead;
-               while (i > EXT_BLKSIZ) {
-                   if (eb)
-                       eb = eb->next;
-                   else
-                       break;
-                   i -= EXT_BLKSIZ;
-               }
-               /* if we have an extern decide the type and make a record
-                */
-               if (eb) {
-                   if (realtype == OUT_REL2ADR || realtype == OUT_REL4ADR) {
-                       error(ERR_PANIC,"Segment of a rel not supported in ieee_write_fixup");
-                   }
-                   else {
-                               /* If we want the segment */
-                           s.ftype = FT_EXTSEG;
-                           s.addend = 0;
-                           s.id1 = eb->index[i];
-                   }
-                   
-               }
-               else 
-                   /* If we get here the seg value doesn't make sense */
-                   error(ERR_PANIC,
-                         "unrecognised segment value in ieee_write_fixup");
-           }
-
-        } else {
-           /* Assume we are offsetting directly from a section
-            * So look up the target segment
-            */
-           for (target = seghead; target; target = target->next)
-               if (target->index == segment)
-                   break;
-           if (target) {
-               if (realtype == OUT_REL2ADR || realtype == OUT_REL4ADR) {
-                   /* PC rel to a known offset */
-                   s.id1 = target->ieee_index;
-                   s.ftype = FT_REL;
-                   s.size = size;
-                   s.addend = offset;
-               }
-               else {
-                   /* We were offsetting from a seg */
-                   s.id1 = target->ieee_index;
-                   s.ftype = FT_OFS;
-                   s.size = size;
-                   s.addend = offset;
-               }
-           }
-           else {
-               /*
-                * Now we assume the segment field is being used
-                * to hold an extern index
-                */
-               long i = segment/2;
-               struct ExtBack *eb = ebhead;
-               while (i > EXT_BLKSIZ) {
-                   if (eb)
-                       eb = eb->next;
-                   else
-                       break;
-                   i -= EXT_BLKSIZ;
-               }
-               /* if we have an extern decide the type and make a record
-                */
-               if (eb) {
-                   if (realtype == OUT_REL2ADR || realtype == OUT_REL4ADR) {
-                       s.ftype = FT_EXTREL;
-                       s.addend = 0;
-                       s.id1 = eb->index[i];
-                   }
-                   else {
-                           /* else we want the external offset */
-                           s.ftype = FT_EXT;
-                           s.addend = 0;
-                           s.id1 = eb->index[i];
-                   }
-                   
-               }
-               else 
-                   /* If we get here the seg value doesn't make sense */
-                   error(ERR_PANIC,
-                         "unrecognised segment value in ieee_write_fixup");
-           }
-       }
-       if (size != 2 && s.ftype == FT_SEG)
-           error(ERR_NONFATAL, "IEEE format can only handle 2-byte"
-                    " segment base references");
-       s.size = size;
-       ieee_install_fixup(segto,&s);
-       return;
-    }
-    /* should never get here */
-}
-static void ieee_install_fixup(struct ieeeSection *seg, struct ieeeFixupp *fix)
-{
-    struct ieeeFixupp *f;
-    f = nasm_malloc(sizeof(struct ieeeFixupp));
-    memcpy(f,fix,sizeof(struct ieeeFixupp));
-    f->offset = seg->currentpos;
-    seg->currentpos += fix->size;
-    f->next = NULL;
-    if (seg->fptr)
-       seg->flptr = seg->flptr->next = f;
-    else
-       seg->fptr = seg->flptr = f;
-
-}
-
-/*
- * segment registry
- */
-static long ieee_segment (char *name, int pass, int *bits) {
-    /*
-     * We call the label manager here to define a name for the new
-     * segment, and when our _own_ label-definition stub gets
-     * called in return, it should register the new segment name
-     * using the pointer it gets passed. That way we save memory,
-     * by sponging off the label manager.
-     */
-    if (!name) {
-       *bits = 16;
-       if (!any_segs)
-               return 0;
-       return seghead->index;
-    } else {
-       struct ieeeSection *seg;
-       int ieee_idx, attrs, rn_error;
-       char *p;
-
-       /*
-        * Look for segment attributes.
-        */
-       attrs = 0;
-       while (*name == '.')
-           name++;                    /* hack, but a documented one */
-       p = name;
-       while (*p && !isspace(*p))
-           p++;
-       if (*p) {
-           *p++ = '\0';
-           while (*p && isspace(*p))
-               *p++ = '\0';
-       }
-       while (*p) {
-           while (*p && !isspace(*p))
-               p++;
-           if (*p) {
-               *p++ = '\0';
-               while (*p && isspace(*p))
-                   *p++ = '\0';
-           }
-
-           attrs++;
-       }
-
-       ieee_idx = 1;
-       for (seg = seghead; seg; seg = seg->next) {
-           ieee_idx++;
-           if (!strcmp(seg->name, name)) {
-               if (attrs > 0 && pass == 1)
-                   error(ERR_WARNING, "segment attributes specified on"
-                         " redeclaration of segment: ignoring");
-               if (seg->use32)
-                   *bits = 32;
-               else
-                   *bits = 16;
-               return seg->index;
-           }
-       }
-
-       *segtail = seg = nasm_malloc(sizeof(*seg));
-       seg->next = NULL;
-       segtail = &seg->next;
-       seg->index = seg_alloc();
-       seg->ieee_index = ieee_idx;
-       any_segs = TRUE;
-       seg->name = NULL;
-       seg->currentpos = 0;
-       seg->align = 1;                /* default */
-       seg->use32 = *bits == 32;      /* default to user spec */
-       seg->combine = CMB_PUBLIC;     /* default */
-       seg->pubhead = NULL;
-       seg->pubtail = &seg->pubhead;
-       seg->data = NULL;
-       seg->fptr = NULL;
-       seg->lochead = NULL;
-       seg->loctail = &seg->lochead;
-
-       /*
-        * Process the segment attributes.
-        */
-       p = name;
-       while (attrs--) {
-           p += strlen(p);
-           while (!*p) p++;
-
-           /*
-            * `p' contains a segment attribute.
-            */
-           if (!nasm_stricmp(p, "private"))
-               seg->combine = CMB_PRIVATE;
-           else if (!nasm_stricmp(p, "public"))
-               seg->combine = CMB_PUBLIC;
-           else if (!nasm_stricmp(p, "common"))
-               seg->combine = CMB_COMMON;
-           else if (!nasm_stricmp(p, "use16"))
-               seg->use32 = FALSE;
-           else if (!nasm_stricmp(p, "use32"))
-               seg->use32 = TRUE;
-           else if (!nasm_strnicmp(p, "align=", 6)) {
-               seg->align = readnum(p+6, &rn_error);
-               if (seg->align == 0)
-                   seg->align = 1;
-               if (rn_error) {
-                   seg->align = 1;
-                   error (ERR_NONFATAL, "segment alignment should be"
-                          " numeric");
-               }
-               switch ((int) seg->align) {
-                 case 1:              /* BYTE */
-                 case 2:              /* WORD */
-                 case 4:              /* DWORD */
-                 case 16:             /* PARA */
-                 case 256:            /* PAGE */
-                 case 8:
-                 case 32:
-                 case 64:
-                 case 128:
-                   break;
-                 default:
-                   error(ERR_NONFATAL, "invalid alignment value %d",
-                         seg->align);
-                   seg->align = 1;
-                   break;
-               }
-           } else if (!nasm_strnicmp(p, "absolute=", 9)) {
-               seg->align = SEG_ABS + readnum(p+9, &rn_error);
-               if (rn_error)
-                   error (ERR_NONFATAL, "argument to `absolute' segment"
-                          " attribute should be numeric");
-           }
-       }
-
-       ieee_seg_needs_update = seg;
-       if (seg->align >= SEG_ABS)
-           deflabel (name, NO_SEG, seg->align - SEG_ABS, 
-                       NULL, FALSE, FALSE, &of_ieee, error);
-       else
-           deflabel (name, seg->index+1, 0L, 
-                       NULL, FALSE, FALSE, &of_ieee, error);
-       ieee_seg_needs_update = NULL;
-
-       if (seg->use32)
-           *bits = 32;
-       else
-           *bits = 16;
-       return seg->index;
-    }
-}
-/*
- * directives supported
- */
-static int ieee_directive (char *directive, char *value, int pass) 
-{
-    
-    (void) value;
-    (void) pass;
-    if (!strcmp(directive, "uppercase")) {
-       ieee_uppercase = TRUE;
-       return 1;
-    }
-    return 0;
-}
-/*
- * Return segment data
- */
-static long ieee_segbase (long segment) 
-{
-    struct ieeeSection *seg;
-
-    /*
-     * Find the segment in our list.
-     */
-    for (seg = seghead; seg; seg = seg->next)
-       if (seg->index == segment-1)
-           break;
-
-    if (!seg)
-       return segment;                /* not one of ours - leave it alone */
-
-    if (seg->align >= SEG_ABS)
-       return seg->align;             /* absolute segment */
-
-    return segment;                   /* no special treatment */
-}
-/*
- * filename
- */
-static void ieee_filename (char *inname, char *outname, efunc error) {
-    strcpy(ieee_infile, inname);
-    standard_extension (inname, outname, ".o", error);
-}
-
-static void ieee_write_file (int debuginfo) {
-    struct tm *thetime;
-    time_t reltime;
-    struct FileName *fn;
-    struct ieeeSection *seg;
-    struct ieeePublic *pub, *loc;
-    struct ieeeExternal *ext;
-    struct ieeeObjData *data;
-    struct ieeeFixupp *fix;
-    struct Array *arr;
-    static char boast[] = "The Netwide Assembler " NASM_VER;
-    int i;
-
-    /*
-     * Write the module header
-     */
-    ieee_putascii("MBFNASM,%02X%s.\r\n",strlen(ieee_infile),ieee_infile);
-
-    /*
-     * Write the NASM boast comment.
-     */
-    ieee_putascii("CO0,%02X%s.\r\n",strlen(boast),boast);
-
-    /* 
-     * write processor-specific information
-     */
-    ieee_putascii("AD8,4,L.\r\n");
-
-    /*
-     * date and time
-     */
-    time(&reltime);
-    thetime = localtime(&reltime);
-    ieee_putascii("DT%04d%02d%02d%02d%02d%02d.\r\n", 
-                       1900+thetime->tm_year,thetime->tm_mon+1,thetime->tm_mday,
-                       thetime->tm_hour, thetime->tm_min, thetime->tm_sec);
-    /* 
-     * if debugging, dump file names
-     */
-    for (fn = fnhead; fn && debuginfo; fn = fn->next) {
-       ieee_putascii("C0105,%02X%s.\r\n",strlen(fn->name),fn->name);
-    }
-     
-    ieee_putascii("CO101,07ENDHEAD.\r\n");
-    /*
-     * the standard doesn't specify when to put checksums,
-     * we'll just do it periodically.
-     */
-    ieee_putcs(FALSE);
-
-    /* 
-     * Write the section headers
-     */
-    seg = seghead;
-    if (!debuginfo && !strcmp(seg->name,"??LINE"))
-       seg = seg->next;
-    while (seg) {
-       char buf[256];
-       char attrib;
-       switch(seg->combine) {
-           case CMB_PUBLIC:
-           default:
-               attrib = 'C';
-               break;
-           case CMB_PRIVATE:
-               attrib = 'S';
-               break;
-           case CMB_COMMON:
-               attrib = 'M';
-               break;
-       }
-       ieee_unqualified_name(buf,seg->name);
-       if (seg->align >= SEG_ABS) {
-           ieee_putascii("ST%X,A,%02X%s.\r\n",seg->ieee_index,strlen(buf), buf);
-           ieee_putascii("ASL%X,%lX.\r\n",seg->ieee_index, (seg->align - SEG_ABS)*16);
-       }
-       else {
-           ieee_putascii("ST%X,%c,%02X%s.\r\n",seg->ieee_index,attrib,strlen(buf), buf);
-           ieee_putascii("SA%X,%lX.\r\n",seg->ieee_index,seg->align);
-           ieee_putascii("ASS%X,%X.\r\n",seg->ieee_index, seg->currentpos);
-       }
-       seg = seg->next;
-    }
-    /*
-     * write the start address if there is one
-     */
-    if (ieee_entry_seg) {
-        for (seg = seghead; seg; seg = seg->next)
-           if (seg->index == ieee_entry_seg)
-               break;
-       if (!seg)
-           error(ERR_PANIC,"Start address records are incorrect");
-       else 
-           ieee_putascii("ASG,R%X,%lX,+.\r\n",seg->ieee_index, ieee_entry_ofs);
-    }  
-
-
-    ieee_putcs(FALSE);
-    /*
-     * Write the publics
-     */
-    i = 1;
-    for (seg = seghead; seg; seg = seg->next) {
-        for (pub = seg->pubhead; pub; pub = pub->next) {
-           char buf[256];
-           ieee_unqualified_name(buf,pub->name);
-                   ieee_putascii("NI%X,%02X%s.\r\n",i, strlen(buf), buf);
-           if (pub->segment == -1)  
-                       ieee_putascii("ASI%X,R%X,%lX,+.\r\n", i, pub->index,pub->offset);
-           else
-                       ieee_putascii("ASI%X,%lX,%lX,+.\r\n", i, pub->segment*16,pub->offset);
-           if (debuginfo) {
-               if (pub->type >= 0x100)
-                   ieee_putascii("ATI%X,T%X.\r\n", i, pub->type - 0x100);
-               else
-                   ieee_putascii("ATI%X,%X.\r\n", i, pub->type);
-           }   
-           i++;
-        }
-    }
-    pub = fpubhead;
-    i = 1;
-    while (pub) {
-       char buf[256];
-       ieee_unqualified_name(buf,pub->name);
-               ieee_putascii("NI%X,%02X%s.\r\n",i, strlen(buf), buf);
-       if (pub->segment == -1)  
-                   ieee_putascii("ASI%X,R%X,%lX,+.\r\n", i, pub->index,pub->offset);
-       else
-                   ieee_putascii("ASI%X,%lX,%lX,+.\r\n", i, pub->segment*16,pub->offset);
-       if (debuginfo) {
-           if (pub->type >= 0x100)
-               ieee_putascii("ATI%X,T%X.\r\n", i, pub->type - 0x100);
-           else
-               ieee_putascii("ATI%X,%X.\r\n", i, pub->type);
-       }
-       i++;
-        pub = pub->next;
-    }
-    /*
-     * Write the externals
-     */
-    ext = exthead;
-    i = 1;
-    while (ext) {
-       char buf[256];
-       ieee_unqualified_name(buf,ext->name);
-               ieee_putascii("NX%X,%02X%s.\r\n",i++, strlen(buf), buf);
-        ext = ext->next;
-    }
-    ieee_putcs(FALSE);
-
-    /*
-     * IEEE doesn't have a standard pass break record
-     * so use the ladsoft variant
-     */
-    ieee_putascii("CO100,06ENDSYM.\r\n");
-
-    /*
-     * now put types
-     */
-    i = ARRAY_BOT;
-    for (arr = arrhead; arr && debuginfo; arr = arr->next) {
-       ieee_putascii("TY%X,20,%X,%lX.\r\n",i++,arr->basetype,arr->size);
-    }
-    /*
-     * now put locals
-     */
-    i = 1;
-    for (seg = seghead; seg && debuginfo; seg = seg->next) {
-        for (loc = seg->lochead; loc; loc = loc->next) {
-           char buf[256];
-           ieee_unqualified_name(buf,loc->name);
-                   ieee_putascii("NN%X,%02X%s.\r\n",i, strlen(buf), buf);
-           if (loc->segment == -1)  
-                       ieee_putascii("ASN%X,R%X,%lX,+.\r\n", i, loc->index,loc->offset);
-           else
-                       ieee_putascii("ASN%X,%lX,%lX,+.\r\n", i, loc->segment*16,loc->offset);
-           if (debuginfo) {
-               if (loc->type >= 0x100)
-                   ieee_putascii("ATN%X,T%X.\r\n", i, loc->type - 0x100);
-               else
-                   ieee_putascii("ATN%X,%X.\r\n", i, loc->type);
-           }
-           i++;
-        }
-    }
-
-    /*
-     *  put out section data;
-     */ 
-    seg = seghead;
-    if (!debuginfo && !strcmp(seg->name,"??LINE"))
-       seg = seg->next;
-    while (seg) {
-       if (seg->currentpos) {
-           long size,org = 0;
-           data = seg->data;
-           ieee_putascii("SB%X.\r\n",seg->ieee_index);
-           fix = seg->fptr;
-           while (fix) {
-               size = HUNKSIZE - (org %HUNKSIZE);
-               size = size +org > seg->currentpos ? seg->currentpos-org : size;
-               size = fix->offset - org > size ? size : fix->offset-org;
-               org = ieee_putld(org,org+size,data->data);
-               if (org % HUNKSIZE == 0)
-                   data = data->next;
-               if (org == fix->offset) {
-                   org += ieee_putlr(fix);
-                   fix = fix->next;
-               }
-           }
-           while (org < seg->currentpos && data) {
-               size = seg->currentpos-org > HUNKSIZE ? HUNKSIZE : seg->currentpos - org;
-               org = ieee_putld(org,org+size,data->data);
-               data = data->next;
-           }
-           ieee_putcs(FALSE);
-               
-       }
-       seg = seg->next;
-    }
-    /*
-     * module end record
-     */
-    ieee_putascii("ME.\r\n");
-}
-
-static void ieee_write_byte(struct ieeeSection *seg, int data) {
-    int temp;
-    if (!(temp = seg->currentpos++ % HUNKSIZE))
-       ieee_data_new(seg);
-    seg->datacurr->data[temp] = data;
-}
-
-static void ieee_write_word(struct ieeeSection *seg, int data) {
-    ieee_write_byte(seg, data & 0xFF);
-    ieee_write_byte(seg,(data >> 8) & 0xFF);
-}
-
-static void ieee_write_dword(struct ieeeSection *seg, long data) {
-    ieee_write_byte(seg, data & 0xFF);
-    ieee_write_byte(seg,(data >> 8) & 0xFF);
-    ieee_write_byte(seg,(data >> 16) & 0xFF);
-    ieee_write_byte(seg,(data >> 24) & 0xFF);
-}
-static void ieee_putascii(char *format, ...)
-{
-       char buffer[256];
-       int i,l;
-       va_list ap;
-
-       va_start(ap, format);
-       vsprintf(buffer, format, ap);
-       l = strlen(buffer);
-       for (i=0; i < l; i++)
-               if ((buffer[i] & 0xff) > 31)
-                       checksum+=buffer[i];
-       va_end(ap);
-       fprintf(ofp,buffer);
-}
-
-/*
- * put out a checksum record */
-static void ieee_putcs(int toclear)
-{
-       if (toclear) {
-               ieee_putascii("CS.\r\n");
-       }
-       else {
-               checksum += 'C';
-               checksum += 'S';
-               ieee_putascii("CS%02X.\r\n",checksum & 127);
-       }
-       checksum = 0;
-}
-
-static long ieee_putld(long start, long end, unsigned char *buf)
-{
-       long val;
-       if (start == end)
-               return(start);
-       val = start % HUNKSIZE;
-       /* fill up multiple lines */
-       while (end - start >= LDPERLINE) {
-               int i;
-               ieee_putascii("LD");
-               for (i=0; i < LDPERLINE; i++) {
-                       ieee_putascii("%02X",buf[val++]);
-                       start++;
-               }
-               ieee_putascii(".\r\n");
-       }
-       /* if no partial lines */
-       if (start == end)
-               return(start);
-       /* make a partial line */
-       ieee_putascii("LD");
-       while (start < end) {
-               ieee_putascii("%02X",buf[val++]);
-               start++;
-       }
-       ieee_putascii(".\r\n");
-       return(start);
-}
-static long ieee_putlr(struct ieeeFixupp *p)
-{
-/*
- * To deal with the vagaries of segmentation the LADsoft linker
- * defines two types of segments: absolute and virtual.  Note that
- * 'absolute' in this context is a different thing from the IEEE
- * definition of an absolute segment type, which is also supported. If a
- * sement is linked in virtual mode the low limit (L-var) is
- * subtracted from each R,X, and P variable which appears in an
- * expression, so that we can have relative offsets.  Meanwhile
- * in the ABSOLUTE mode this subtraction is not done and
- * so we can use absolute offsets from 0.  In the LADsoft linker
- * this configuration is not done in the assemblker source but in
- * a source the linker reads.  Generally this type of thing only
- * becomes an issue if real mode code is used.  A pure 32-bit linker could
- * get away without defining the virtual mode...
- */
-       char buf[40];
-       long size=p->size;
-       switch(p->ftype) {
-           case FT_SEG:
-               if (p->id1 < 0)
-                   sprintf(buf,"%lX",-p->id1);
-               else
-                   sprintf(buf,"L%lX,10,/",p->id1);
-               break;
-           case FT_OFS:
-               sprintf(buf,"R%lX,%lX,+",p->id1,p->addend);
-               break;
-           case FT_REL:
-               sprintf(buf,"R%lX,%lX,+,P,-,%X,-",p->id1,p->addend,p->size);
-               break;
-               
-           case FT_WRT:
-               if (p->id2 < 0)
-                   sprintf(buf,"R%lX,%lX,+,L%lX,+,%lX,-",p->id2,p->addend,p->id2,-p->id1*16);
-               else
-                   sprintf(buf,"R%lX,%lX,+,L%lX,+,L%lX,-",p->id2,p->addend,p->id2,p->id1);
-               break;
-           case FT_EXT:
-               sprintf(buf,"X%lX",p->id1);
-               break;
-           case FT_EXTREL:
-               sprintf(buf,"X%lX,P,-,%lX,-",p->id1,size);
-               break;
-           case FT_EXTSEG:
-               /* We needed a non-ieee hack here.
-                * We introduce the Y variable, which is the low
-                * limit of the native segment the extern resides in
-                */
-               sprintf(buf,"Y%lX,10,/",p->id1);
-               break;
-           case FT_EXTWRT:
-               if (p->id2 < 0)
-                   sprintf(buf,"X%lX,Y%lX,+,%lX,-",p->id2,p->id2,-p->id1*16);
-               else
-                   sprintf(buf,"X%lX,Y%lX,+,L%lX,-",p->id2,p->id2,p->id1);
-               break;
-       }
-       ieee_putascii("LR(%s,%lX).\r\n", buf, size);
-
-       return(size);
-}
-/* Dump all segment data (text and fixups )*/
-
-static void ieee_unqualified_name(char *dest, char *source)
-{
-    if (ieee_uppercase) {
-       while (*source)
-           *dest++ = toupper(*source++);
-        *dest = 0;
-    }
-    else strcpy(dest,source);
-}
-void dbgls_init(struct ofmt * of, void * id, FILE * fp, efunc error)
-{
-    int tempint;
-    (void) of;
-    (void) id;
-    (void) fp;
-    (void) error;
-
-    fnhead = NULL;
-    fntail = &fnhead;
-    arrindex = ARRAY_BOT ;
-    arrhead = NULL;
-    arrtail = &arrhead;
-    ieee_segment("??LINE", 2, &tempint);
-    any_segs = FALSE;
-}
-static void dbgls_cleanup(void)
-{
-    struct ieeeSection *segtmp;
-    while (fnhead) {
-       struct FileName *fntemp = fnhead;
-       fnhead = fnhead->next;
-       nasm_free (fntemp->name);
-       nasm_free (fntemp);
-    }
-    for (segtmp = seghead; segtmp; segtmp = segtmp->next) {
-       while (segtmp->lochead) {
-           struct ieeePublic *loctmp = segtmp->lochead;
-           segtmp->lochead = loctmp->next;
-           nasm_free (loctmp->name);
-           nasm_free (loctmp);
-       }
-    }
-    while (arrhead) {
-       struct Array *arrtmp = arrhead;
-        arrhead = arrhead->next;
-        nasm_free (arrtmp);
-    }
-}
-
-/*
- * because this routine is not bracketed in
- * the main program, this routine will be called even if there
- * is no request for debug info
- * so, we have to make sure the ??LINE segment is avaialbe
- * as the first segment when this debug format is selected
- */
-static void dbgls_linnum (const char *lnfname, long lineno, long segto)
-{
-    struct FileName *fn;
-    struct ieeeSection *seg;
-    int i = 0;
-    if (segto == NO_SEG)
-       return;
-
-    /*
-     * If `any_segs' is still FALSE, we must define a default
-     * segment.
-     */
-    if (!any_segs) {
-       int tempint;                   /* ignored */
-       if (segto != ieee_segment("__NASMDEFSEG", 2, &tempint))
-           error (ERR_PANIC, "strange segment conditions in OBJ driver");
-    }
-
-    /*
-     * Find the segment we are targetting.
-     */
-    for (seg = seghead; seg; seg = seg->next)
-       if (seg->index == segto)
-           break;
-    if (!seg)
-       error (ERR_PANIC, "lineno directed to nonexistent segment?");
-
-    for (fn = fnhead; fn; fn = fnhead->next) {
-       if (!nasm_stricmp(lnfname,fn->name))
-           break;
-        i++;
-    }
-    if (!fn) {
-       fn = nasm_malloc ( sizeof( *fn));
-       fn->name = nasm_malloc ( strlen(lnfname) + 1) ;
-       fn->index = i;
-        strcpy (fn->name,lnfname);
-       fn->next = NULL;
-       *fntail = fn;
-       fntail = &fn->next;
-    }
-    ieee_write_byte(seghead, fn->index);
-    ieee_write_word(seghead, lineno);
-    ieee_write_fixup (segto, NO_SEG, seghead, 4, OUT_ADDRESS, seg->currentpos);
-
-}
-static void dbgls_deflabel (char *name, long segment,
-                         long offset, int is_global, char *special) 
-{
-    struct ieeeSection *seg;
-    int used_special;          /* have we used the special text? */
-
-    /* Keep compiler from warning about special and used_special */
-    used_special = special ? FALSE : FALSE;
-
-    /*
-     * If it's a special-retry from pass two, discard it.
-     */
-    if (is_global == 3)
-       return;
-
-    /*
-     * First check for the double-period, signifying something
-     * unusual.
-     */
-    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
-       return;
-    }
-
-    /*
-     * Case (i):
-     */
-    if (ieee_seg_needs_update)
-       return;
-    if (segment < SEG_ABS && segment != NO_SEG && segment % 2)
-       return;
-
-    if (segment >= SEG_ABS || segment == NO_SEG) {
-       return;
-    }
-
-    /*
-     * If `any_segs' is still FALSE, we might need to define a
-     * default segment, if they're trying to declare a label in
-     * `first_seg'.  But the label should exist due to a prior
-     * call to ieee_deflabel so we can skip that.
-     */
-
-    for (seg = seghead; seg; seg = seg->next)
-       if (seg->index == segment) {
-           struct ieeePublic *loc;
-           /*
-            * Case (ii). Maybe MODPUB someday?
-            */
-           if (!is_global) {
-               last_defined = loc  = nasm_malloc (sizeof(*loc));
-               *seg->loctail = loc;
-               seg->loctail = &loc->next;
-               loc->next = NULL;
-               loc->name = nasm_strdup(name);
-               loc->offset = offset;
-               loc->segment = -1;
-               loc->index = seg->ieee_index;
-           }
-       }
-}
-static void dbgls_typevalue (long type)
-{
-    int elem = TYM_ELEMENTS(type);
-    type = TYM_TYPE(type);
-
-    if (! last_defined)
-       return;
-
-    switch (type) {
-       case TY_BYTE:
-           last_defined->type = 1; /* unsigned char */
-           break;
-       case TY_WORD:
-           last_defined->type = 3; /* unsigned word */
-           break;
-       case TY_DWORD:
-           last_defined->type = 5; /* unsigned dword */
-           break;
-       case TY_FLOAT:
-           last_defined->type = 9; /* float */
-           break;
-       case TY_QWORD:
-           last_defined->type = 10; /* qword */
-           break;
-       case TY_TBYTE:
-           last_defined->type = 11; /* TBYTE */
-           break;
-       default:
-           last_defined->type = 0x10; /* near label */
-           break;
-    }
-               
-    if (elem > 1) {
-        struct Array *arrtmp = nasm_malloc (sizeof(*arrtmp));
-        int vtype = last_defined->type;
-        arrtmp->size = elem;
-        arrtmp->basetype = vtype;
-        arrtmp->next = NULL;
-        last_defined->type = arrindex++ + 0x100;
-        *arrtail = arrtmp;
-        arrtail = & (arrtmp->next);
-    }
-    last_defined = NULL;
-}
-static void dbgls_output (int output_type, void *param)
-{
-    (void) output_type;
-    (void) param;
-}
-static struct dfmt ladsoft_debug_form = {
-    "LADsoft Debug Records",
-    "ladsoft",
-    dbgls_init,
-    dbgls_linnum,
-    dbgls_deflabel,
-    null_debug_routine,
-    dbgls_typevalue,
-    dbgls_output,
-    dbgls_cleanup,
-};
-static struct dfmt *ladsoft_debug_arr[3] = {
-       &ladsoft_debug_form,
-       &null_debug_form,
-       NULL
-};
-struct ofmt of_ieee = {
-    "IEEE-695 (LADsoft variant) object file format",
-    "ieee",
-    NULL,
-    ladsoft_debug_arr,
-    &null_debug_form,
-    NULL,
-    ieee_init,
-    ieee_set_info,
-    ieee_out,
-    ieee_deflabel,
-    ieee_segment,
-    ieee_segbase,
-    ieee_directive,
-    ieee_filename,
-    ieee_cleanup
-};
-
-#endif /* OF_IEEE */