NASM 0.98.12
authorH. Peter Anvin <hpa@zytor.com>
Tue, 30 Apr 2002 21:02:01 +0000 (21:02 +0000)
committerH. Peter Anvin <hpa@zytor.com>
Tue, 30 Apr 2002 21:02:01 +0000 (21:02 +0000)
12 files changed:
assemble.c
insns.dat
macros.c
macros.pl
misc/exasm.zip
nasm.c
nasm.h
parser.c
preproc.c
rdoff/Makefile.in
rdoff/ldrdf.c
test/bintest.asm

index 39ffd46..f93457d 100644 (file)
@@ -59,7 +59,8 @@
  *                as a literal byte in order to aid the disassembler.
  * \340          - reserve <operand 0> bytes of uninitialised storage.
  *                 Operand 0 had better be a segmentless constant.
- * \370,\371,\372 - match only if operand 0, 1, 2 meets byte jump criteria.
+ * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
+ *                370 is used for Jcc, 371 is used for JMP.
  * \373                 - assemble 0x03 if bits==16, 0x05 if bits==32;
  *                used for conditional jump over longer jump
  */
@@ -151,9 +152,11 @@ static int jmp_match (long segment, long offset, int bits,
     unsigned char c = code[0];
 
 
-    if (c != 0370) return 0;
-    if (ins->oprs[0].opflags & OPFLAG_FORWARD) return (!pass0);        /* match a forward reference */
-    
+    if (c != 0370 && c != 0371) return 0;
+    if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
+       if (optimizing<0 && c==0370) return 1;
+       else return (pass0==0); /* match a forward reference */
+    }
     isize = calcsize (segment, offset, bits, ins, code);
     if (ins->oprs[0].segment != segment) return 0;
     isize = ins->oprs[0].offset - offset - isize;      /* isize is now the delta */
@@ -546,7 +549,7 @@ static int is_sbyte (insn *ins, int op, int size)
     int ret;
     
     ret = !(ins->forw_ref && ins->oprs[op].opflags ) &&        /* dead in the water on forward reference or External */
-          (optimizing || !(ins->oprs[op].type & (BITS16|BITS32))) &&
+          (optimizing>0 || !(ins->oprs[op].type & (BITS16|BITS32))) &&
           ins->oprs[op].wrt==NO_SEG && ins->oprs[op].segment==NO_SEG;
 
     v = ins->oprs[op].offset;
index c34fa0e..d626fcd 100644 (file)
--- a/insns.dat
+++ b/insns.dat
@@ -37,15 +37,15 @@ ADC       rm16,imm8           \320\300\1\x83\202\15         8086
 ADC       rm32,imm8           \321\300\1\x83\202\15         386
 ADC       reg_al,imm          \1\x14\21                     8086,SM
 ADC       reg_ax,imm          \320\1\x15\31                 8086,SM
-ADC       reg_eax,sbyte       \321\1\x83\202\15             386,SM,ND
-ADC       reg_eax,sbig        \321\1\x15\41                 386,SM,ND
+ADC       reg_eax,sbyte       \321\1\x83\202\15                  386,SM,ND
+ADC       reg_eax,sbig        \321\1\x15\41                      386,SM,ND
 ADC       reg_eax,imm32       \321\1\x15\41                 386
 ADC       rm8,imm             \300\1\x80\202\21             8086,SM
-ADC       rm16,imm            \320\300\134\1\x81\202\131    8086,SM
-ADC       rm32,imm            \321\300\144\1\x81\202\141    386,SM
+ADC       rm16,imm            \320\300\134\1\x81\202\131         8086,SM
+ADC       rm32,imm            \321\300\144\1\x81\202\141         386,SM
 ADC       mem,imm8            \300\1\x80\202\21             8086,SM
-ADC       mem,imm16           \320\300\134\1\x81\202\131    8086,SM
-ADC       mem,imm32           \321\300\144\1\x81\202\141    386,SM
+ADC       mem,imm16           \320\300\134\1\x81\202\131         8086,SM
+ADC       mem,imm32           \321\300\144\1\x81\202\141         386,SM
 ADD       mem,reg8            \300\17\101                   8086,SM
 ADD       reg8,reg8           \300\17\101                   8086
 ADD       mem,reg16           \320\300\1\x01\101            8086,SM
@@ -62,15 +62,15 @@ ADD       rm16,imm8           \320\300\1\x83\200\15         8086
 ADD       rm32,imm8           \321\300\1\x83\200\15         386
 ADD       reg_al,imm          \1\x04\21                     8086,SM
 ADD       reg_ax,imm          \320\1\x05\31                 8086,SM
-ADD       reg_eax,sbyte       \321\1\x83\200\15             386,SM,ND
-ADD       reg_eax,sbig        \321\1\x05\41                 386,SM,ND
+ADD       reg_eax,sbyte       \321\1\x83\200\15                  386,SM,ND
+ADD       reg_eax,sbig        \321\1\x05\41                      386,SM,ND
 ADD       reg_eax,imm32       \321\1\x05\41                 386
 ADD       rm8,imm             \300\1\x80\200\21             8086,SM
-ADD       rm16,imm            \320\300\134\1\x81\200\131    8086,SM
-ADD       rm32,imm            \321\300\144\1\x81\200\141    386,SM
+ADD       rm16,imm            \320\300\134\1\x81\200\131         8086,SM
+ADD       rm32,imm            \321\300\144\1\x81\200\141         386,SM
 ADD       mem,imm8            \300\1\x80\200\21             8086,SM
-ADD       mem,imm16           \320\300\134\1\x81\200\131    8086,SM
-ADD       mem,imm32           \321\300\144\1\x81\200\141    386,SM
+ADD       mem,imm16           \320\300\134\1\x81\200\131         8086,SM
+ADD       mem,imm32           \321\300\144\1\x81\200\141         386,SM
 AND       mem,reg8            \300\1\x20\101                8086,SM
 AND       reg8,reg8           \300\1\x20\101                8086
 AND       mem,reg16           \320\300\1\x21\101            8086,SM
@@ -87,15 +87,15 @@ AND       rm16,imm8           \320\300\1\x83\204\15         8086
 AND       rm32,imm8           \321\300\1\x83\204\15         386
 AND       reg_al,imm          \1\x24\21                     8086,SM
 AND       reg_ax,imm          \320\1\x25\31                 8086,SM
-AND       reg_eax,sbyte       \321\1\x83\204\15             386,SM,ND
-AND       reg_eax,sbig        \321\1\x25\41                 386,SM,ND
+AND       reg_eax,sbyte       \321\1\x83\204\15                  386,SM,ND
+AND       reg_eax,sbig        \321\1\x25\41                      386,SM,ND
 AND       reg_eax,imm32       \321\1\x25\41                 386
 AND       rm8,imm             \300\1\x80\204\21             8086,SM
-AND       rm16,imm            \320\300\134\1\x81\204\131    8086,SM
-AND       rm32,imm            \321\300\144\1\x81\204\141    386,SM
+AND       rm16,imm            \320\300\134\1\x81\204\131         8086,SM
+AND       rm32,imm            \321\300\144\1\x81\204\141         386,SM
 AND       mem,imm8            \300\1\x80\204\21             8086,SM
-AND       mem,imm16           \320\300\134\1\x81\204\131    8086,SM
-AND       mem,imm32           \321\300\144\1\x81\204\141    386,SM
+AND       mem,imm16           \320\300\134\1\x81\204\131         8086,SM
+AND       mem,imm32           \321\300\144\1\x81\204\141         386,SM
 ARPL      mem,reg16           \300\1\x63\101                286,PROT,SM
 ARPL      reg16,reg16         \300\1\x63\101                286,PROT
 BOUND     reg16,mem           \320\301\1\x62\110            186
@@ -181,15 +181,15 @@ CMP       rm16,imm8           \320\300\1\x83\207\15         8086
 CMP       rm32,imm8           \321\300\1\x83\207\15         386
 CMP       reg_al,imm          \1\x3C\21                     8086,SM
 CMP       reg_ax,imm          \320\1\x3D\31                 8086,SM
-CMP       reg_eax,sbyte       \321\1\x83\207\15             386,SM,ND
-CMP       reg_eax,sbig        \321\1\x3D\41                 386,SM,ND
+CMP       reg_eax,sbyte       \321\1\x83\207\15                  386,SM,ND
+CMP       reg_eax,sbig        \321\1\x3D\41                      386,SM,ND
 CMP       reg_eax,imm32       \321\1\x3D\41                 386
 CMP       rm8,imm             \300\1\x80\207\21             8086,SM
-CMP       rm16,imm            \320\300\134\1\x81\207\131    8086,SM
-CMP       rm32,imm            \321\300\144\1\x81\207\141    386,SM
+CMP       rm16,imm            \320\300\134\1\x81\207\131         8086,SM
+CMP       rm32,imm            \321\300\144\1\x81\207\141         386,SM
 CMP       mem,imm8            \300\1\x80\207\21             8086,SM
-CMP       mem,imm16           \320\300\134\1\x81\207\131    8086,SM
-CMP       mem,imm32           \321\300\144\1\x81\207\141    386,SM
+CMP       mem,imm16           \320\300\134\1\x81\207\131         8086,SM
+CMP       mem,imm32           \321\300\144\1\x81\207\141         386,SM
 CMPSB     void                \332\1\xA6                    8086
 CMPSD     void                \332\321\1\xA7                386
 CMPSW     void                \332\320\1\xA7                8086
@@ -427,29 +427,29 @@ IMUL      reg16,reg16         \320\2\x0F\xAF\110            386
 IMUL      reg32,mem           \321\301\2\x0F\xAF\110        386,SM
 IMUL      reg32,reg32         \321\2\x0F\xAF\110            386
 IMUL      reg16,mem,imm8      \320\301\1\x6B\110\16         186,SM
-IMUL      reg16,mem,sbyte     \320\301\1\x6B\110\16         186,SM,ND
-IMUL      reg16,mem,imm16     \320\301\1\x69\110\32         186,SM
-IMUL      reg16,mem,imm       \320\301\135\1\x69\110\132    186,SM,ND
+IMUL      reg16,mem,sbyte     \320\301\1\x6B\110\16              186,SM,ND
+IMUL      reg16,mem,imm16     \320\301\1\x69\110\32              186,SM
+IMUL      reg16,mem,imm       \320\301\135\1\x69\110\132         186,SM,ND
 IMUL      reg16,reg16,imm8    \320\1\x6B\110\16             186
-IMUL      reg16,reg16,sbyte   \320\1\x6B\110\16             186,SM,ND
-IMUL      reg16,reg16,imm16   \320\1\x69\110\32             186
-IMUL      reg16,reg16,imm     \320\135\1\x69\110\132        186,SM,ND
+IMUL      reg16,reg16,sbyte   \320\1\x6B\110\16                  186,SM,ND
+IMUL      reg16,reg16,imm16   \320\1\x69\110\32                  186
+IMUL      reg16,reg16,imm     \320\135\1\x69\110\132             186,SM,ND
 IMUL      reg32,mem,imm8      \321\301\1\x6B\110\16         386,SM
-IMUL      reg32,mem,sbyte     \321\301\1\x6B\110\16         386,SM,ND
-IMUL      reg32,mem,imm32     \321\301\1\x69\110\42         386,SM
-IMUL      reg32,mem,imm       \321\301\145\1\x69\110\142    386,SM,ND
+IMUL      reg32,mem,sbyte     \321\301\1\x6B\110\16              386,SM,ND
+IMUL      reg32,mem,imm32     \321\301\1\x69\110\42              386,SM
+IMUL      reg32,mem,imm       \321\301\145\1\x69\110\142         386,SM,ND
 IMUL      reg32,reg32,imm8    \321\1\x6B\110\16             386
-IMUL      reg32,reg32,sbyte   \321\1\x6B\110\16             386,SM,ND
-IMUL      reg32,reg32,imm32   \321\1\x69\110\42             386
-IMUL      reg32,reg32,imm     \321\145\1\x69\110\142        386,SM,ND
+IMUL      reg32,reg32,sbyte   \321\1\x6B\110\16                  386,SM,ND
+IMUL      reg32,reg32,imm32   \321\1\x69\110\42                  386
+IMUL      reg32,reg32,imm     \321\145\1\x69\110\142             386,SM,ND
 IMUL      reg16,imm8          \320\1\x6B\100\15             186
-IMUL      reg16,sbyte         \320\1\x6B\100\15             186,SM,ND
-IMUL      reg16,imm16         \320\1\x69\100\31             186
-IMUL      reg16,imm           \320\134\1\x69\100\131        186,SM,ND
+IMUL      reg16,sbyte         \320\1\x6B\100\15                  186,SM,ND
+IMUL      reg16,imm16         \320\1\x69\100\31                  186
+IMUL      reg16,imm           \320\134\1\x69\100\131             186,SM,ND
 IMUL      reg32,imm8          \321\1\x6B\100\15             386
-IMUL      reg32,sbyte         \321\1\x6B\100\15             386,SM,ND
-IMUL      reg32,imm32         \321\1\x69\100\41             386
-IMUL      reg32,imm           \321\144\1\x69\100\141        386,SM,ND
+IMUL      reg32,sbyte         \321\1\x6B\100\15                  386,SM,ND
+IMUL      reg32,imm32         \321\1\x69\100\41                  386
+IMUL      reg32,imm           \321\144\1\x69\100\141             386,SM,ND
 IN        reg_al,imm          \1\xE4\25                     8086,SB
 IN        reg_ax,imm          \320\1\xE5\25                 8086,SB
 IN        reg_eax,imm         \321\1\xE5\25                 386,SB
@@ -479,7 +479,7 @@ IRETW     void                \320\1\xCF                    8086
 JCXZ      imm                 \310\1\xE3\50                 8086
 JECXZ     imm                 \311\1\xE3\50                 386
 JMP       imm|short           \1\xEB\50                     8086
-JMP       imm                 \370\1\xEB\50                 8086,ND
+JMP       imm                 \371\1\xEB\50                     8086,ND
 JMP       imm                 \322\1\xE9\64                 8086
 JMP       imm|near            \322\1\xE9\64                 8086,ND
 JMP       imm|far             \322\1\xEA\34\37              8086,ND
@@ -558,9 +558,9 @@ LSS       reg32,mem           \321\301\2\x0F\xB2\110        386
 LTR       mem                 \300\1\x0F\17\203             286,PROT,PRIV
 LTR       mem16               \300\1\x0F\17\203             286,PROT,PRIV
 LTR       reg16               \300\1\x0F\17\203             286,PROT,PRIV
-MOV       mem,reg_cs          \300\1\x8C\201                8086,SM
-MOV       mem,reg_dess        \300\1\x8C\101                8086,SM
-MOV       mem,reg_fsgs        \300\1\x8C\101                386,SM
+MOV       mem,reg_cs          \300\1\x8C\201                   8086,SM
+MOV       mem,reg_dess        \300\1\x8C\101                           8086,SM
+MOV       mem,reg_fsgs        \300\1\x8C\101                           386,SM
 MOV       reg16,reg_cs        \320\300\1\x8C\201            8086
 MOV       reg16,reg_dess      \320\300\1\x8C\101            8086
 MOV       reg16,reg_fsgs      \320\300\1\x8C\101            386
@@ -653,15 +653,15 @@ OR        rm16,imm8           \320\300\1\x83\201\15         8086
 OR        rm32,imm8           \321\300\1\x83\201\15         386
 OR        reg_al,imm          \1\x0C\21                     8086,SM
 OR        reg_ax,imm          \320\1\x0D\31                 8086,SM
-OR        reg_eax,sbyte       \321\1\x83\201\15             386,SM,ND
-OR        reg_eax,sbig        \321\1\x0D\41                 386,SM,ND
+OR        reg_eax,sbyte       \321\1\x83\201\15                  386,SM,ND
+OR        reg_eax,sbig        \321\1\x0D\41                      386,SM,ND
 OR        reg_eax,imm32       \321\1\x0D\41                 386
 OR        rm8,imm             \300\1\x80\201\21             8086,SM
-OR        rm16,imm            \320\300\134\1\x81\201\131    8086,SM
-OR        rm32,imm            \321\300\144\1\x81\201\141    386,SM
+OR        rm16,imm            \320\300\134\1\x81\201\131         8086,SM
+OR        rm32,imm            \321\300\144\1\x81\201\141         386,SM
 OR        mem,imm8            \300\1\x80\201\21             8086,SM
-OR        mem,imm16           \320\300\134\1\x81\201\131    8086,SM
-OR        mem,imm32           \321\300\144\1\x81\201\141    386,SM
+OR        mem,imm16           \320\300\134\1\x81\201\131         8086,SM
+OR        mem,imm32           \321\300\144\1\x81\201\141         386,SM
 OUT       imm,reg_al          \1\xE6\24                     8086,SB
 OUT       imm,reg_ax          \320\1\xE7\24                 8086,SB
 OUT       imm,reg_eax         \321\1\xE7\24                 386,SB
@@ -946,15 +946,15 @@ SBB       rm16,imm8           \320\300\1\x83\203\15         8086
 SBB       rm32,imm8           \321\300\1\x83\203\15         8086
 SBB       reg_al,imm          \1\x1C\21                     8086,SM
 SBB       reg_ax,imm          \320\1\x1D\31                 8086,SM
-SBB       reg_eax,sbyte       \321\1\x83\203\15             386,SM,ND
-SBB       reg_eax,sbig        \321\1\x1D\41                 386,SM,ND
+SBB       reg_eax,sbyte       \321\1\x83\203\15                  386,SM,ND
+SBB       reg_eax,sbig        \321\1\x1D\41                      386,SM,ND
 SBB       reg_eax,imm32       \321\1\x1D\41                 386
 SBB       rm8,imm             \300\1\x80\203\21             8086,SM
-SBB       rm16,imm            \320\300\134\1\x81\203\131    8086,SM
-SBB       rm32,imm            \321\300\144\1\x81\203\141    386,SM
+SBB       rm16,imm            \320\300\134\1\x81\203\131         8086,SM
+SBB       rm32,imm            \321\300\144\1\x81\203\141         386,SM
 SBB       mem,imm8            \300\1\x80\203\21             8086,SM
-SBB       mem,imm16           \320\300\134\1\x81\203\131    8086,SM
-SBB       mem,imm32           \321\300\144\1\x81\203\141    386,SM
+SBB       mem,imm16           \320\300\134\1\x81\203\131         8086,SM
+SBB       mem,imm32           \321\300\144\1\x81\203\141         386,SM
 SCASB     void                \332\1\xAE                    8086
 SCASD     void                \332\321\1\xAF                386
 SCASW     void                \332\320\1\xAF                8086
@@ -1029,15 +1029,15 @@ SUB       rm16,imm8           \320\300\1\x83\205\15         8086
 SUB       rm32,imm8           \321\300\1\x83\205\15         386
 SUB       reg_al,imm          \1\x2C\21                     8086,SM
 SUB       reg_ax,imm          \320\1\x2D\31                 8086,SM
-SUB       reg_eax,sbyte       \321\1\x83\205\15             386,SM,ND
-SUB       reg_eax,sbig        \321\1\x2D\41                 386,SM,ND
+SUB       reg_eax,sbyte       \321\1\x83\205\15                  386,SM,ND
+SUB       reg_eax,sbig        \321\1\x2D\41                      386,SM,ND
 SUB       reg_eax,imm32       \321\1\x2D\41                 386
 SUB       rm8,imm             \300\1\x80\205\21             8086,SM
-SUB       rm16,imm            \320\300\134\1\x81\205\131    8086,SM
-SUB       rm32,imm            \321\300\144\1\x81\205\141    386,SM
+SUB       rm16,imm            \320\300\134\1\x81\205\131         8086,SM
+SUB       rm32,imm            \321\300\144\1\x81\205\141         386,SM
 SUB       mem,imm8            \300\1\x80\205\21             8086,SM
-SUB       mem,imm16           \320\300\134\1\x81\205\131    8086,SM
-SUB       mem,imm32           \321\300\144\1\x81\205\141    386,SM
+SUB       mem,imm16           \320\300\134\1\x81\205\131         8086,SM
+SUB       mem,imm32           \321\300\144\1\x81\205\141         386,SM
 SVDC      mem80,reg_sreg      \300\2\x0F\x78\101            486,CYRIX,SMM
 SVLDT     mem80               \300\2\x0F\x7A\200            486,CYRIX,SMM
 SVTS      mem80               \300\2\x0F\x7C\200            486,CYRIX,SMM
@@ -1132,15 +1132,15 @@ XOR       rm16,imm8           \320\300\1\x83\206\15         8086
 XOR       rm32,imm8           \321\300\1\x83\206\15         386
 XOR       reg_al,imm          \1\x34\21                     8086,SM
 XOR       reg_ax,imm          \320\1\x35\31                 8086,SM
-XOR       reg_eax,sbyte       \321\1\x83\206\15             386,SM,ND
-XOR       reg_eax,sbig        \321\1\x35\41                 386,SM,ND
+XOR       reg_eax,sbyte       \321\1\x83\206\15                  386,SM,ND
+XOR       reg_eax,sbig        \321\1\x35\41                      386,SM,ND
 XOR       reg_eax,imm32       \321\1\x35\41                 386
 XOR       rm8,imm             \300\1\x80\206\21             8086,SM
-XOR       rm16,imm            \320\300\134\1\x81\206\131    8086,SM
-XOR       rm32,imm            \321\300\144\1\x81\206\141    386,SM
+XOR       rm16,imm            \320\300\134\1\x81\206\131         8086,SM
+XOR       rm32,imm            \321\300\144\1\x81\206\141         386,SM
 XOR       mem,imm8            \300\1\x80\206\21             8086,SM
-XOR       mem,imm16           \320\300\134\1\x81\206\131    8086,SM
-XOR       mem,imm32           \321\300\144\1\x81\206\141    386,SM
+XOR       mem,imm16           \320\300\134\1\x81\206\131         8086,SM
+XOR       mem,imm32           \321\300\144\1\x81\206\141         386,SM
 CMOVcc    reg16,mem           \320\301\1\x0F\330\x40\110    P6,SM
 CMOVcc    reg16,reg16         \320\301\1\x0F\330\x40\110    P6
 CMOVcc    reg32,mem           \321\301\1\x0F\330\x40\110    P6,SM
index 38a7e0f..ed70a75 100644 (file)
--- a/macros.c
+++ b/macros.c
@@ -1,12 +1,6 @@
 /* This file auto-generated from standard.mac by macros.pl - don't edit it */
 
 static char *stdmac[] = {
-    "%idefine IDEAL",
-    "%idefine JUMPS",
-    "%idefine P386",
-    "%idefine P486",
-    "%idefine P586",
-    "%idefine END",
     "%define __NASM_MAJOR__ 0",
     "%define __NASM_MINOR__ 98",
     "%define __FILE__",
@@ -63,12 +57,6 @@ static char *stdmac[] = {
     "%imacro bits 1+.nolist",
     "[bits %1]",
     "%endmacro",
-    "%imacro use16 0.nolist",
-    "[bits 16]",
-    "%endmacro",
-    "%imacro use32 0.nolist",
-    "[bits 32]",
-    "%endmacro",
     "%imacro global 1-*.nolist",
     "%rep %0",
     "[global %1]",
@@ -81,9 +69,5 @@ static char *stdmac[] = {
     "%rotate 1",
     "%endrep",
     "%endmacro",
-    "%imacro cpu 1+.nolist",
-    "[cpu %1]",
-    "%endmacro",
     NULL
 };
-#define TASM_MACRO_COUNT 6
index ecf0595..1de90e7 100644 (file)
--- a/macros.pl
+++ b/macros.pl
@@ -7,7 +7,7 @@
 # redistributable under the licence given in the file "Licence"
 # distributed in the NASM archive.
 
-# use strict; # if your PERL's got it
+# use strict;
 
 my $fname;
 my $line = 0;
index e813018..b4e9e58 100644 (file)
Binary files a/misc/exasm.zip and b/misc/exasm.zip differ
diff --git a/nasm.c b/nasm.c
index c3575cd..20485d8 100644 (file)
--- a/nasm.c
+++ b/nasm.c
@@ -51,7 +51,7 @@ static struct ofmt *ofmt = NULL;
 static FILE *error_file;              /* Where to write error messages */
 
 static FILE *ofile = NULL;
-int optimizing = 0;            /* number of optimization passes to take */
+int optimizing = -1;           /* number of optimization passes to take */
 static int sb, cmd_sb = 16;                   /* by default */
 static unsigned long cmd_cpu = IF_PLEVEL;      /* highest level by default */
 static unsigned long cpu = IF_PLEVEL;          /* passed to insn_size & assemble.c */
@@ -386,11 +386,14 @@ static int process_arg (char *p, char *q)
                else
                    ofmt->current_dfmt = ofmt->debug_formats[0];
            } else if (p[1]=='O') {                 /* Optimization level */
+               int opt;
                if (!isdigit(*param)) report_error(ERR_FATAL,
                     "command line optimization level must be 0..3 or <nn>");
-               optimizing = atoi(param);
-               if (optimizing <= 0) optimizing = 0;
-               else if (optimizing <= 3) optimizing *= 5;  /* 5 passes for each level */
+               opt = atoi(param);
+               if (opt<=0) optimizing = -1;            /* 0.98 behaviour */
+               else if (opt==1) optimizing = 0;        /* Two passes, 0.98.09 behavior */
+               else if (opt<=3) optimizing = opt*5;    /* Multiple passes */
+               else optimizing = opt;                  /* Multiple passes */
            } else if (p[1]=='P' || p[1]=='p') {    /* pre-include */
                pp_pre_include (param);
            } else if (p[1]=='D' || p[1]=='d') {    /* pre-define */
@@ -754,8 +757,8 @@ static void assemble_file (char *fname)
       report_error(ERR_FATAL, "command line: "
                     "32-bit segment size requires a higher cpu");
 
-   pass_max = optimizing + 2;    /* passes 1, optimizing, then 2 */
-   pass0 = !optimizing;                /* start at 1 if not optimizing */
+   pass_max = (optimizing>0 ? optimizing : 0) + 2;    /* passes 1, optimizing, then 2 */
+   pass0 = !(optimizing>0);            /* start at 1 if not optimizing */
    for (pass = 1; pass <= pass_max  &&  pass0 <= 2; pass++) {
       int pass1, pass2;
       ldfunc def_label;
@@ -1027,11 +1030,11 @@ static void assemble_file (char *fname)
                            report_error, evaluate,
                            def_label);
 
-               if (!optimizing && pass == 2) {
+               if (!(optimizing>0) && pass == 2) {
                   if (forwref != NULL && globallineno == forwref->lineno) {
                      output_ins.forw_ref = TRUE;
                      do {
-                        output_ins.oprs[forwref->operand].opflags|= OPFLAG_FORWARD;
+                        output_ins.oprs[forwref->operand].opflags |= OPFLAG_FORWARD;
                         forwref = saa_rstruct (forwrefs);
                      } while (forwref != NULL && forwref->lineno == globallineno);
                   } else
@@ -1039,7 +1042,7 @@ static void assemble_file (char *fname)
                }
 
 
-               if (!optimizing && output_ins.forw_ref)
+               if (!(optimizing>0) && output_ins.forw_ref)
                {
                   if (pass == 1) {
                         for(i = 0; i < output_ins.operands; i++)
@@ -1251,13 +1254,13 @@ static void assemble_file (char *fname)
       if (pass>1 && !global_offset_changed) {
         pass0++;
         if (pass0==2) pass = pass_max - 1;
-      }        else if (!optimizing) pass0++;
+      }        else if (!(optimizing>0)) pass0++;
 
    } /* for (pass=1; pass<=2; pass++) */
 
    nasmlist.cleanup();
 #if 1
-   if (optimizing && using_debug_info) /*  -On and -g switches */
+   if (optimizing>0 && using_debug_info)       /*  -On and -g switches */
       fprintf(error_file,
                 "info:: assembly required 1+%d+1 passes\n", pass_cnt-2);
 #endif
@@ -1511,6 +1514,8 @@ static unsigned long get_cpu (char *value)
        !nasm_stricmp(value, "p2")    )         return IF_P6;
     if (!nasm_stricmp(value, "p3")    ||
        !nasm_stricmp(value, "katmai") )        return IF_KATMAI;
+    if (!nasm_stricmp(value, "p4")    ||       /* is this right? -- jrc */
+       !nasm_stricmp(value, "willamette") )    return IF_WILLAMETTE;
 
     report_error (pass0<2 ? ERR_NONFATAL : ERR_FATAL, "unknown 'cpu' type");
 
diff --git a/nasm.h b/nasm.h
index 55d8a8f..c463879 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.11"
+#define NASM_VER "0.98.12"
 
 #ifndef NULL
 #define NULL 0
index d802f05..c3c00fc 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -686,7 +686,7 @@ insn *parse_line (int pass, char *buffer, insn *result,
                if (is_simple(value)) {
                    if (reloc_value(value)==1)
                        result->oprs[operand].type |= UNITY;
-                   if (optimizing) {
+                   if (optimizing>0) {
                        if (reloc_value(value) >= -128 &&
                                 reloc_value(value) <= 127)
                            result->oprs[operand].type |= SBYTE;
index 488517b..a62fe85 100644 (file)
--- a/preproc.c
+++ b/preproc.c
@@ -917,7 +917,8 @@ delete_Token(Token * t)
 {
     Token *next = t->next;
     nasm_free(t->text);
-    t->next = freeTokens ? freeTokens->next : NULL;
+/*    t->next = freeTokens ? freeTokens->next : NULL; */
+    t->next = freeTokens;
     freeTokens = t;
     return next;
 }
index 38620d7..5ea14a0 100644 (file)
@@ -1,86 +1,84 @@
-***************
-*** 1,4 ****
-- # $Id$
-  #
-  # Auto-configuring Makefile for RDOFF object file utils; part of the
-  # Netwide Assembler
---- 1,4 ----
-+ # $Id$
-  #
-  # Auto-configuring Makefile for RDOFF object file utils; part of the
-  # Netwide Assembler
-***************
-*** 31,37 ****
-  .c.o:
-       $(CC) -c $(CFLAGS) $<
-  
-- all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
-  
-  rdfdump: rdfdump.o
-       $(CC) $(LDFLAGS) -o rdfdump rdfdump.o
---- 31,37 ----
-  .c.o:
-       $(CC) -c $(CFLAGS) $<
-  
-+ all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
-  
-  rdfdump: rdfdump.o
-       $(CC) $(LDFLAGS) -o rdfdump rdfdump.o
-***************
-*** 45,51 ****
-       $(CC) $(LDFLAGS) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o
-  rdf2com:
-       rm -f rdf2com && $(LN_S) rdf2bin rdf2com
-  
-  rdf2bin.o: rdf2bin.c
-  rdfdump.o: rdfdump.c
-  rdoff.o: rdoff.c rdoff.h
---- 45,54 ----
-       $(CC) $(LDFLAGS) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o
-  rdf2com:
-       rm -f rdf2com && $(LN_S) rdf2bin rdf2com
-+ rdf2ihx: rdf2ihx.o $(RDXLIBS) nasmlib.o
-+      $(CC) $(LDFLAGS) -o rdf2ihx rdf2ihx.o $(RDXLIBS) nasmlib.o
-  
-+ rdf2ihx.o: rdf2ihx.c
-  rdf2bin.o: rdf2bin.c
-  rdfdump.o: rdfdump.c
-  rdoff.o: rdoff.c rdoff.h
-***************
-*** 62,78 ****
-       $(CC) -c $(CFLAGS) $(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
---- 65,82 ----
-       $(CC) -c $(CFLAGS) $(top_srcdir)/nasmlib.c
-  
-  clean:
-+      rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
-  
-  spotless: clean
-       rm -f Makefile
-  
-  distclean: spotless
-  
-+ install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
-       $(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
-+      $(INSTALL_PROGRAM) rdf2ihx $(INSTALLROOT)$(bindir)/rdf2ihx
-       cd $(INSTALLROOT)$(bindir) && rm -f rdf2com && $(LN_S) rdf2bin rdf2com
+# $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     = @top_srcdir@
+srcdir         = @srcdir@
+VPATH          = @srcdir@
+prefix         = @prefix@
+exec_prefix    = @exec_prefix@
+bindir         = @bindir@
+mandir         = @mandir@
+
+CC             = @CC@
+CFLAGS         = @CFLAGS@ @GCCFLAGS@ -I$(srcdir) -I$(top_srcdir)
+LDFLAGS                = @LDFLAGS@
+
+INSTALL                = @INSTALL@
+INSTALL_PROGRAM        = @INSTALL_PROGRAM@
+INSTALL_DATA   = @INSTALL_DATA@
+LN_S           = @LN_S@
+
+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) $<
+
+all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
+
+rdfdump: rdfdump.o
+       $(CC) $(LDFLAGS) -o rdfdump rdfdump.o
+ldrdf: ldrdf.o $(LDRDFLIBS)
+       $(CC) $(LDFLAGS) -o ldrdf ldrdf.o $(LDRDFLIBS)
+rdx: rdx.o $(RDXLIBS)
+       $(CC) $(LDFLAGS) -o rdx rdx.o $(RDXLIBS)
+rdflib: rdflib.o
+       $(CC) $(LDFLAGS) -o rdflib rdflib.o
+rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
+       $(CC) $(LDFLAGS) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o
+rdf2com:
+       rm -f rdf2com && $(LN_S) rdf2bin rdf2com
+rdf2ihx: rdf2ihx.o $(RDXLIBS) nasmlib.o
+       $(CC) $(LDFLAGS) -o rdf2ihx rdf2ihx.o $(RDXLIBS) nasmlib.o
+
+rdf2ihx.o: rdf2ihx.c
+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) $(top_srcdir)/nasmlib.c
+       cd $(top_srcdir);make nasmlib.o
+       cp $(top_srcdir)/nasmlib.o $(srcdir)
+
+clean:
+       rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
+
+spotless: clean
+       rm -f Makefile
+
+distclean: spotless
+
+install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
+       $(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
+       $(INSTALL_PROGRAM) rdf2ihx $(INSTALLROOT)$(bindir)/rdf2ihx
+       cd $(INSTALLROOT)$(bindir) && rm -f rdf2com && $(LN_S) rdf2bin rdf2com
index d9aac2f..3d9d749 100644 (file)
-***************
-*** 29,42 ****
-  #include <stdlib.h>
-  #include <string.h>
-  
-  #include "rdoff.h"
-  #include "symtab.h"
-  #include "collectn.h"
-  #include "rdlib.h"
-  #include "segtab.h"
-- #include "multboot.h"
-  
-- #define LDRDF_VERSION "1.01 alpha 2"
-  
-  #define RDF_MAXSEGS 64
-  /* #define STINGY_MEMORY */
---- 29,42 ----
-  #include <stdlib.h>
-  #include <string.h>
-  
-+ #include "multboot.h"
-  #include "rdoff.h"
-  #include "symtab.h"
-  #include "collectn.h"
-  #include "rdlib.h"
-  #include "segtab.h"
-  
-+ #define LDRDF_VERSION "1.02"
-  
-  #define RDF_MAXSEGS 64
-  /* #define STINGY_MEMORY */
+/* ldrdf.c      RDOFF Object File linker/loader main program
+ *
+ * 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.
+ */
+
+/*
+ * TODO: actually get this new version working!
+ * - finish off write_output()       - appears to be done
+ * - implement library searching     - appears to be done
+ *   - maybe we only want to do one pass, for performance reasons?
+ *     this makes things a little harder, but unix 'ld' copes...
+ * - implement command line options  - appears to be done
+ * - improve symbol table implementation  - done, thanks to Graeme Defty
+ * - keep a cache of symbol names in each library module so
+ *   we don't have to constantly recheck the file
+ * - general performance improvements
+ *
+ * BUGS & LIMITATIONS: this program doesn't support multiple code, data
+ * or bss segments, therefore for 16 bit programs whose code, data or BSS
+ * segment exceeds 64K in size, it will not work. This program probably
+ * wont work if compiled by a 16 bit compiler. Try DJGPP if you're running
+ * under DOS. '#define STINGY_MEMORY' may help a little.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "multboot.h"
+#include "rdoff.h"
+#include "symtab.h"
+#include "collectn.h"
+#include "rdlib.h"
+#include "segtab.h"
+
+#define LDRDF_VERSION "1.02"
+
+#define RDF_MAXSEGS 64
+/* #define STINGY_MEMORY */
+
+/* =======================================================================
+ * Types & macros that are private to this program
+ */
+
+struct segment_infonode {
+    int                dest_seg;       /* output segment to be placed into, -1 to 
+                                  skip linking this segment */
+    long       reloc;          /* segment's relocation factor */
+};
+
+
+struct modulenode {
+    rdffile    f;              /* the RDOFF file structure */
+    struct segment_infonode seginfo[RDF_MAXSEGS]; /* what are we doing
+                                                    with each segment? */
+    void       * header;
+    char       * name;
+    struct modulenode * next;
+    long       bss_reloc;
+};
+
+#include "ldsegs.h"
+
+#define newstr(str) strcpy(malloc(strlen(str) + 1),str)
+#define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1)+strlen(s2)+1),s1),s2)
+
+/* ==========================================================================
+ * Function prototypes of private utility functions
+ */
+
+void processmodule(const char * filename, struct modulenode * mod);
+int allocnewseg(int16 type,int16 reserved);
+int findsegment(int16 type,int16 reserved);
+void symtab_add(const char * symbol, int segment, long offset);
+int symtab_get(const char * symbol, int * segment, long * offset);
+
+/* =========================================================================
+ * Global data structures.
+ */
+
+/* a linked list of modules that will be included in the output */
+struct modulenode      * modules = NULL;
+struct modulenode      * lastmodule = NULL;
+
+/* a linked list of libraries to be searched for unresolved imported symbols */
+struct librarynode     * libraries = NULL;
+struct librarynode     * lastlib = NULL;
+
+/* the symbol table */
+void                   * symtab = NULL;
+
+/* objects search path */
+char                   * objpath = NULL;
+
+/* libraries search path */
+char                   * libpath = NULL;
+
+/* error file */
+static FILE            * error_file;
+
+#ifdef _MULTBOOT_H
+
+/* loading address for multiboot header */
+unsigned               MBHloadAddr;
+
+/*
+ * Tiny code that moves RDF loader to its working memory region:
+ *     mov     esi,SOURCE_ADDR         ; BE xx xx xx xx
+ *     mov     edi,DEST_ADDR           ; BF xx xx xx xx
+ *     mov     esp,edi                 ; 89 FC
+ *     push    edi                     ; 57
+ *     mov     ecx,RDFLDR_LENGTH/4     ; B9 xx xx xx xx
+ *     cld                             ; FC
+ *     rep     movsd                   ; F3 A5
+ *     ret                             ; C3
+ */
+
+#define        RDFLDR_LENGTH   4096            /* Loader will be moved to unused */
+#define        RDFLDR_DESTLOC  0xBF000         /* video page                     */
+unsigned char RDFloaderMover[]={
+       0xBE, 0, 0, 0, 0, 0xBF, 0, 0xF0, 0xB, 0,
+       0x89, 0xFC, 0x57,
+       0xB9, 0, 4, 0, 0,
+       0xFC, 0xF3, 0xA5, 0xC3
+};
+               
+#endif
+
+/* the header of the output file, built up stage by stage */
+rdf_headerbuf          * newheader = NULL;
+
+/* The current state of segment allocation, including information about
+ * which output segment numbers have been allocated, and their types and
+ * amount of data which has already been allocated inside them. 
+ */
+struct SegmentHeaderRec        outputseg[RDF_MAXSEGS];
+int                    nsegs = 0;
+long                   bss_length;
+
+/* global options which affect how the program behaves */
+struct ldrdfoptions {
+    int                verbose;
+    int                align;
+    int                warnUnresolved;
+    int                errorUnresolved;
+    int                strip;
+    int         respfile;
+    int         stderr_redir;
+    int         objpath;
+    int         libpath;
+    int                addMBheader;
+} options;
+
+int errorcount = 0;    /* determines main program exit status */
+
+/* =========================================================================
+ * Utility functions
+ */
+
+
+/*
+ * initsegments()
+ *
+ * sets up segments 0, 1, and 2, the initial code data and bss segments
+ */
+
+void initsegments()
+{
+    nsegs = 3;
+    outputseg[0].type = 1;
+    outputseg[0].number = 0;
+    outputseg[0].reserved = 0;
+    outputseg[0].length = 0;
+    outputseg[1].type = 2;
+    outputseg[1].number = 1;
+    outputseg[1].reserved = 0;
+    outputseg[1].length = 0;
+    outputseg[2].type = 0xFFFF;        /* reserved segment type */
+    outputseg[2].number = 2;
+    outputseg[2].reserved = 0;
+    outputseg[2].length = 0;
+    bss_length = 0;
+}
+
+/*
+ * loadmodule
+ *
+ * Determine the characteristics of a module, and decide what to do with
+ * each segment it contains (including determining destination segments and
+ * relocation factors for segments that        are kept).
+ */
+
+void loadmodule(const char * filename)
+{
+    if (options.verbose)
+       printf("loading `%s'\n", filename);
+
+    /* allocate a new module entry on the end of the modules list */
+    if (!modules)
+    {
+       modules = malloc (sizeof(*modules));
+       lastmodule = modules;
+    }
+    else
+    {
+       lastmodule->next = malloc (sizeof(*modules));
+       lastmodule = lastmodule->next;
+    }
+
+    if ( ! lastmodule)
+    {
+       fprintf(stderr, "ldrdf: out of memory\n");
+       exit(1);
+    }
+
+    /* open the file using 'rdfopen', which returns nonzero on error */
+
+    if (rdfopen(&lastmodule->f, filename) != 0)
+    {
+       rdfperror("ldrdf", filename);
+       exit(1);
+    }
+
+    /* 
+     * store information about the module, and determine what segments
+     * it contains, and what we should do with them (determine relocation
+     * factor if we decide to keep them)
+     */
+
+    lastmodule->header = NULL;
+    lastmodule->name = strdup(filename);
+    lastmodule->next = NULL;
+
+    processmodule(filename, lastmodule);
+}
+       
+/*
+ * processmodule()
+ *
+ * step through each segment, determine what exactly we're doing with
+ * it, and if we intend to keep it, determine (a) which segment to
+ * put it in and (b) whereabouts in that segment it will end up.
+ * (b) is fairly easy, cos we're now keeping track of how big each segment
+ * in our output file is...
+ */
+
+void processmodule(const char * filename, struct modulenode * mod)
+{
+    struct segconfig sconf;
+    int                seg, outseg;
+    void       * header;
+    rdfheaderrec * hr;
+    long       bssamount = 0;
+
+    for (seg = 0; seg < mod->f.nsegs; seg++)
+    {
+       /*
+        * get the segment configuration for this type from the segment
+        * table. getsegconfig() is a macro, defined in ldsegs.h.
+        */
+       getsegconfig(sconf, mod->f.seg[seg].type);
+
+       if (options.verbose > 1) {
+           printf ("%s %04x [%04x:%10s] ", filename, mod->f.seg[seg].number, 
+                   mod->f.seg[seg].type, sconf.typedesc);
+       }
+       /*
+        * sconf->dowhat tells us what to do with a segment of this type.
+        */
+       switch (sconf.dowhat) {
+       case SEG_IGNORE:
+           /*
+            * Set destination segment to -1, to indicate that this segment
+            * should be ignored for the purpose of output, ie it is left
+            * out of the linked executable.
+            */
+           mod->seginfo[seg].dest_seg = -1;
+           if (options.verbose > 1) printf("IGNORED\n");
+           break;
+
+       case SEG_NEWSEG:
+           /*
+            * The configuration tells us to create a new segment for
+            * each occurrence of this segment type.
+            */
+           outseg = allocnewseg(sconf.mergetype,
+                                mod->f.seg[seg].reserved);
+           mod->seginfo[seg].dest_seg = outseg;
+           mod->seginfo[seg].reloc = 0;
+           outputseg[outseg].length = mod->f.seg[seg].length;
+           if (options.verbose > 1) 
+               printf ("=> %04x:%08lx (+%04lx)\n", outseg,
+                       mod->seginfo[seg].reloc,
+                       mod->f.seg[seg].length);
+           break;
+
+       case SEG_MERGE:
+           /*
+            * The configuration tells us to merge the segment with
+            * a previously existing segment of type 'sconf.mergetype',
+            * if one exists. Otherwise a new segment is created.
+            * This is handled transparently by 'findsegment()'.
+            */
+           outseg = findsegment(sconf.mergetype,
+                                mod->f.seg[seg].reserved);
+           mod->seginfo[seg].dest_seg = outseg;
+
+           /*
+            * We need to add alignment to these segments.
+            */
+           if (outputseg[outseg].length % options.align != 0)
+               outputseg[outseg].length += 
+                   options.align - (outputseg[outseg].length % options.align);
+           
+           mod->seginfo[seg].reloc = outputseg[outseg].length;
+           outputseg[outseg].length  += mod->f.seg[seg].length;
+
+           if (options.verbose > 1) 
+               printf ("=> %04x:%08lx (+%04lx)\n", outseg,
+                       mod->seginfo[seg].reloc,
+                       mod->f.seg[seg].length);
+       }
+
+    }
+
+    /*
+     * extract symbols from the header, and dump them into the
+     * symbol table
+     */
+    header = malloc(mod->f.header_len);
+    if (!header) {
+       fprintf(stderr, "ldrdf: not enough memory\n");
+       exit(1);
+    }
+    if (rdfloadseg(&mod->f, RDOFF_HEADER, header)) {
+       rdfperror("ldrdf", filename);
+       exit(1);
+    }
+
+    while ((hr = rdfgetheaderrec (&mod->f)))
+    {
+       switch(hr->type) {
+       case 2: /* imported symbol - define with seg = -1 */
+       case 7:
+           symtab_add(hr->i.label, -1, 0);
+           break;
+
+       case 3: /* exported symbol */
+           {
+            int destseg;
+            long destreloc;
+
+            if (hr->e.segment == 2)
+             {
+               destreloc = bss_length;
+               if (destreloc % options.align != 0)
+                  destreloc +=  options.align - (destreloc % options.align);
+               destseg = 2;
+             }
+            else
+             {
+               if ((destseg = mod->seginfo[(int)hr->e.segment].dest_seg) == -1)
+                  continue;
+               destreloc = mod->seginfo[(int)hr->e.segment].reloc;
+             }
+           symtab_add(hr->e.label, destseg, destreloc + hr->e.offset);
+           break;
+           }
+
+       case 5: /* BSS reservation */
+           /*
+            * first, amalgamate all BSS reservations in this module
+            * into one, because we allow this in the output format.
+            */
+           bssamount += hr->b.amount;
+           break;
+       }
+    }
+
+    if (bssamount != 0)
+    {
+       /*
+        * handle the BSS segment - first pad the existing bss length
+        * to the correct alignment, then store the length in bss_reloc
+        * for this module. Then add this module's BSS length onto
+        * bss_length.
+        */
+       if (bss_length % options.align != 0)
+           bss_length +=  options.align - (bss_length % options.align);
+    
+       mod->bss_reloc = bss_length;
+       if (options.verbose > 1) {
+           printf ("%s 0002 [            BSS] => 0002:%08lx (+%04lx)\n",
+                   filename, bss_length, bssamount);
+       }
+       bss_length += bssamount;
+    }
+
+#ifdef STINGY_MEMORY
+    /*
+     * we free the header buffer here, to save memory later.
+     * this isn't efficient, but probably halves the memory usage
+     * of this program...
+     */
+    mod->f.header_loc = NULL;
+    free(header);
+
+#endif
+
+}
+
+
+/*
+ * Look in list for module by its name.
+ */
+int lookformodule(const char *name)
+ {
+  struct modulenode *curr=modules;
+
+  while(curr) {
+   if (!strcmp(name,curr->name)) return 1;
+   curr = curr->next;
+  }
+  return 0;
+ }
+
+
+/*
+ * allocnewseg()
+ * findsegment()
+ *
+ * These functions manipulate the array of output segments, and are used
+ * by processmodule(). allocnewseg() allocates a segment in the array,
+ * initialising it to be empty. findsegment() first scans the array for
+ * a segment of the type requested, and if one isn't found allocates a
+ * new one.
+ */
+int allocnewseg(int16 type,int16 reserved)
+{
+    outputseg[nsegs].type = type;
+    outputseg[nsegs].number = nsegs;
+    outputseg[nsegs].reserved = reserved;
+    outputseg[nsegs].length = 0;
+    outputseg[nsegs].offset = 0;
+    outputseg[nsegs].data = NULL;
+
+    return nsegs++;
+}
+
+int findsegment(int16 type,int16 reserved)
+{
+    int i;
+
+    for (i = 0; i < nsegs; i++)
+       if (outputseg[i].type == type) return i;
+
+    return allocnewseg(type,reserved);
+}
+
+/*
+ * symtab_add()
+ *
+ * inserts a symbol into the global symbol table, which associates symbol
+ * names either with addresses, or a marker that the symbol hasn't been
+ * resolved yet, or possibly that the symbol has been defined as
+ * contained in a dynamic [load time/run time] linked library.
+ *
+ * segment = -1 => not yet defined
+ * segment = -2 => defined as dll symbol
+ *
+ * If the symbol is already defined, and the new segment >= 0, then
+ * if the original segment was < 0 the symbol is redefined, otherwise
+ * a duplicate symbol warning is issued. If new segment == -1, this
+ * routine won't change a previously existing symbol. It will change
+ * to segment = -2 only if the segment was previously < 0.
+ */
+
+void symtab_add(const char * symbol, int segment, long offset)
+{
+    symtabEnt * ste;
+
+    ste = symtabFind(symtab, symbol);
+    if (ste)
+    {
+       if (ste->segment >= 0) {
+           /*
+            * symbol previously defined
+            */
+           if (segment < 0) return;
+           fprintf (error_file, "warning: `%s' redefined\n", symbol);
+           return;
+       }
+
+       /*
+        * somebody wanted the symbol, and put an undefined symbol
+        * marker into the table
+        */
+       if (segment == -1) return;
+       /*
+        * we have more information now - update the symbol's entry
+        */
+       ste->segment = segment;
+       ste->offset = offset;
+       ste->flags = 0;
+       return;
+    }
+    /*
+     * this is the first declaration of this symbol
+     */
+    ste = malloc(sizeof(symtabEnt));
+    if (!ste) {
+       fprintf(stderr, "ldrdf: out of memory\n");
+       exit(1);
+    }
+    ste->name = strdup(symbol);
+    ste->segment = segment;
+    ste->offset = offset;
+    ste->flags = 0;
+    symtabInsert(symtab, ste);
+}
+
+/*
+ * symtab_get()
+ *
+ * Retrieves the values associated with a symbol. Undefined symbols
+ * are assumed to have -1:0 associated. Returns 1 if the symbol was
+ * successfully located.
+ */
+
+int symtab_get(const char * symbol, int * segment, long * offset)
+{
+    symtabEnt * ste = symtabFind(symtab, symbol);
+    if (!ste) {
+       *segment = -1;
+       *offset = 0;
+       return 0;
+    }
+    else
+    {
+       *segment = ste->segment;
+       *offset = ste->offset;
+       return 1;
+    }
+}
+
+/*
+ * add_library()
+ *
+ * checks that a library can be opened and is in the correct format,
+ * then adds it to the linked list of libraries.
+ */
+
+void add_library(const char * name)
+{
+    if (rdl_verify(name)) {
+       rdl_perror("ldrdf", name);
+       errorcount++;
+       return;
+    }
+    if (! libraries)
+    {
+       lastlib = libraries = malloc(sizeof(*libraries));
+       if (! libraries) {
+           fprintf(stderr, "ldrdf: out of memory\n");
+           exit(1);
+       }
+    }
+    else
+    {
+       lastlib->next = malloc(sizeof(*libraries));
+       if (!lastlib->next) {
+           fprintf(stderr, "ldrdf: out of memory\n");
+           exit(1);
+       }
+       lastlib = lastlib->next;
+    }
+    lastlib->next = NULL;
+    if (rdl_open(lastlib, name)) {
+       rdl_perror("ldrdf", name);
+       errorcount++;
+       return;
+    }
+}
+
+/*
+ * search_libraries()
+ *
+ * scans through the list of libraries, attempting to match symbols
+ * defined in library modules against symbols that are referenced but
+ * not defined (segment = -1 in the symbol table)
+ *
+ * returns 1 if any extra library modules are included, indicating that
+ * another pass through the library list should be made (possibly).
+ */
+
+int search_libraries()
+{
+    struct librarynode * cur;
+    rdffile f;
+    int     i;
+    void    * header;
+    int            segment;
+    long    offset;
+    int            doneanything = 0, pass = 1, keepfile;
+    rdfheaderrec * hr;
+
+    cur = libraries;
+
+    while (cur)
+    {
+       if (options.verbose > 2)
+           printf("scanning library `%s', pass %d...\n", cur->name, pass);
+       
+       for (i = 0; rdl_openmodule(cur, i, &f) == 0; i++)
+       {
+           if (pass == 2 && lookformodule(f.name)) continue;
+
+           if (options.verbose > 3)
+               printf("  looking in module `%s'\n", f.name);
+
+           header = malloc(f.header_len);
+           if (!header) {
+               fprintf(stderr, "ldrdf: not enough memory\n");
+               exit(1);
+           }
+           if (rdfloadseg(&f, RDOFF_HEADER, header)) {
+               rdfperror("ldrdf", f.name);
+               errorcount++;
+               return 0;
+           }
+           
+           keepfile = 0;
+
+           while ((hr = rdfgetheaderrec (&f)))
+           {
+                /* we're only interested in exports, so skip others: */
+               if (hr->type != 3) continue; 
+
+               /*
+                * Find the symbol in the symbol table. If the symbol isn't
+                * defined, we aren't interested, so go on to the next.
+                * If it is defined as anything but -1, we're also not
+                * interested. But if it is defined as -1, insert this
+                * module into the list of modules to use, and go
+                * immediately on to the next module...
+                */
+               if (! symtab_get(hr->e.label, &segment, &offset) 
+                   || segment != -1)
+               {
+                   continue;    
+               }
+               
+               doneanything = 1;
+               keepfile = 1;
+
+               /*
+                * as there are undefined symbols, we can assume that
+                * there are modules on the module list by the time
+                * we get here.
+                */
+               lastmodule->next = malloc(sizeof(*lastmodule->next));
+               if (!lastmodule->next) {
+                   fprintf(stderr, "ldrdf: not enough memory\n");
+                   exit(1);
+               }
+               lastmodule = lastmodule->next;
+               memcpy(&lastmodule->f, &f, sizeof(f));
+               lastmodule->name = strdup(f.name);
+                lastmodule->next = NULL;
+               processmodule(f.name, lastmodule);
+               break;
+           }
+           if (!keepfile)
+             {
+              free(f.name);
+              f.name = NULL;
+              f.fp = NULL;
+             }
+       }
+       if (rdl_error != 0 && rdl_error != RDL_ENOTFOUND)
+           rdl_perror("ldrdf", cur->name);
+
+       cur = cur->next;
+       if (cur == NULL && pass == 1) {
+           cur = libraries;
+           pass++;
+       }
+    }
+
+    return doneanything;
+}
+
+/*
+ * write_output()
+ *
+ * this takes the linked list of modules, and walks through it, merging
+ * all the modules into a single output module, and then writes this to a
+ * file.
+ */
+void write_output(const char * filename)
+{
+    FILE          * f;
+    rdf_headerbuf * rdfheader;
+    struct modulenode * cur;
+    int                  i, availableseg, seg, localseg, isrelative;
+    void         * header;
+    rdfheaderrec  * hr, newrec;
+    symtabEnt    * se;
+    segtab       segs;
+    long         offset;
+    byte         * data;
+
+    if ((f = fopen(filename, "wb"))==NULL) {
+       fprintf(stderr, "ldrdf: couldn't open %s for output\n", filename);
+       exit(1);
+    }
+    if ((rdfheader=rdfnewheader())==NULL) {
+       fprintf(stderr, "ldrdf: out of memory\n");
+       exit(1);
+    }
+    
+    /*
+     * Add multiboot header if appropriate option is specified.
+     * Multiboot record *MUST* be the first record in output file.
+     */
+    if (options.addMBheader) {
+       if (options.verbose)
+           puts("\nadding multiboot header record");
+    
+        hr = (rdfheaderrec *) malloc(sizeof(struct MultiBootHdrRec));
+        hr->mbh.type = 9;
+        hr->mbh.reclen = sizeof(struct tMultiBootHeader)+RDFLDRMOVER_SIZE;
+           
+        hr->mbh.mb.Magic = MB_MAGIC;
+        hr->mbh.mb.Flags = MB_FL_KLUDGE;
+       hr->mbh.mb.Checksum = ~(MB_MAGIC+MB_FL_KLUDGE-1);
+        hr->mbh.mb.HeaderAddr = MBHloadAddr+16;
+        hr->mbh.mb.LoadAddr = MBHloadAddr;
+       hr->mbh.mb.Entry = MBHloadAddr+16+sizeof(struct tMultiBootHeader);
+       
+       memcpy(hr->mbh.mover,RDFloaderMover,RDFLDRMOVER_SIZE);
+           
+        rdfaddheader(rdfheader,hr);
+        free(hr);
+    }
+
+    if (options.verbose)
+       printf ("\nbuilding output module (%d segments)\n", nsegs);
+
+    /*
+     * Allocate the memory for the segments. We may be better off
+     * building the output module one segment at a time when running
+     * under 16 bit DOS, but that would be a slower way of doing this.
+     * And you could always use DJGPP...
+     */
+    for (i = 0; i < nsegs; i++)
+    {
+       outputseg[i].data=NULL;
+       if(!outputseg[i].length) continue;
+       outputseg[i].data = malloc(outputseg[i].length);
+       if (!outputseg[i].data) {
+           fprintf(stderr, "ldrdf: out of memory\n");
+           exit(1);
+       }
+    }
+
+    /*
+     * initialise availableseg, used to allocate segment numbers for
+     * imported and exported labels...
+     */
+    availableseg = nsegs;
+
+    /*
+     * Step through the modules, performing required actions on each one
+     */
+    for (cur = modules; cur; cur=cur->next)
+    {
+       /*
+        * Read the actual segment contents into the correct places in
+        * the newly allocated segments
+        */
+
+       for (i = 0; i < cur->f.nsegs; i++)
+       {
+           int dest = cur->seginfo[i].dest_seg;
+
+           if (dest == -1) continue;
+           if (rdfloadseg(&cur->f, i, 
+                          outputseg[dest].data + cur->seginfo[i].reloc))
+           {
+               rdfperror("ldrdf", cur->name);
+               exit(1);
+           }
+       }
+       /*
+        * Perform fixups, and add new header records where required
+        */
+
+       header = malloc(cur->f.header_len);
+       if (!header) {
+           fprintf(stderr, "ldrdf: out of memory\n");
+           exit(1);
+       }
+
+       if (cur->f.header_loc)
+           rdfheaderrewind(&cur->f);
+       else
+           if (rdfloadseg(&cur->f, RDOFF_HEADER, header))
+           {
+               rdfperror("ldrdf", cur->name);
+               exit(1);
+           }
+       
+       /*
+        * we need to create a local segment number -> location
+        * table for the segments in this module.
+        */
+       init_seglocations(&segs);
+       for (i = 0; i < cur->f.nsegs; i++)
+       {
+           add_seglocation(&segs, cur->f.seg[i].number,
+                           cur->seginfo[i].dest_seg, cur->seginfo[i].reloc);
+       }
+       /*
+        * and the BSS segment (doh!)
+        */
+       add_seglocation (&segs, 2, 2, cur->bss_reloc);
+       
+       while ((hr = rdfgetheaderrec(&cur->f)))
+       {
+           switch(hr->type) {
+           case 1: /* relocation record - need to do a fixup */
+               /*
+                * First correct the offset stored in the segment from
+                * the start of the segment (which may well have changed).
+                *
+                * To do this we add to the number stored the relocation
+                * factor associated with the segment that contains the
+                * target segment.
+                *
+                * The relocation could be a relative relocation, in which
+                * case we have to first subtract the amount we've relocated
+                * the containing segment by.
+                */
+               
+               if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset))
+               {
+                   fprintf(stderr, "%s: reloc to undefined segment %04x\n",
+                           cur->name, (int) hr->r.refseg);
+                   errorcount++;
+                   break;
+               }
+
+               isrelative = (hr->r.segment & 64) == 64;
+               hr->r.segment &= 63;
+
+               if (hr->r.segment == 2 || 
+                   (localseg = rdffindsegment(&cur->f, hr->r.segment)) == -1)
+               {
+                   fprintf(stderr, "%s: reloc from %s segment (%d)\n", 
+                           cur->name,
+                           hr->r.segment == 2 ? "BSS" : "unknown",
+                           hr->r.segment);
+                   errorcount++;
+                   break;
+               }
+
+               if (hr->r.length != 1 && hr->r.length != 2 && hr->r.length!=4)
+               {
+                   fprintf(stderr, "%s: nonstandard length reloc "
+                           "(%d bytes)\n", cur->name, hr->r.length);
+                   errorcount++;
+                   break;
+               }
+
+               /* 
+                * okay, now the relocation is in the segment pointed to by
+                * cur->seginfo[localseg], and we know everything else is
+                * okay to go ahead and do the relocation
+                */
+               data = outputseg[cur->seginfo[localseg].dest_seg].data;
+               data += cur->seginfo[localseg].reloc + hr->r.offset;
+
+               /*
+                * data now points to the reference that needs
+                * relocation. Calculate the relocation factor.
+                * Factor is:
+                *      offset of referred object in segment [in offset]
+                *      (- relocation of localseg, if ref is relative)
+                * For simplicity, the result is stored in 'offset'.
+                * Then add 'offset' onto the value at data.
+                */
+               
+               if (isrelative) offset -= cur->seginfo[localseg].reloc;
+               switch (hr->r.length)
+               {
+               case 1:
+                   offset += *data;
+                   if (offset < -127 || offset > 128)
+                       fprintf(error_file, "warning: relocation out of range "
+                               "at %s(%02x:%08lx)\n", cur->name,
+                               (int)hr->r.segment, hr->r.offset);
+                   *data = (char) offset;
+                   break;
+               case 2:
+                   offset += * (short *)data;
+                   if (offset < -32767 || offset > 32768)
+                       fprintf(error_file, "warning: relocation out of range "
+                               "at %s(%02x:%08lx)\n", cur->name,
+                               (int)hr->r.segment, hr->r.offset);
+                   * (short *)data = (short) offset;
+                   break;
+               case 4:
+                   * (long *)data += offset;
+                   /* we can't easily detect overflow on this one */
+                   break;
+               }
+
+               /*
+                * If the relocation was relative between two symbols in
+                * the same segment, then we're done.
+                *
+                * Otherwise, we need to output a new relocation record
+                * with the references updated segment and offset...
+                */
+               if (! isrelative 
+                   || cur->seginfo[localseg].dest_seg != seg)
+               {
+                   hr->r.segment = cur->seginfo[localseg].dest_seg;
+                   hr->r.offset += cur->seginfo[localseg].reloc;
+                   hr->r.refseg = seg;
+                   rdfaddheader(rdfheader, hr);
+               }
+               break;
+
+           case 2: /* import symbol */
+           case 7:
+               /*
+                * scan the global symbol table for the symbol
+                * and associate its location with the segment number 
+                * for this module
+                */
+               se = symtabFind(symtab, hr->i.label);
+               if (!se || se->segment == -1) {
+                   if (options.warnUnresolved) {
+                       fprintf(error_file, "warning: unresolved reference to `%s'"
+                               " in module `%s'\n", hr->i.label, cur->name);
+                       if (options.errorUnresolved==1) errorcount++;
+                   }
+                   /*
+                    * we need to allocate a segment number for this
+                    * symbol, and store it in the symbol table for
+                    * future reference
+                    */ 
+                   if (!se) {
+                       se=malloc(sizeof(*se));
+                       if (!se) {
+                           fprintf(stderr, "ldrdf: out of memory\n");
+                           exit(1);
+                       }
+                       se->name = strdup(hr->i.label);
+                       se->flags = 0;
+                       se->segment = availableseg++;
+                       se->offset = 0;
+                       symtabInsert(symtab, se);
+                   }
+                   else {
+                       se->segment = availableseg++;
+                       se->offset = 0;
+                   }
+                   /*
+                    * output a header record that imports it to the
+                    * recently allocated segment number...
+                    */
+                   newrec = *hr;
+                   newrec.i.segment = se->segment;
+                   rdfaddheader(rdfheader, &newrec);
+               }
+
+               add_seglocation(&segs, hr->i.segment, se->segment, se->offset);
+               
+               break;
+
+           case 3: /* export symbol */
+               /*
+                * need to insert an export for this symbol into the new
+                * header, unless we're stripping symbols [unless this
+                * symbol is in an explicit keep list]. *** FIXME ***
+                */
+               if (options.strip)
+                   break;
+
+               if (hr->e.segment == 2) {
+                   seg = 2;
+                   offset = cur->bss_reloc;
+               }
+               else {
+                   localseg = rdffindsegment(&cur->f, hr->e.segment);
+                   if (localseg == -1) {
+                       fprintf(stderr, "%s: exported symbol `%s' from "
+                               "unrecognised segment\n", cur->name,
+                               hr->e.label);
+                       errorcount++;
+                       break;
+                   }
+                   offset = cur->seginfo[localseg].reloc;
+                   seg = cur->seginfo[localseg].dest_seg;
+               }
+
+               hr->e.segment = seg;    
+               hr->e.offset += offset;
+               rdfaddheader(rdfheader, hr);
+               break;
+
+           case 8: /* module name */
+                /*
+                 * insert module name record if export symbols
+                 * are not stripped.
+                 */
+               if (options.strip) break;
+
+               rdfaddheader(rdfheader, hr);
+               break;
+
+           case 6: /* segment fixup */
+               /*
+                * modify the segment numbers if necessary, and
+                * pass straight through to the output module header
+                *
+                * *** FIXME ***
+                */
+               if (hr->r.segment == 2) {
+                   fprintf(stderr, "%s: segment fixup in BSS section\n",
+                           cur->name);
+                   errorcount++;
+                   break;
+               }
+               localseg = rdffindsegment(&cur->f, hr->r.segment);
+               if (localseg == -1) {
+                   fprintf(stderr, "%s: segment fixup in unrecognised"
+                           " segment (%d)\n", cur->name, hr->r.segment);
+                   errorcount++;
+                   break;
+               }
+               hr->r.segment = cur->seginfo[localseg].dest_seg;
+               hr->r.offset += cur->seginfo[localseg].reloc;
+
+               if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset))
+               {
+                   fprintf(stderr, "%s: segment fixup to undefined "
+                           "segment %04x\n", cur->name, (int)hr->r.refseg);
+                   errorcount++;
+                   break;
+               }
+               hr->r.refseg = seg;
+               rdfaddheader(rdfheader, hr);
+               break;
+           }
+       }
+
+       free(header);
+       done_seglocations(&segs);
+
+    }
+
+    /*
+     * combined BSS reservation for the entire results
+     */
+    newrec.type = 5;
+    newrec.b.reclen = 4;
+    newrec.b.amount = bss_length;
+    rdfaddheader(rdfheader, &newrec);
+
+    /*
+     * Write the header
+     */
+    for (i = 0; i < nsegs; i++)
+    {
+       if (i == 2) continue;
+       rdfaddsegment (rdfheader, outputseg[i].length);
+    }
+    
+    if (options.addMBheader) {
+       struct MultiBootHdrRec *mbhrec = (struct MultiBootHdrRec *)(rdfheader->buf->buffer);
+       unsigned l = membuflength(rdfheader->buf) + 14 + 
+                    10*rdfheader->nsegments + rdfheader->seglength;
+       unsigned *ldraddr = (unsigned *)(mbhrec->mover+1);
+
+       mbhrec->mb.LoadEndAddr = MBHloadAddr+l+10+RDFLDR_LENGTH; 
+       mbhrec->mb.BSSendAddr = mbhrec->mb.LoadEndAddr;
+       *ldraddr = MBHloadAddr+l+10;
+    }
+    
+    rdfwriteheader(f, rdfheader);
+    rdfdoneheader(rdfheader);
+    /*
+     * Step through the segments, one at a time, writing out into
+     * the output file
+     */
+    
+    for (i = 0; i < nsegs; i++)
+    {
+       int16 s;
+       long l;
+       
+       if (i == 2) continue;
+
+       s = translateshort(outputseg[i].type);
+       fwrite(&s, 2, 1, f);
+       s = translateshort(outputseg[i].number);
+       fwrite(&s, 2, 1, f);
+       s = translateshort(outputseg[i].reserved);
+       fwrite(&s, 2, 1, f);
+       l = translatelong(outputseg[i].length);
+       fwrite(&l, 4, 1, f);
+
+       fwrite(outputseg[i].data, outputseg[i].length, 1, f);
+    }
+
+    fwrite("\0\0\0\0\0\0\0\0\0\0", 10, 1, f);
+}
+
+/* =========================================================================
+ * Main program
+ */
+
+void usage()
+{
+    printf("usage:\n");
+    printf("   ldrdf [options] object modules ... [-llibrary ...]\n");
+    printf("   ldrdf -r\n");
+    printf("options:\n");
+    printf("   -v[=n]          increases verbosity by 1, or sets it to n\n");
+    printf("   -a nn           sets segment alignment value (default 16)\n");
+    printf("   -s              strips exported symbols\n");
+    printf("   -x              warn about unresolved symbols\n");
+    printf("   -o name         write output in file 'name'\n");
+    printf("   -j path         specify objects search path\n");
+    printf("   -L path         specify libraries search path\n");
+    printf("   -mbh [address]  add multiboot header to output file. Default\n");
+    printf("                   loading address is 0x110000\n");
+    exit(0);
+}
+
+int main(int argc, char ** argv)
+{
+    char * outname = "aout.rdf";
+    int  moduleloaded = 0;
+    char *respstrings[128] = {0, };
+
+    options.verbose = 0;
+    options.align = 16;
+    options.warnUnresolved = 0;
+    options.strip = 0;
+
+    error_file = stderr;
+
+    argc --, argv ++;
+    if (argc == 0) usage();
+    while (argc && **argv == '-' && argv[0][1] != 'l')
+    {
+       switch(argv[0][1]) {
+       case 'r':
+           printf("ldrdf (linker for RDF files) version " LDRDF_VERSION "\n");
+           printf( _RDOFF_H "\n");
+           exit(0);
+       case 'v':
+           if (argv[0][2] == '=') {
+               options.verbose = argv[0][3] - '0';
+               if (options.verbose < 0 || options.verbose > 9) {
+                   fprintf(stderr, "ldrdf: verbosity level must be a number"
+                           " between 0 and 9\n");
+                   exit(1);
+               }
+           }
+           else
+               options.verbose++;
+           break;
+       case 'a':
+           options.align = atoi(argv[1]);
+           if (options.align <= 0) {
+               fprintf(stderr,
+                       "ldrdf: -a expects a positive number argument\n");
+               exit(1);
+           }
+           argv++, argc--;
+           break;
+       case 's':
+           options.strip = 1;
+           break;
+       case 'x':
+           options.warnUnresolved = 1;
+           if (argv[0][2]=='e')
+               options.errorUnresolved = 1;
+           break;
+       case 'o':
+           outname = argv[1];
+           argv++, argc--;
+           break;
+       case 'j':
+           if (!objpath)
+            {
+              options.objpath = 1;
+             objpath = argv[1];
+             argv++, argc--;
+             break;
+            }
+           else
+            {
+             fprintf(stderr,"ldrdf: more than one objects search path specified\n");
+             exit(1);
+            }
+       case 'L':
+           if (!libpath)
+             {
+              options.libpath = 1;
+             libpath = argv[1];
+             argv++, argc--;
+             break;
+            }
+           else
+            {
+             fprintf(stderr,"ldrdf: more than one libraries search path specified\n");
+             exit(1);
+            }
+       case '@': {
+             int i=0;
+             char buf[256];
+             FILE *f;
+
+              options.respfile = 1;
+             if (argv[1] != NULL) f = fopen(argv[1],"r");
+             else
+              {
+               fprintf(stderr,"ldrdf: no response file name specified\n");
+               exit(1);
+              }
+
+             if (f == NULL)
+              {
+               fprintf(stderr,"ldrdf: unable to open response file\n");
+               exit(1);
+              }
+             argc-=2;
+             while(fgets(buf,sizeof(buf)-1,f)!=NULL)
+              {
+               char *p;
+               if (buf[0]=='\n') continue;
+               if ((p = strchr(buf,'\n')) != 0)
+                *p=0;
+               if (i >= 128)
+                {
+                 fprintf(stderr,"ldrdf: too many input files\n");
+                 exit(1);
+                }
+               *(respstrings+i) = newstr(buf);
+               argc++, i++;
+              }
+             goto done;
+        }
+       case '2':
+            options.stderr_redir = 1;
+           error_file = stdout;
+           break;
+       case 'm':
+           if (argv[0][2] == 'b' && argv[0][3] == 'h') {
+               if (argv[1][0] != '-') {
+                   MBHloadAddr = atoi(argv[1]);
+               } else {
+                   MBHloadAddr = MB_DEFAULTLOADADDR;
+               }        
+               options.addMBheader = 1;
+               break;    
+           }           
+       default:
+           usage();
+       }
+       argv++, argc--;
+    }
+done:
+    if (options.verbose > 4) {
+       printf("ldrdf invoked with options:\n");
+       printf("    section alignment: %d bytes\n", options.align);
+       printf("    output name: `%s'\n", outname);
+       if (options.strip)
+           printf("    strip symbols\n");
+       if (options.warnUnresolved)
+           printf("    warn about unresolved symbols\n");
+       if (options.errorUnresolved)
+           printf("    error if unresolved symbols\n");    
+        if (options.objpath)
+            printf("    objects search path: %s\n",objpath);
+        if (options.libpath)
+            printf("    libraries search path: %s\n",libpath);
+       if (options.addMBheader)
+            printf("    loading address for multiboot header: 0x%X\n",MBHloadAddr);    
+       printf("\n");
+    }
+
+    symtab = symtabNew();
+    initsegments();
+
+    if (!symtab) {
+       fprintf(stderr, "ldrdf: out of memory\n");
+       exit(1);
+    }
+
+    if (*respstrings) argv = respstrings;
+    while (argc)
+    {
+       if (!strncmp(*argv, "-l", 2)) /* library */
+         {
+         if(libpath) add_library(newstrcat(libpath,*argv + 2));
+          else add_library(*argv + 2);
+         }
+       else {
+           if(objpath) loadmodule(newstrcat(objpath,*argv));
+           else loadmodule(*argv);
+           moduleloaded = 1;
+       }
+       argv++, argc--;
+    }
+
+    if (! moduleloaded) {
+       printf("ldrdf: nothing to do. ldrdf -h for usage\n");
+       return 0;
+    }
+
+
+    search_libraries();
+
+    if (options.verbose > 2)
+    {
+       printf ("symbol table:\n");
+       symtabDump(symtab, stdout);
+    }
+
+    write_output(outname);
+
+    if (errorcount > 0)        exit(1);
+    return 0;
+}
index 96a1dce..94d2bf7 100644 (file)
@@ -1,34 +1,56 @@
-***************
-*** 26,32 ****
-  
-         jmp start             ; [6]
-  
-- end    mov ax,0x4c00         ; [1]
-         int 0x21
-  
-  start          mov byte [bss_sym],',' ; [1] [8]
---- 26,32 ----
-  
-         jmp start             ; [6]
-  
-+ endX   mov ax,0x4c00         ; [1]
-         int 0x21
-  
-  start          mov byte [bss_sym],',' ; [1] [8]
-***************
-*** 49,55 ****
-  datasym        db 'hello  world', 13, 10, '$' ; [2]
-  bssptr         dw bss_sym            ; [2] [11]
-  dataptr        dw datasym+5          ; [2] [10]
-- textptr        dw end                ; [2] [9]
-  
-         SECTION .bss
-  
---- 49,55 ----
-  datasym        db 'hello  world', 13, 10, '$' ; [2]
-  bssptr         dw bss_sym            ; [2] [11]
-  dataptr        dw datasym+5          ; [2] [10]
-+ textptr        dw endX               ; [2] [9]
-  
-         SECTION .bss
-  
+; test source file for assembling to binary files
+; build with:
+;    nasm -f bin -o bintest.com bintest.asm
+
+; When run (as a DOS .COM file), this program should print
+;    hello, world
+; on two successive lines, then exit cleanly.
+
+; This file should test the following:
+; [1] Define a text-section symbol
+; [2] Define a data-section symbol
+; [3] Define a BSS-section symbol
+; [4] Define a NASM local label
+; [5] Reference a NASM local label
+; [6] Reference a text-section symbol in the text section
+; [7] Reference a data-section symbol in the text section
+; [8] Reference a BSS-section symbol in the text section
+; [9] Reference a text-section symbol in the data section
+; [10] Reference a data-section symbol in the data section
+; [11] Reference a BSS-section symbol in the data section
+
+         BITS 16
+         ORG 0x100
+
+         SECTION .text
+
+         jmp start             ; [6]
+
+endX     mov ax,0x4c00         ; [1]
+         int 0x21
+
+start    mov byte [bss_sym],',' ; [1] [8]
+         mov bx,[bssptr]       ; [7]
+         mov al,[bx]
+         mov bx,[dataptr]      ; [7]
+         mov [bx],al
+         mov cx,2
+.loop    mov dx,datasym        ; [1] [4] [7]
+         mov ah,9
+         push cx
+         int 0x21
+         pop cx
+         loop .loop            ; [5] [6]
+         mov bx,[textptr]      ; [7]
+         jmp bx
+
+         SECTION .data
+
+datasym          db 'hello  world', 13, 10, '$' ; [2]
+bssptr   dw bss_sym            ; [2] [11]
+dataptr          dw datasym+5          ; [2] [10]
+textptr          dw endX               ; [2] [9]
+
+         SECTION .bss
+
+bss_sym          resb 1                ; [3]