mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-11-08 23:27:15 -05:00
error: factor out error functions into separate files
Tidy up a *lot* of code by moving error functions into separate source files. This required breaking out some of the assembler-only files into a separate library, as it conflicts with stubs in the disassembler. Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
132
Makefile.in
132
Makefile.in
@@ -135,54 +135,22 @@ NDISASM = disasm/ndisasm.$(O)
|
||||
PROGOBJ = $(NASM) $(NDISASM)
|
||||
PROGS = nasm$(X) ndisasm$(X)
|
||||
|
||||
# Files dependent on warnings.dat
|
||||
WARNOBJ = asm/warnings.$(O)
|
||||
WARNFILES = asm/warnings_c.h include/warnings.h doc/warnings.src
|
||||
# Objects for the local copy of zlib. The variable ZLIB is set to
|
||||
# $(ZLIBOBJ) if the internal version of zlib should be used.
|
||||
ZLIBOBJ = \
|
||||
zlib/adler32.$(O) \
|
||||
zlib/crc32.$(O) \
|
||||
zlib/infback.$(O) \
|
||||
zlib/inffast.$(O) \
|
||||
zlib/inflate.$(O) \
|
||||
zlib/inftrees.$(O) \
|
||||
zlib/zutil.$(O)
|
||||
|
||||
OUTPUTOBJ = \
|
||||
output/outform.$(O) output/outlib.$(O) \
|
||||
output/nulldbg.$(O) output/nullout.$(O) \
|
||||
output/outbin.$(O) output/outaout.$(O) output/outcoff.$(O) \
|
||||
output/outelf.$(O) \
|
||||
output/outobj.$(O) output/outas86.$(O) \
|
||||
output/outdbg.$(O) output/outieee.$(O) output/outmacho.$(O) \
|
||||
output/codeview.$(O)
|
||||
|
||||
# The source files for these objects are scanned for warnings
|
||||
LIBOBJ_W = \
|
||||
nasmlib/readnum.$(O) \
|
||||
\
|
||||
asm/error.$(O) \
|
||||
asm/floats.$(O) \
|
||||
asm/directiv.$(O) \
|
||||
asm/pragma.$(O) \
|
||||
asm/assemble.$(O) asm/labels.$(O) asm/parser.$(O) \
|
||||
asm/preproc.$(O) asm/quote.$(O) \
|
||||
asm/listing.$(O) asm/eval.$(O) asm/exprlib.$(O) asm/exprdump.$(O) \
|
||||
asm/stdscan.$(O) \
|
||||
asm/getbool.$(O) \
|
||||
asm/strfunc.$(O) \
|
||||
asm/segalloc.$(O) \
|
||||
asm/rdstrnum.$(O) \
|
||||
asm/srcfile.$(O) \
|
||||
\
|
||||
$(OUTPUTOBJ)
|
||||
|
||||
# The source files for these objects are NOT scanned for warnings;
|
||||
# normally this will include all generated files.
|
||||
# It is entirely possible that it may be necessary to move some of these
|
||||
# files to LIBOBJ_W, notably $(OUTPUTOBJ)
|
||||
LIBOBJ_NW = \
|
||||
# Common library objects
|
||||
LIBOBJ_COM = \
|
||||
stdlib/snprintf.$(O) stdlib/vsnprintf.$(O) stdlib/strlcpy.$(O) \
|
||||
stdlib/strnlen.$(O) stdlib/strrchrnul.$(O) \
|
||||
\
|
||||
asm/directbl.$(O) \
|
||||
asm/pptok.$(O) \
|
||||
asm/tokhash.$(O) \
|
||||
asm/uncompress.$(O) \
|
||||
\
|
||||
macros/macros.$(O) \
|
||||
\
|
||||
nasmlib/ver.$(O) \
|
||||
nasmlib/alloc.$(O) nasmlib/asprintf.$(O) \
|
||||
nasmlib/crc32b.$(O) nasmlib/crc64.$(O) nasmlib/md5c.$(O) \
|
||||
@@ -196,35 +164,63 @@ LIBOBJ_NW = \
|
||||
nasmlib/raa.$(O) nasmlib/saa.$(O) \
|
||||
nasmlib/strlist.$(O) \
|
||||
nasmlib/perfhash.$(O) nasmlib/badenum.$(O) \
|
||||
nasmlib/readnum.$(O) \
|
||||
\
|
||||
common/common.$(O) \
|
||||
common/common.$(O) common/errstubs.$(O) \
|
||||
\
|
||||
x86/insnsa.$(O) x86/insnsb.$(O) x86/insnsn.$(O) \
|
||||
x86/regs.$(O) x86/regvals.$(O) x86/regflags.$(O) \
|
||||
x86/iflag.$(O) \
|
||||
\
|
||||
$(WARNOBJ)
|
||||
$(ZLIB)
|
||||
|
||||
# Files dependent on warnings.dat
|
||||
WARNOBJ = asm/warnings.$(O)
|
||||
WARNFILES = asm/warnings_c.h include/warnings.h doc/warnings.src
|
||||
|
||||
OUTPUTOBJ = \
|
||||
output/outform.$(O) output/outlib.$(O) \
|
||||
output/nulldbg.$(O) output/nullout.$(O) \
|
||||
output/outbin.$(O) output/outaout.$(O) output/outcoff.$(O) \
|
||||
output/outelf.$(O) \
|
||||
output/outobj.$(O) output/outas86.$(O) \
|
||||
output/outdbg.$(O) output/outieee.$(O) output/outmacho.$(O) \
|
||||
output/codeview.$(O)
|
||||
|
||||
# Assembler-only library objects
|
||||
LIBOBJ_ASM = \
|
||||
asm/error.$(O) \
|
||||
asm/floats.$(O) \
|
||||
asm/directiv.$(O) \
|
||||
asm/pragma.$(O) \
|
||||
asm/assemble.$(O) asm/labels.$(O) asm/parser.$(O) \
|
||||
asm/preproc.$(O) asm/quote.$(O) \
|
||||
asm/listing.$(O) asm/eval.$(O) asm/exprlib.$(O) asm/exprdump.$(O) \
|
||||
asm/stdscan.$(O) \
|
||||
asm/getbool.$(O) \
|
||||
asm/strfunc.$(O) \
|
||||
asm/segalloc.$(O) \
|
||||
asm/rdstrnum.$(O) \
|
||||
asm/srcfile.$(O) \
|
||||
asm/directbl.$(O) \
|
||||
asm/pptok.$(O) \
|
||||
asm/tokhash.$(O) \
|
||||
asm/uncompress.$(O) \
|
||||
\
|
||||
macros/macros.$(O) \
|
||||
\
|
||||
$(WARNOBJ) \
|
||||
$(OUTPUTOBJ)
|
||||
|
||||
# Objects which are only used for the disassembler
|
||||
LIBOBJ_DIS = \
|
||||
disasm/disasm.$(O) disasm/sync.$(O) disasm/prefix.$(O) \
|
||||
disasm/diserror.$(O) \
|
||||
\
|
||||
x86/insnsd.$(O) x86/regdis.$(O)
|
||||
|
||||
# Objects for the local copy of zlib. The variable ZLIB is set to
|
||||
# $(ZLIBOBJ) if the internal version of zlib should be used.
|
||||
ZLIBOBJ = \
|
||||
zlib/adler32.$(O) \
|
||||
zlib/crc32.$(O) \
|
||||
zlib/infback.$(O) \
|
||||
zlib/inffast.$(O) \
|
||||
zlib/inflate.$(O) \
|
||||
zlib/inftrees.$(O) \
|
||||
zlib/zutil.$(O)
|
||||
|
||||
LIBOBJ = $(LIBOBJ_W) $(LIBOBJ_NW) $(ZLIB)
|
||||
ALLOBJ_W = $(NASM) $(LIBOBJ_W)
|
||||
ALLOBJ = $(PROGOBJ) $(LIBOBJ) $(LIBOBJ_DIS)
|
||||
LIBOBJ = $(LIBOBJ_COM) $(LIBOBJ_ASM) $(LIBOBJ_DIS)
|
||||
ALLOBJ = $(PROGOBJ) $(LIBOBJ)
|
||||
SUBDIRS = stdlib nasmlib include config output asm disasm x86 \
|
||||
common zlib macros misc
|
||||
XSUBDIRS = nsis win test doc editors
|
||||
@@ -241,21 +237,27 @@ $(DIRS):
|
||||
@$(MKDIR_P) $(SUBDIRS) $(XSUBDIRS)
|
||||
|
||||
NASMLIB = libnasm.$(A)
|
||||
DISLIB = libndis.$(A)
|
||||
ASMLIB = libasm.$(A)
|
||||
DISLIB = libdis.$(A)
|
||||
|
||||
$(NASMLIB): $(LIBOBJ)
|
||||
$(NASMLIB): $(LIBOBJ_COM)
|
||||
$(RM_F) $(NASMLIB)
|
||||
$(AR) cq $(NASMLIB) $(LIBOBJ)
|
||||
$(AR) cq $(NASMLIB) $(LIBOBJ_COM)
|
||||
$(RANLIB) $(NASMLIB)
|
||||
|
||||
$(ASMLIB): $(LIBOBJ_ASM)
|
||||
$(RM_F) $(ASMLIB)
|
||||
$(AR) cq $(ASMLIB) $(LIBOBJ_ASM)
|
||||
$(RANLIB) $(ASMLIB)
|
||||
|
||||
$(DISLIB): $(LIBOBJ_DIS)
|
||||
$(RM_F) $(DISLIB)
|
||||
$(AR) cq $(DISLIB) $(LIBOBJ_DIS)
|
||||
$(RANLIB) $(DISLIB)
|
||||
|
||||
nasm$(X): $(NASM) $(MANIFEST) $(NASMLIB)
|
||||
nasm$(X): $(NASM) $(MANIFEST) $(ASMLIB) $(NASMLIB)
|
||||
$(CC) $(ALL_LDFLAGS) -o $@ $(NASM) $(MANIFEST) \
|
||||
$(NASMLIB) $(LIBS)
|
||||
$(ASMLIB) $(NASMLIB) $(LIBS)
|
||||
|
||||
ndisasm$(X): $(NDISASM) $(MANIFEST) $(DISLIB) $(NASMLIB)
|
||||
$(CC) $(ALL_LDFLAGS) -o $@ $(NDISASM) $(MANIFEST) \
|
||||
|
||||
134
Mkfiles/msvc.mak
134
Mkfiles/msvc.mak
@@ -86,54 +86,22 @@ NDISASM = disasm\ndisasm.obj
|
||||
PROGOBJ = $(NASM) $(NDISASM)
|
||||
PROGS = nasm$(X) ndisasm$(X)
|
||||
|
||||
# Files dependent on warnings.dat
|
||||
WARNOBJ = asm\warnings.obj
|
||||
WARNFILES = asm\warnings_c.h include\warnings.h doc\warnings.src
|
||||
# Objects for the local copy of zlib. The variable ZLIB is set to
|
||||
# $(ZLIBOBJ) if the internal version of zlib should be used.
|
||||
ZLIBOBJ = \
|
||||
zlib\adler32.obj \
|
||||
zlib\crc32.obj \
|
||||
zlib\infback.obj \
|
||||
zlib\inffast.obj \
|
||||
zlib\inflate.obj \
|
||||
zlib\inftrees.obj \
|
||||
zlib\zutil.obj
|
||||
|
||||
OUTPUTOBJ = \
|
||||
output\outform.obj output\outlib.obj \
|
||||
output\nulldbg.obj output\nullout.obj \
|
||||
output\outbin.obj output\outaout.obj output\outcoff.obj \
|
||||
output\outelf.obj \
|
||||
output\outobj.obj output\outas86.obj \
|
||||
output\outdbg.obj output\outieee.obj output\outmacho.obj \
|
||||
output\codeview.obj
|
||||
|
||||
# The source files for these objects are scanned for warnings
|
||||
LIBOBJ_W = \
|
||||
nasmlib\readnum.obj \
|
||||
\
|
||||
asm\error.obj \
|
||||
asm\floats.obj \
|
||||
asm\directiv.obj \
|
||||
asm\pragma.obj \
|
||||
asm\assemble.obj asm\labels.obj asm\parser.obj \
|
||||
asm\preproc.obj asm\quote.obj \
|
||||
asm\listing.obj asm\eval.obj asm\exprlib.obj asm\exprdump.obj \
|
||||
asm\stdscan.obj \
|
||||
asm\getbool.obj \
|
||||
asm\strfunc.obj \
|
||||
asm\segalloc.obj \
|
||||
asm\rdstrnum.obj \
|
||||
asm\srcfile.obj \
|
||||
\
|
||||
$(OUTPUTOBJ)
|
||||
|
||||
# The source files for these objects are NOT scanned for warnings;
|
||||
# normally this will include all generated files.
|
||||
# It is entirely possible that it may be necessary to move some of these
|
||||
# files to LIBOBJ_W, notably $(OUTPUTOBJ)
|
||||
LIBOBJ_NW = \
|
||||
# Common library objects
|
||||
LIBOBJ_COM = \
|
||||
stdlib\snprintf.obj stdlib\vsnprintf.obj stdlib\strlcpy.obj \
|
||||
stdlib\strnlen.obj stdlib\strrchrnul.obj \
|
||||
\
|
||||
asm\directbl.obj \
|
||||
asm\pptok.obj \
|
||||
asm\tokhash.obj \
|
||||
asm\uncompress.obj \
|
||||
\
|
||||
macros\macros.obj \
|
||||
\
|
||||
nasmlib\ver.obj \
|
||||
nasmlib\alloc.obj nasmlib\asprintf.obj \
|
||||
nasmlib\crc32b.obj nasmlib\crc64.obj nasmlib\md5c.obj \
|
||||
@@ -147,35 +115,63 @@ LIBOBJ_NW = \
|
||||
nasmlib\raa.obj nasmlib\saa.obj \
|
||||
nasmlib\strlist.obj \
|
||||
nasmlib\perfhash.obj nasmlib\badenum.obj \
|
||||
nasmlib\readnum.obj \
|
||||
\
|
||||
common\common.obj \
|
||||
common\common.obj common\errstubs.obj \
|
||||
\
|
||||
x86\insnsa.obj x86\insnsb.obj x86\insnsn.obj \
|
||||
x86\regs.obj x86\regvals.obj x86\regflags.obj \
|
||||
x86\iflag.obj \
|
||||
\
|
||||
$(WARNOBJ)
|
||||
$(ZLIB)
|
||||
|
||||
# Files dependent on warnings.dat
|
||||
WARNOBJ = asm\warnings.obj
|
||||
WARNFILES = asm\warnings_c.h include\warnings.h doc\warnings.src
|
||||
|
||||
OUTPUTOBJ = \
|
||||
output\outform.obj output\outlib.obj \
|
||||
output\nulldbg.obj output\nullout.obj \
|
||||
output\outbin.obj output\outaout.obj output\outcoff.obj \
|
||||
output\outelf.obj \
|
||||
output\outobj.obj output\outas86.obj \
|
||||
output\outdbg.obj output\outieee.obj output\outmacho.obj \
|
||||
output\codeview.obj
|
||||
|
||||
# Assembler-only library objects
|
||||
LIBOBJ_ASM = \
|
||||
asm\error.obj \
|
||||
asm\floats.obj \
|
||||
asm\directiv.obj \
|
||||
asm\pragma.obj \
|
||||
asm\assemble.obj asm\labels.obj asm\parser.obj \
|
||||
asm\preproc.obj asm\quote.obj \
|
||||
asm\listing.obj asm\eval.obj asm\exprlib.obj asm\exprdump.obj \
|
||||
asm\stdscan.obj \
|
||||
asm\getbool.obj \
|
||||
asm\strfunc.obj \
|
||||
asm\segalloc.obj \
|
||||
asm\rdstrnum.obj \
|
||||
asm\srcfile.obj \
|
||||
asm\directbl.obj \
|
||||
asm\pptok.obj \
|
||||
asm\tokhash.obj \
|
||||
asm\uncompress.obj \
|
||||
\
|
||||
macros\macros.obj \
|
||||
\
|
||||
$(WARNOBJ) \
|
||||
$(OUTPUTOBJ)
|
||||
|
||||
# Objects which are only used for the disassembler
|
||||
LIBOBJ_DIS = \
|
||||
disasm\disasm.obj disasm\sync.obj disasm\prefix.obj \
|
||||
disasm\diserror.obj \
|
||||
\
|
||||
x86\insnsd.obj x86\regdis.obj
|
||||
|
||||
# Objects for the local copy of zlib. The variable ZLIB is set to
|
||||
# $(ZLIBOBJ) if the internal version of zlib should be used.
|
||||
ZLIBOBJ = \
|
||||
zlib\adler32.obj \
|
||||
zlib\crc32.obj \
|
||||
zlib\infback.obj \
|
||||
zlib\inffast.obj \
|
||||
zlib\inflate.obj \
|
||||
zlib\inftrees.obj \
|
||||
zlib\zutil.obj
|
||||
|
||||
LIBOBJ = $(LIBOBJ_W) $(LIBOBJ_NW) $(ZLIB)
|
||||
ALLOBJ_W = $(NASM) $(LIBOBJ_W)
|
||||
ALLOBJ = $(PROGOBJ) $(LIBOBJ) $(LIBOBJ_DIS)
|
||||
LIBOBJ = $(LIBOBJ_COM) $(LIBOBJ_ASM) $(LIBOBJ_DIS)
|
||||
ALLOBJ = $(PROGOBJ) $(LIBOBJ)
|
||||
SUBDIRS = stdlib nasmlib include config output asm disasm x86 \
|
||||
common zlib macros misc
|
||||
XSUBDIRS = nsis win test doc editors
|
||||
@@ -186,22 +182,26 @@ EDITORS = editors\nasmtok.el editors\nasmtok.json
|
||||
#-- End File Lists --#
|
||||
|
||||
NASMLIB = libnasm.$(A)
|
||||
NDISLIB = libndis.$(A)
|
||||
ASMLIB = libasm.$(A)
|
||||
DISLIB = libdis.$(A)
|
||||
|
||||
all: nasm$(X) ndisasm$(X)
|
||||
|
||||
nasm$(X): $(NASM) $(MANIFEST) $(NASMLIB)
|
||||
$(CC) /Fe:$@ $(ALL_CFLAGS) $(NASM) $(NASMLIB) $(LIBS) \
|
||||
nasm$(X): $(NASM) $(MANIFEST) $(ASMLIB) $(NASMLIB)
|
||||
$(CC) /Fe:$@ $(ALL_CFLAGS) $(NASM) $(ASMLIB) $(NASMLIB) $(LIBS) \
|
||||
$(ALL_LDFLAGS)
|
||||
|
||||
ndisasm$(X): $(NDISASM) $(MANIFEST) $(NDISLIB) $(NASMLIB)
|
||||
$(CC) /Fe:$@ $(ALL_CFLAGS) $(NDISASM) $(NDISLIB) $(NASMLIB) $(LIBS) \
|
||||
ndisasm$(X): $(NDISASM) $(MANIFEST) $(DISLIB) $(NASMLIB)
|
||||
$(CC) /Fe:$@ $(ALL_CFLAGS) $(NDISASM) $(DISLIB) $(NASMLIB) $(LIBS) \
|
||||
$(ALL_LDFLAGS)
|
||||
|
||||
$(NASMLIB): $(LIBOBJ)
|
||||
$(NASMLIB): $(LIBOBJ_COM)
|
||||
$(AR) $(ARFLAGS) /out:$@ $**
|
||||
|
||||
$(NDISLIB): $(LIBOBJ_DIS)
|
||||
$(ASMLIB): $(LIBOBJ_ASM)
|
||||
$(AR) $(ARFLAGS) /out:$@ $**
|
||||
|
||||
$(DISLIB): $(LIBOBJ_DIS)
|
||||
$(AR) $(ARFLAGS) /out:$@ $**
|
||||
|
||||
# These are specific to certain Makefile syntaxes...
|
||||
|
||||
@@ -72,54 +72,22 @@ NDISASM = disasm\ndisasm.obj
|
||||
PROGOBJ = $(NASM) $(NDISASM)
|
||||
PROGS = nasm$(X) ndisasm$(X)
|
||||
|
||||
# Files dependent on warnings.dat
|
||||
WARNOBJ = asm\warnings.obj
|
||||
WARNFILES = asm\warnings_c.h include\warnings.h doc\warnings.src
|
||||
# Objects for the local copy of zlib. The variable ZLIB is set to
|
||||
# $(ZLIBOBJ) if the internal version of zlib should be used.
|
||||
ZLIBOBJ = &
|
||||
zlib\adler32.obj &
|
||||
zlib\crc32.obj &
|
||||
zlib\infback.obj &
|
||||
zlib\inffast.obj &
|
||||
zlib\inflate.obj &
|
||||
zlib\inftrees.obj &
|
||||
zlib\zutil.obj
|
||||
|
||||
OUTPUTOBJ = &
|
||||
output\outform.obj output\outlib.obj &
|
||||
output\nulldbg.obj output\nullout.obj &
|
||||
output\outbin.obj output\outaout.obj output\outcoff.obj &
|
||||
output\outelf.obj &
|
||||
output\outobj.obj output\outas86.obj &
|
||||
output\outdbg.obj output\outieee.obj output\outmacho.obj &
|
||||
output\codeview.obj
|
||||
|
||||
# The source files for these objects are scanned for warnings
|
||||
LIBOBJ_W = &
|
||||
nasmlib\readnum.obj &
|
||||
&
|
||||
asm\error.obj &
|
||||
asm\floats.obj &
|
||||
asm\directiv.obj &
|
||||
asm\pragma.obj &
|
||||
asm\assemble.obj asm\labels.obj asm\parser.obj &
|
||||
asm\preproc.obj asm\quote.obj &
|
||||
asm\listing.obj asm\eval.obj asm\exprlib.obj asm\exprdump.obj &
|
||||
asm\stdscan.obj &
|
||||
asm\getbool.obj &
|
||||
asm\strfunc.obj &
|
||||
asm\segalloc.obj &
|
||||
asm\rdstrnum.obj &
|
||||
asm\srcfile.obj &
|
||||
&
|
||||
$(OUTPUTOBJ)
|
||||
|
||||
# The source files for these objects are NOT scanned for warnings;
|
||||
# normally this will include all generated files.
|
||||
# It is entirely possible that it may be necessary to move some of these
|
||||
# files to LIBOBJ_W, notably $(OUTPUTOBJ)
|
||||
LIBOBJ_NW = &
|
||||
# Common library objects
|
||||
LIBOBJ_COM = &
|
||||
stdlib\snprintf.obj stdlib\vsnprintf.obj stdlib\strlcpy.obj &
|
||||
stdlib\strnlen.obj stdlib\strrchrnul.obj &
|
||||
&
|
||||
asm\directbl.obj &
|
||||
asm\pptok.obj &
|
||||
asm\tokhash.obj &
|
||||
asm\uncompress.obj &
|
||||
&
|
||||
macros\macros.obj &
|
||||
&
|
||||
nasmlib\ver.obj &
|
||||
nasmlib\alloc.obj nasmlib\asprintf.obj &
|
||||
nasmlib\crc32b.obj nasmlib\crc64.obj nasmlib\md5c.obj &
|
||||
@@ -133,35 +101,63 @@ LIBOBJ_NW = &
|
||||
nasmlib\raa.obj nasmlib\saa.obj &
|
||||
nasmlib\strlist.obj &
|
||||
nasmlib\perfhash.obj nasmlib\badenum.obj &
|
||||
nasmlib\readnum.obj &
|
||||
&
|
||||
common\common.obj &
|
||||
common\common.obj common\errstubs.obj &
|
||||
&
|
||||
x86\insnsa.obj x86\insnsb.obj x86\insnsn.obj &
|
||||
x86\regs.obj x86\regvals.obj x86\regflags.obj &
|
||||
x86\iflag.obj &
|
||||
&
|
||||
$(WARNOBJ)
|
||||
$(ZLIB)
|
||||
|
||||
# Files dependent on warnings.dat
|
||||
WARNOBJ = asm\warnings.obj
|
||||
WARNFILES = asm\warnings_c.h include\warnings.h doc\warnings.src
|
||||
|
||||
OUTPUTOBJ = &
|
||||
output\outform.obj output\outlib.obj &
|
||||
output\nulldbg.obj output\nullout.obj &
|
||||
output\outbin.obj output\outaout.obj output\outcoff.obj &
|
||||
output\outelf.obj &
|
||||
output\outobj.obj output\outas86.obj &
|
||||
output\outdbg.obj output\outieee.obj output\outmacho.obj &
|
||||
output\codeview.obj
|
||||
|
||||
# Assembler-only library objects
|
||||
LIBOBJ_ASM = &
|
||||
asm\error.obj &
|
||||
asm\floats.obj &
|
||||
asm\directiv.obj &
|
||||
asm\pragma.obj &
|
||||
asm\assemble.obj asm\labels.obj asm\parser.obj &
|
||||
asm\preproc.obj asm\quote.obj &
|
||||
asm\listing.obj asm\eval.obj asm\exprlib.obj asm\exprdump.obj &
|
||||
asm\stdscan.obj &
|
||||
asm\getbool.obj &
|
||||
asm\strfunc.obj &
|
||||
asm\segalloc.obj &
|
||||
asm\rdstrnum.obj &
|
||||
asm\srcfile.obj &
|
||||
asm\directbl.obj &
|
||||
asm\pptok.obj &
|
||||
asm\tokhash.obj &
|
||||
asm\uncompress.obj &
|
||||
&
|
||||
macros\macros.obj &
|
||||
&
|
||||
$(WARNOBJ) &
|
||||
$(OUTPUTOBJ)
|
||||
|
||||
# Objects which are only used for the disassembler
|
||||
LIBOBJ_DIS = &
|
||||
disasm\disasm.obj disasm\sync.obj disasm\prefix.obj &
|
||||
disasm\diserror.obj &
|
||||
&
|
||||
x86\insnsd.obj x86\regdis.obj
|
||||
|
||||
# Objects for the local copy of zlib. The variable ZLIB is set to
|
||||
# $(ZLIBOBJ) if the internal version of zlib should be used.
|
||||
ZLIBOBJ = &
|
||||
zlib\adler32.obj &
|
||||
zlib\crc32.obj &
|
||||
zlib\infback.obj &
|
||||
zlib\inffast.obj &
|
||||
zlib\inflate.obj &
|
||||
zlib\inftrees.obj &
|
||||
zlib\zutil.obj
|
||||
|
||||
LIBOBJ = $(LIBOBJ_W) $(LIBOBJ_NW) $(ZLIB)
|
||||
ALLOBJ_W = $(NASM) $(LIBOBJ_W)
|
||||
ALLOBJ = $(PROGOBJ) $(LIBOBJ) $(LIBOBJ_DIS)
|
||||
LIBOBJ = $(LIBOBJ_COM) $(LIBOBJ_ASM) $(LIBOBJ_DIS)
|
||||
ALLOBJ = $(PROGOBJ) $(LIBOBJ)
|
||||
SUBDIRS = stdlib nasmlib include config output asm disasm x86 &
|
||||
common zlib macros misc
|
||||
XSUBDIRS = nsis win test doc editors
|
||||
@@ -198,18 +194,22 @@ all: perlreq nasm$(X) ndisasm$(X) .SYMBOLIC
|
||||
# cd rdoff && $(MAKE) all
|
||||
|
||||
NASMLIB = nasm.lib
|
||||
NDISLIB = ndisasm.lib
|
||||
ASMLIB = asm.lib
|
||||
DISLIB = dis.lib
|
||||
|
||||
nasm$(X): $(NASM) $(NASMLIB)
|
||||
$(LD) $(LDFLAGS) name nasm$(X) libr {$(NASMLIB) $(LIBS)} file {$(NASM)}
|
||||
nasm$(X): $(NASM) $(ASMLIB) $(NASMLIB)
|
||||
$(LD) $(LDFLAGS) name nasm$(X) libr {$(ASMLIB) $(NASMLIB) $(LIBS)} file {$(NASM)}
|
||||
|
||||
ndisasm$(X): $(NDISASM) $(NDISLIB) $(NASMLIB)
|
||||
$(LD) $(LDFLAGS) name ndisasm$(X) libr {$(NDISLIB) $(NASMLIB) $(LIBS)} file {$(NDISASM)}
|
||||
ndisasm$(X): $(NDISASM) $(DISLIB) $(NASMLIB)
|
||||
$(LD) $(LDFLAGS) name ndisasm$(X) libr {$(DISLIB) $(NASMLIB) $(LIBS)} file {$(NDISASM)}
|
||||
|
||||
nasm.lib: $(LIBOBJ)
|
||||
wlib -q -b -n $@ $(LIBOBJ)
|
||||
nasm.lib: $(LIBOBJ_COM)
|
||||
wlib -q -b -n $@ $(LIBOBJ_COM)
|
||||
|
||||
ndisasm.lib: $(LIBOBJ_DIS)
|
||||
asm.lib: $(LIBOBJ_ASM)
|
||||
wlib -q -b -n $@ $(LIBOBJ_ASM)
|
||||
|
||||
dis.lib: $(LIBOBJ_DIS)
|
||||
wlib -q -b -n $@ $(LIBOBJ_DIS)
|
||||
|
||||
# These are specific to certain Makefile syntaxes (what are they
|
||||
|
||||
646
asm/error.c
646
asm/error.c
@@ -8,108 +8,27 @@
|
||||
#include "compiler.h"
|
||||
#include "nasmlib.h"
|
||||
#include "error.h"
|
||||
#include "listing.h"
|
||||
#include "srcfile.h"
|
||||
#include "strlist.h"
|
||||
|
||||
unsigned int debug_nasm; /* Debugging messages? */
|
||||
unsigned int opt_verbose_info; /* Informational messages? */
|
||||
struct error_format {
|
||||
const char *beforeline; /* Before line number, if present */
|
||||
const char *afterline; /* After line number, if present */
|
||||
const char *beforemsg; /* Before actual message */
|
||||
};
|
||||
|
||||
/* Common function body */
|
||||
#define nasm_do_error(_sev,_flags) \
|
||||
do { \
|
||||
const errflags nde_severity = (_sev); \
|
||||
const errflags nde_flags = nde_severity | (_flags); \
|
||||
va_list ap; \
|
||||
va_start(ap, fmt); \
|
||||
if (nde_severity >= ERR_CRITICAL) { \
|
||||
nasm_verror_critical(nde_flags, fmt, ap); \
|
||||
unreachable(); \
|
||||
} else { \
|
||||
nasm_verror(nde_flags, fmt, ap); \
|
||||
if (nde_severity >= ERR_FATAL) \
|
||||
unreachable(); \
|
||||
} \
|
||||
va_end(ap); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* This is the generic function to use when the error type is not
|
||||
* known a priori. For ERR_DEBUG and ERR_INFO the level can be
|
||||
* included by
|
||||
*/
|
||||
void nasm_error(errflags flags, const char *fmt, ...)
|
||||
{
|
||||
nasm_do_error(flags & ERR_MASK, flags);
|
||||
}
|
||||
|
||||
#define nasm_err_helpers(_type, _name, _sev) \
|
||||
_type nasm_ ## _name ## f (errflags flags, const char *fmt, ...) \
|
||||
{ \
|
||||
nasm_do_error(_sev, flags); \
|
||||
} \
|
||||
_type nasm_ ## _name (const char *fmt, ...) \
|
||||
{ \
|
||||
nasm_do_error(_sev, 0); \
|
||||
}
|
||||
|
||||
nasm_err_helpers(void, listmsg, ERR_LISTMSG)
|
||||
nasm_err_helpers(void, note, ERR_NOTE)
|
||||
nasm_err_helpers(void, nonfatal, ERR_NONFATAL)
|
||||
nasm_err_helpers(fatal_func, fatal, ERR_FATAL)
|
||||
nasm_err_helpers(fatal_func, critical, ERR_CRITICAL)
|
||||
nasm_err_helpers(fatal_func, panic, ERR_PANIC)
|
||||
|
||||
/*
|
||||
* Strongly discourage warnings without level by require flags on warnings.
|
||||
* This means nasm_warn() is the equivalent of the -f variants of the
|
||||
* other ones.
|
||||
*
|
||||
* This is wrapped in a macro to be able to elide it if the warning is
|
||||
* disabled, hence the extra underscore.
|
||||
*/
|
||||
void nasm_warn_(errflags flags, const char *fmt, ...)
|
||||
{
|
||||
nasm_do_error(ERR_WARNING, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* nasm_info() and nasm_debug() takes mandatory enabling levels.
|
||||
*/
|
||||
void nasm_info_(unsigned int level, const char *fmt, ...)
|
||||
{
|
||||
if (info_level(level))
|
||||
nasm_do_error(ERR_INFO, LEVEL(level));
|
||||
}
|
||||
|
||||
void nasm_debug_(unsigned int level, const char *fmt, ...)
|
||||
{
|
||||
if (debug_level(level))
|
||||
nasm_do_error(ERR_DEBUG, LEVEL(level));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convenience function for nasm_nonfatal(ERR_HOLD, ...)
|
||||
*/
|
||||
void nasm_holderr(const char *fmt, ...)
|
||||
{
|
||||
nasm_do_error(ERR_NONFATAL, ERR_NONFATAL|ERR_HOLD);
|
||||
}
|
||||
|
||||
fatal_func nasm_panic_from_macro(const char *func, const char *file, int line)
|
||||
{
|
||||
if (!func)
|
||||
func = "<unknown>";
|
||||
|
||||
nasm_panic("internal error in %s at %s:%d\n", func, file, line);
|
||||
}
|
||||
|
||||
fatal_func nasm_assert_failed(const char *msg, const char *func,
|
||||
const char *file, int line)
|
||||
{
|
||||
if (!func)
|
||||
func = "<unknown>";
|
||||
|
||||
nasm_panic("assertion %s failed in %s at %s:%d", msg, func, file, line);
|
||||
}
|
||||
enum error_formats {
|
||||
ERRFMT_GNU,
|
||||
ERRFMT_MSVC
|
||||
};
|
||||
static const struct error_format errfmts[] = {
|
||||
{ ":", "", ": " }, /* ERRFMT_GNU */
|
||||
{ "(", ")", " : " } /* ERRFMT_MSVC */
|
||||
};
|
||||
static const struct error_format *errfmt = &errfmts[ERRFMT_GNU];
|
||||
|
||||
static void usage(void);
|
||||
|
||||
/*
|
||||
* Warning stack management. Note that there is an implicit "push"
|
||||
@@ -121,6 +40,7 @@ struct warning_stack {
|
||||
uint8_t state[sizeof warning_state];
|
||||
};
|
||||
static struct warning_stack *warning_stack, *warning_state_init;
|
||||
static struct strlist *warn_list;
|
||||
|
||||
/* Push the warning status onto the warning stack */
|
||||
void push_warnings(void)
|
||||
@@ -147,16 +67,33 @@ void pop_warnings(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Call after the command line is parsed, but before the first pass */
|
||||
void init_warnings(void)
|
||||
/* Called after the command line is parsed, but before the first pass */
|
||||
static void init_warnings(void)
|
||||
{
|
||||
push_warnings();
|
||||
warning_state_init = warning_stack;
|
||||
}
|
||||
|
||||
void error_init(void)
|
||||
{
|
||||
erropt.worst = 0;
|
||||
init_warnings();
|
||||
}
|
||||
|
||||
/* Call after each pass */
|
||||
void reset_warnings(void)
|
||||
/* Called before each pass. Buffer warnings if "final" is false. */
|
||||
void error_pass_start(bool final)
|
||||
{
|
||||
nasm_assert(!warn_list);
|
||||
|
||||
erropt.worst = 0;
|
||||
if (!final)
|
||||
warn_list = strlist_alloc(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called after the completion of each pass. This MUST preserve erropt.worst!
|
||||
*/
|
||||
static void reset_warnings(void)
|
||||
{
|
||||
struct warning_stack *ws = warning_stack;
|
||||
|
||||
@@ -170,6 +107,12 @@ void reset_warnings(void)
|
||||
memcpy(warning_state, ws->state, sizeof warning_state);
|
||||
}
|
||||
|
||||
void error_pass_end(void)
|
||||
{
|
||||
strlist_free(&warn_list);
|
||||
reset_warnings();
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called when processing a -w or -W option, or a warning directive.
|
||||
* Returns ok if the action was successful.
|
||||
@@ -311,3 +254,500 @@ const char *error_pfx(errflags severity)
|
||||
return "internal error: ";
|
||||
}
|
||||
}
|
||||
|
||||
static bool skip_this_pass(errflags severity)
|
||||
{
|
||||
errflags type = severity & ERR_MASK;
|
||||
|
||||
/*
|
||||
* See if it's a pass-specific error or warning which should be skipped.
|
||||
* We can never skip fatal errors as by definition they cannot be
|
||||
* resumed from.
|
||||
*/
|
||||
if (type >= ERR_FATAL)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* ERR_LISTMSG and ERR_NOTE messages are always skipped; the list
|
||||
* file receives them anyway as this function is not consulted for
|
||||
* sending to the list file.
|
||||
*/
|
||||
if (type <= ERR_NOTE)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* This message is not applicable unless it is the last pass we
|
||||
* are going to execute; this can be either the final
|
||||
* code-generation pass or the single pass executed in
|
||||
* preproc-only mode.
|
||||
*/
|
||||
return (severity & ERR_PASS2) && !pass_final_or_preproc();
|
||||
}
|
||||
|
||||
/**
|
||||
* check for suppressed message (usually warnings or notes)
|
||||
*
|
||||
* @param severity the severity of the warning or error
|
||||
* @return true if we should abort error/warning printing
|
||||
*/
|
||||
static bool is_suppressed(errflags flags)
|
||||
{
|
||||
const errflags severity = flags & ERR_MASK;
|
||||
const errflags level = WARN_IDX(flags);
|
||||
|
||||
if (severity >= ERR_FATAL) {
|
||||
/* Fatal errors or higher can never be suppressed */
|
||||
return false;
|
||||
}
|
||||
|
||||
if (flags & erropt.never)
|
||||
return true;
|
||||
|
||||
switch (severity) {
|
||||
case ERR_WARNING:
|
||||
if (!(warning_state[level] & WARN_ST_ENABLED))
|
||||
return true;
|
||||
break;
|
||||
|
||||
case ERR_INFO:
|
||||
if (!info_level(level))
|
||||
return true;
|
||||
break;
|
||||
|
||||
case ERR_DEBUG:
|
||||
if (!debug_level(level))
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Suppressed by the preprocessor? */
|
||||
if (!(flags & ERR_PP_LISTMACRO))
|
||||
return pp_suppress_error(flags);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the true error type (the ERR_MASK part) of the given
|
||||
* severity, accounting for warnings that may need to be promoted to
|
||||
* error.
|
||||
*
|
||||
* @param severity the severity of the warning or error
|
||||
* @return true if we should error out
|
||||
*/
|
||||
static errflags pure_func true_error_type(errflags severity)
|
||||
{
|
||||
const uint8_t warn_is_err = WARN_ST_ENABLED|WARN_ST_ERROR;
|
||||
int type;
|
||||
|
||||
type = severity & ERR_MASK;
|
||||
|
||||
if (type == ERR_WARNING) {
|
||||
/* Promote warning to error? */
|
||||
uint8_t state = warning_state[WARN_IDX(severity)];
|
||||
if ((state & warn_is_err) == warn_is_err)
|
||||
type = ERR_NONFATAL;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static const char no_file_name[] = "nasm"; /* What to print if no file name */
|
||||
|
||||
/*
|
||||
* For fatal/critical/panic errors, kill this process.
|
||||
*
|
||||
* For FATAL errors doing cleanups, tidying up the list process,
|
||||
* and so in is acceptable.
|
||||
*
|
||||
* For CRITICAL errors, minimize dependencies on memory allocation
|
||||
* and/or having a system valid state.
|
||||
*
|
||||
* For PANIC, if abort_on_panic is set, abort without any other action.
|
||||
*/
|
||||
static_fatal_func die_hard(errflags true_type, errflags severity)
|
||||
{
|
||||
if (true_type < ERR_PANIC || !erropt.abort_on_panic) {
|
||||
if (true_type < ERR_CRITICAL) {
|
||||
/* FATAL shutdown, general cleanup actions are valid */
|
||||
print_final_report(true);
|
||||
lfmt->cleanup();
|
||||
}
|
||||
|
||||
fflush(NULL);
|
||||
|
||||
close_output(true);
|
||||
|
||||
if (severity & ERR_USAGE)
|
||||
usage();
|
||||
|
||||
/* Terminate immediately (exit closes any still open files) */
|
||||
exit(true_type - ERR_FATAL + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* abort() shouldn't ever return, but be paranoid about this,
|
||||
* plus it helps some compilers clue in to the fact that this
|
||||
* function can never, ever return.
|
||||
*/
|
||||
while (1)
|
||||
abort();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the struct src_location appropriate for use, after some
|
||||
* potential filename mangling.
|
||||
*/
|
||||
static struct src_location error_where(errflags severity)
|
||||
{
|
||||
struct src_location where;
|
||||
|
||||
if (severity & ERR_NOFILE) {
|
||||
where.filename = NULL;
|
||||
where.lineno = 0;
|
||||
} else {
|
||||
where = src_where_error();
|
||||
|
||||
if (!where.filename) {
|
||||
where.filename =
|
||||
inname && inname[0] ? inname :
|
||||
outname && outname[0] ? outname :
|
||||
NULL;
|
||||
where.lineno = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return where;
|
||||
}
|
||||
|
||||
/*
|
||||
* error reporting for critical and panic errors: minimize
|
||||
* the amount of system dependencies for getting a message out,
|
||||
* and in particular try to avoid memory allocations.
|
||||
*/
|
||||
fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list args)
|
||||
{
|
||||
struct src_location where;
|
||||
errflags true_type = severity & ERR_MASK;
|
||||
static bool been_here = false;
|
||||
|
||||
while (unlikely(been_here))
|
||||
abort(); /* Recursive critical error... just die */
|
||||
|
||||
been_here = true;
|
||||
|
||||
erropt.worst = true_type;
|
||||
|
||||
where = error_where(severity);
|
||||
if (!where.filename)
|
||||
where.filename = no_file_name;
|
||||
|
||||
fputs(error_pfx(severity), erropt.file);
|
||||
fputs(where.filename, erropt.file);
|
||||
if (where.lineno) {
|
||||
fprintf(erropt.file, "%s%"PRId32"%s",
|
||||
errfmt->beforeline, where.lineno, errfmt->afterline);
|
||||
}
|
||||
fputs(errfmt->beforemsg, erropt.file);
|
||||
vfprintf(erropt.file, fmt, args);
|
||||
fputc('\n', erropt.file);
|
||||
|
||||
die_hard(true_type, severity);
|
||||
unreachable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stack of tentative error hold lists.
|
||||
*/
|
||||
struct nasm_errtext {
|
||||
struct nasm_errtext *next;
|
||||
char *msg; /* Owned by this structure */
|
||||
struct src_location where; /* Owned by the srcfile system */
|
||||
errflags severity;
|
||||
errflags true_type;
|
||||
int c_errno; /* Saved errno (for ERR_PERROR) */
|
||||
};
|
||||
struct nasm_errhold {
|
||||
struct nasm_errhold *up;
|
||||
struct nasm_errtext *head, **tail;
|
||||
};
|
||||
|
||||
static struct strlist *warn_list;
|
||||
static struct nasm_errhold *errhold_stack;
|
||||
|
||||
static void nasm_free_error(struct nasm_errtext *et)
|
||||
{
|
||||
nasm_free(et->msg);
|
||||
nasm_free(et);
|
||||
}
|
||||
|
||||
static void nasm_issue_error(struct nasm_errtext *et);
|
||||
|
||||
struct nasm_errhold *nasm_error_hold_push(void)
|
||||
{
|
||||
struct nasm_errhold *eh;
|
||||
|
||||
nasm_new(eh);
|
||||
eh->up = errhold_stack;
|
||||
eh->tail = &eh->head;
|
||||
errhold_stack = eh;
|
||||
|
||||
return eh;
|
||||
}
|
||||
|
||||
/* Pop an error hold. Returns the highest severity issued or dropped. */
|
||||
errflags nasm_error_hold_pop(struct nasm_errhold *eh, bool issue)
|
||||
{
|
||||
struct nasm_errtext *et, *etmp;
|
||||
errflags worst = 0;
|
||||
|
||||
/*
|
||||
* Allow calling with a null argument saying no hold in the first place.
|
||||
*/
|
||||
if (!eh)
|
||||
return worst;
|
||||
|
||||
/* This *must* be the current top of the errhold stack */
|
||||
nasm_assert(eh == errhold_stack);
|
||||
|
||||
if (eh->head) {
|
||||
if (issue) {
|
||||
if (eh->up) {
|
||||
/* Commit the current hold list to the previous level */
|
||||
*eh->up->tail = eh->head;
|
||||
eh->up->tail = eh->tail;
|
||||
} else {
|
||||
/* Issue errors */
|
||||
list_for_each_safe(et, etmp, eh->head) {
|
||||
if (et->true_type > worst)
|
||||
worst = et->true_type;
|
||||
nasm_issue_error(et);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Free the list, drop errors */
|
||||
list_for_each_safe(et, etmp, eh->head) {
|
||||
if (et->true_type > worst)
|
||||
worst = et->true_type;
|
||||
nasm_free_error(et);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
errhold_stack = eh->up;
|
||||
nasm_free(eh);
|
||||
return worst;
|
||||
}
|
||||
|
||||
/**
|
||||
* common error reporting
|
||||
* This is the common back end of the error reporting schemes currently
|
||||
* implemented. It prints the nature of the warning and then the
|
||||
* specific error message to erropt.file and may or may not return. It
|
||||
* doesn't return if the error severity is a "panic" or "debug" type.
|
||||
*
|
||||
* @param severity the severity of the warning or error
|
||||
* @param fmt the printf style format string
|
||||
*/
|
||||
void nasm_verror(errflags severity, const char *fmt, va_list args)
|
||||
{
|
||||
struct nasm_errtext *et;
|
||||
int c_errno = errno;
|
||||
errflags true_type = true_error_type(severity);
|
||||
|
||||
if (true_type >= ERR_CRITICAL) {
|
||||
nasm_verror_critical(severity, fmt, args);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (is_suppressed(severity))
|
||||
return;
|
||||
|
||||
nasm_new(et);
|
||||
et->c_errno = c_errno;
|
||||
et->severity = severity;
|
||||
et->true_type = true_type;
|
||||
et->msg = nasm_vasprintf(fmt, args);
|
||||
et->where = error_where(severity);
|
||||
|
||||
if (errhold_stack && true_type <= ERR_NONFATAL) {
|
||||
/* It is a tentative error */
|
||||
*errhold_stack->tail = et;
|
||||
errhold_stack->tail = &et->next;
|
||||
} else {
|
||||
nasm_issue_error(et);
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't do this before then, if we do, we lose messages in the list
|
||||
* file, as the list file is only generated in the last pass.
|
||||
*/
|
||||
if (skip_this_pass(severity))
|
||||
return;
|
||||
|
||||
if (!(severity & (ERR_HERE|ERR_PP_LISTMACRO)))
|
||||
pp_error_list_macros(severity);
|
||||
}
|
||||
|
||||
/*
|
||||
* Actually print, list and take action on an error
|
||||
*/
|
||||
static void nasm_issue_error(struct nasm_errtext *et)
|
||||
{
|
||||
const char *pfx;
|
||||
char warnsuf[64]; /* Warning suffix */
|
||||
char linestr[64]; /* Formatted line number if applicable */
|
||||
const errflags severity = et->severity;
|
||||
const errflags true_type = et->true_type;
|
||||
const struct src_location where = et->where;
|
||||
const char *cerrsep = "";
|
||||
const char *cerrmsg = "";
|
||||
bool buffer = true_type < ERR_NONFATAL || (severity & ERR_HOLD);
|
||||
|
||||
if (severity & ERR_NO_SEVERITY)
|
||||
pfx = "";
|
||||
else
|
||||
pfx = error_pfx(true_type);
|
||||
|
||||
*warnsuf = 0;
|
||||
if (!(severity & (ERR_HERE|ERR_PP_LISTMACRO))) {
|
||||
switch (severity & ERR_MASK) {
|
||||
case ERR_WARNING:
|
||||
{
|
||||
const unsigned int level = WARN_IDX(severity);
|
||||
snprintf(warnsuf, sizeof warnsuf, " [-w+%s%s]",
|
||||
(true_type >= ERR_NONFATAL) ? "error=" : "",
|
||||
warning_name[level]);
|
||||
break;
|
||||
}
|
||||
case ERR_DEBUG:
|
||||
snprintf(warnsuf, sizeof warnsuf, " [--debug=%u]", erropt.debug_nasm);
|
||||
break;
|
||||
case ERR_INFO:
|
||||
snprintf(warnsuf, sizeof warnsuf, " [--info=%u]", erropt.verbose_info);
|
||||
break;
|
||||
default:
|
||||
/* Not WARNING, DEBUG or INFO, not suppressible */
|
||||
break;
|
||||
}
|
||||
|
||||
if (severity & ERR_PERROR) {
|
||||
cerrsep = ":";
|
||||
cerrmsg = strerror(et->c_errno);
|
||||
}
|
||||
}
|
||||
|
||||
*linestr = 0;
|
||||
if (where.lineno) {
|
||||
snprintf(linestr, sizeof linestr, "%s%"PRId32"%s",
|
||||
errfmt->beforeline, where.lineno, errfmt->afterline);
|
||||
}
|
||||
|
||||
if (!skip_this_pass(severity)) {
|
||||
const char *file = where.filename ? where.filename : no_file_name;
|
||||
const char *here = "";
|
||||
|
||||
if (severity & ERR_HERE) {
|
||||
here = where.filename ? " here" : " in an unknown location";
|
||||
}
|
||||
|
||||
if (!warn_list)
|
||||
buffer = false;
|
||||
|
||||
if (buffer) {
|
||||
/*
|
||||
* Buffer up warnings and held errors until we either get
|
||||
* an error or we are on the code-generation pass.
|
||||
*/
|
||||
strlist_printf(warn_list, "%s%s%s%s%s%s%s%s%s",
|
||||
file, linestr, errfmt->beforemsg,
|
||||
pfx, et->msg, cerrsep, cerrmsg,
|
||||
here, warnsuf);
|
||||
} else {
|
||||
/*
|
||||
* Actually output an error. If we have buffered
|
||||
* warnings, and this is a non-warning, output them now.
|
||||
*/
|
||||
if (warn_list) {
|
||||
strlist_write(warn_list, "\n", erropt.file);
|
||||
strlist_free(&warn_list);
|
||||
}
|
||||
|
||||
fprintf(erropt.file, "%s%s%s%s%s%s%s%s%s\n",
|
||||
file, linestr, errfmt->beforemsg,
|
||||
pfx, et->msg, cerrsep, cerrmsg,
|
||||
here, warnsuf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Are we recursing from error_list_macros? */
|
||||
if (severity & ERR_PP_LISTMACRO)
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* Don't suppress this with skip_this_pass(), or we don't get
|
||||
* pass1 or preprocessor warnings in the list file
|
||||
*/
|
||||
if (severity & ERR_HERE) {
|
||||
if (where.lineno)
|
||||
lfmt->error(severity, "%s%s at %s:%"PRId32"%s",
|
||||
pfx, et->msg, where.filename, where.lineno, warnsuf);
|
||||
else if (where.filename)
|
||||
lfmt->error(severity, "%s%s in file %s%s",
|
||||
pfx, et->msg, where.filename, warnsuf);
|
||||
else
|
||||
lfmt->error(severity, "%s%s in an unknown location%s",
|
||||
pfx, et->msg, warnsuf);
|
||||
} else {
|
||||
lfmt->error(severity, "%s%s%s", pfx, et->msg, warnsuf);
|
||||
}
|
||||
|
||||
if (skip_this_pass(severity))
|
||||
goto done;
|
||||
|
||||
if (true_type >= ERR_FATAL) {
|
||||
die_hard(true_type, severity);
|
||||
} else if (!buffer) {
|
||||
if (true_type > erropt.worst)
|
||||
erropt.worst = true_type;
|
||||
|
||||
if (true_type >= ERR_NONFATAL)
|
||||
erropt.never |= ERR_UNDEAD;
|
||||
}
|
||||
|
||||
done:
|
||||
nasm_free_error(et);
|
||||
}
|
||||
|
||||
|
||||
int set_error_format(const char *fmt)
|
||||
{
|
||||
if (!nasm_stricmp("vc", fmt) ||
|
||||
!nasm_stricmp("msvc", fmt) ||
|
||||
!nasm_stricmp("ms", fmt))
|
||||
errfmt = &errfmts[ERRFMT_MSVC];
|
||||
else if (!nasm_stricmp("gnu", fmt) ||
|
||||
!nasm_stricmp("gcc", fmt))
|
||||
errfmt = &errfmts[ERRFMT_GNU];
|
||||
else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(erropt.file,
|
||||
"Usage: %s [-@ response_file] [options...] [--] filename\n"
|
||||
" For additional help:\n"
|
||||
" %s -h [run|topics|all|-option]\n",
|
||||
_progname, _progname);
|
||||
}
|
||||
|
||||
void warn_dollar_hex(void)
|
||||
{
|
||||
nasm_warn(WARN_NUMBER_DEPRECATED_HEX,
|
||||
"$ prefix for hexadecimal is deprecated");
|
||||
}
|
||||
|
||||
628
asm/nasm.c
628
asm/nasm.c
@@ -27,6 +27,7 @@
|
||||
#include "iflag.h"
|
||||
#include "quote.h"
|
||||
#include "ver.h"
|
||||
#include "error.h"
|
||||
|
||||
/*
|
||||
* This is the maximum number of optimization passes to do. If we ever
|
||||
@@ -45,22 +46,8 @@ const char *_progname;
|
||||
static void open_and_process_respfile(char *, int);
|
||||
static void parse_cmdline(int, char **, int);
|
||||
static void assemble_file(const char *, struct strlist *);
|
||||
static bool skip_this_pass(errflags severity);
|
||||
static void usage(void);
|
||||
static void help(FILE *out, const char *what);
|
||||
|
||||
struct error_format {
|
||||
const char *beforeline; /* Before line number, if present */
|
||||
const char *afterline; /* After line number, if present */
|
||||
const char *beforemsg; /* Before actual message */
|
||||
};
|
||||
|
||||
static const struct error_format errfmt_gnu = { ":", "", ": " };
|
||||
static const struct error_format errfmt_msvc = { "(", ")", " : " };
|
||||
static const struct error_format *errfmt = &errfmt_gnu;
|
||||
static struct strlist *warn_list;
|
||||
static struct nasm_errhold *errhold_stack;
|
||||
|
||||
static bool using_debug_info;
|
||||
static const char *debug_format;
|
||||
|
||||
@@ -91,7 +78,6 @@ const struct ofmt *ofmt = &OF_DEFAULT;
|
||||
const struct ofmt_alias *ofmt_alias = NULL;
|
||||
const struct dfmt *dfmt;
|
||||
|
||||
static FILE *error_file; /* Where to write error messages */
|
||||
errflags errflags_never = 0; /* Error flags to unconditionally suppress */
|
||||
|
||||
FILE *ofile = NULL;
|
||||
@@ -125,8 +111,10 @@ static const char *depend_target = NULL;
|
||||
static const char *depend_file = NULL;
|
||||
struct strlist *depend_list;
|
||||
|
||||
static bool want_usage;
|
||||
static bool terminate_after_phase;
|
||||
static inline bool terminate_after_phase(void)
|
||||
{
|
||||
return erropt.worst >= ERR_NONFATAL;
|
||||
}
|
||||
|
||||
static char *quote_for_pmake(const char *str);
|
||||
static char *quote_for_wmake(const char *str);
|
||||
@@ -481,7 +469,7 @@ static void timestamp(void)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* Do these as early as possible */
|
||||
error_file = stderr;
|
||||
erropt.file = stderr;
|
||||
_progname = argv[0];
|
||||
if (!_progname || !_progname[0])
|
||||
_progname = "nasm";
|
||||
@@ -495,11 +483,10 @@ int main(int argc, char **argv)
|
||||
|
||||
include_path = strlist_alloc(true);
|
||||
|
||||
reset_global_defaults(0);
|
||||
_pass_type = PASS_INIT;
|
||||
_passn = 0;
|
||||
|
||||
want_usage = terminate_after_phase = false;
|
||||
|
||||
nasm_ctype_init();
|
||||
src_init();
|
||||
|
||||
@@ -516,11 +503,8 @@ int main(int argc, char **argv)
|
||||
operating_mode = OP_NORMAL;
|
||||
|
||||
parse_cmdline(argc, argv, 1);
|
||||
if (terminate_after_phase) {
|
||||
if (want_usage)
|
||||
usage();
|
||||
if (terminate_after_phase())
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* At this point we have ofmt and the name of the desired debug format */
|
||||
if (!using_debug_info) {
|
||||
@@ -545,14 +529,11 @@ int main(int argc, char **argv)
|
||||
preproc_init(include_path);
|
||||
|
||||
parse_cmdline(argc, argv, 2);
|
||||
if (terminate_after_phase) {
|
||||
if (want_usage)
|
||||
usage();
|
||||
if (terminate_after_phase())
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Save away the default state of warnings */
|
||||
init_warnings();
|
||||
error_init();
|
||||
|
||||
/* Dependency filename if we are also doing other things */
|
||||
if (!depend_file && (operating_mode & ~OP_DEPEND)) {
|
||||
@@ -580,9 +561,13 @@ int main(int argc, char **argv)
|
||||
if (!depend_target)
|
||||
depend_target = quote_for_make(outname);
|
||||
|
||||
reset_global_defaults(cmd_sb);
|
||||
|
||||
if (!(operating_mode & (OP_PREPROCESS|OP_NORMAL))) {
|
||||
char *line;
|
||||
|
||||
error_pass_start(true);
|
||||
|
||||
if (depend_missing_ok)
|
||||
pp_include_path(NULL); /* "assume generated" */
|
||||
|
||||
@@ -591,29 +576,28 @@ int main(int argc, char **argv)
|
||||
while ((line = pp_getline()))
|
||||
nasm_free(line);
|
||||
pp_cleanup_pass();
|
||||
reset_warnings();
|
||||
error_pass_end();
|
||||
} else if (operating_mode & OP_PREPROCESS) {
|
||||
char *line;
|
||||
const char *file_name = NULL;
|
||||
char *quoted_file_name = nasm_quote_filename(file_name);
|
||||
int32_t linnum = 0;
|
||||
int32_t lineinc = 0;
|
||||
FILE *out;
|
||||
|
||||
if (outname) {
|
||||
ofile = nasm_open_write(outname, NF_TEXT);
|
||||
if (!ofile)
|
||||
nasm_fatal("unable to open output file `%s'", outname);
|
||||
out = ofile;
|
||||
nasm_fatalf(ERR_PERROR,
|
||||
"unable to open output file `%s'", outname);
|
||||
} else {
|
||||
ofile = NULL;
|
||||
out = stdout;
|
||||
ofile = stdout;
|
||||
}
|
||||
|
||||
location.known = false;
|
||||
|
||||
_pass_type = PASS_PREPROC;
|
||||
pp_reset(inname, PP_PREPROC, depend_list);
|
||||
error_pass_start(true);
|
||||
|
||||
while ((line = pp_getline())) {
|
||||
/*
|
||||
@@ -629,7 +613,7 @@ int main(int argc, char **argv)
|
||||
} else if (lineinc) {
|
||||
if (linnum + lineinc == where.lineno) {
|
||||
/* Add one blank line to account for increment */
|
||||
fputc('\n', out);
|
||||
fputc('\n', ofile);
|
||||
linnum += lineinc;
|
||||
} else if (linnum - lineinc == where.lineno) {
|
||||
/*
|
||||
@@ -649,60 +633,49 @@ int main(int argc, char **argv)
|
||||
continue;
|
||||
|
||||
if (linnum != where.lineno) {
|
||||
fprintf(out, "%%line %"PRId32"%+"PRId32" %s\n",
|
||||
fprintf(ofile, "%%line %"PRId32"%+"PRId32" %s\n",
|
||||
where.lineno, lineinc, quoted_file_name);
|
||||
}
|
||||
linnum = where.lineno + lineinc;
|
||||
|
||||
fputs(line, out);
|
||||
fputc('\n', out);
|
||||
fputs(line, ofile);
|
||||
fputc('\n', ofile);
|
||||
}
|
||||
|
||||
nasm_free(quoted_file_name);
|
||||
|
||||
pp_cleanup_pass();
|
||||
reset_warnings();
|
||||
if (ofile)
|
||||
fclose(ofile);
|
||||
if (ofile && terminate_after_phase && !keep_all)
|
||||
remove(outname);
|
||||
ofile = NULL;
|
||||
error_pass_end();
|
||||
close_output(terminate_after_phase());
|
||||
}
|
||||
|
||||
if (operating_mode & OP_NORMAL) {
|
||||
ofile = nasm_open_write(outname, (ofmt->flags & OFMT_TEXT) ? NF_TEXT : NF_BINARY);
|
||||
if (!ofile)
|
||||
nasm_fatal("unable to open output file `%s'", outname);
|
||||
nasm_fatalf(ERR_PERROR, "unable to open output file `%s'", outname);
|
||||
|
||||
ofmt->init();
|
||||
dfmt->init();
|
||||
|
||||
assemble_file(inname, depend_list);
|
||||
|
||||
if (!terminate_after_phase) {
|
||||
if (!terminate_after_phase()) {
|
||||
ofmt->cleanup();
|
||||
cleanup_labels();
|
||||
fflush(ofile);
|
||||
if (ferror(ofile))
|
||||
nasm_nonfatal("write error on output file `%s'", outname);
|
||||
nasm_nonfatalf(ERR_PERROR,
|
||||
"write error on output file `%s'", outname);
|
||||
}
|
||||
|
||||
if (ofile) {
|
||||
fclose(ofile);
|
||||
if (terminate_after_phase && !keep_all)
|
||||
remove(outname);
|
||||
ofile = NULL;
|
||||
}
|
||||
close_output(terminate_after_phase());
|
||||
}
|
||||
|
||||
pp_cleanup_session();
|
||||
|
||||
if (depend_list && !terminate_after_phase)
|
||||
if (depend_list && !terminate_after_phase())
|
||||
emit_dependencies(depend_list);
|
||||
|
||||
if (want_usage)
|
||||
usage();
|
||||
|
||||
raa_free(offsets);
|
||||
saa_free(forwrefs);
|
||||
eval_cleanup();
|
||||
@@ -710,7 +683,7 @@ int main(int argc, char **argv)
|
||||
src_free();
|
||||
strlist_free(&include_path);
|
||||
|
||||
return terminate_after_phase;
|
||||
return terminate_after_phase();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -984,7 +957,7 @@ static bool process_arg(char *p, char *q, int pass)
|
||||
break;
|
||||
case 's':
|
||||
if (pass == 1)
|
||||
error_file = stdout;
|
||||
erropt.file = stdout;
|
||||
break;
|
||||
|
||||
case 'o': /* output file */
|
||||
@@ -1030,7 +1003,7 @@ static bool process_arg(char *p, char *q, int pass)
|
||||
case 'v':
|
||||
case '+':
|
||||
param++;
|
||||
opt_verbose_info++;
|
||||
erropt.verbose_info++;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
@@ -1039,7 +1012,8 @@ static bool process_arg(char *p, char *q, int pass)
|
||||
break;
|
||||
|
||||
default:
|
||||
nasm_fatal("unknown optimization option -O%c\n",
|
||||
nasm_fatalf(ERR_USAGE,
|
||||
"unknown optimization option -O%c\n",
|
||||
*param);
|
||||
break;
|
||||
}
|
||||
@@ -1098,17 +1072,11 @@ static bool process_arg(char *p, char *q, int pass)
|
||||
|
||||
case 'X': /* specify error reporting format */
|
||||
if (pass == 1) {
|
||||
if (!nasm_stricmp("vc", param) ||
|
||||
!nasm_stricmp("msvc", param) ||
|
||||
!nasm_stricmp("ms", param))
|
||||
errfmt = &errfmt_msvc;
|
||||
else if (!nasm_stricmp("gnu", param) ||
|
||||
!nasm_stricmp("gcc", param))
|
||||
errfmt = &errfmt_gnu;
|
||||
else
|
||||
if (set_error_format(param)) {
|
||||
nasm_fatalf(ERR_USAGE,
|
||||
"unrecognized error reporting format `%s'",
|
||||
param);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1326,13 +1294,13 @@ static bool process_arg(char *p, char *q, int pass)
|
||||
break;
|
||||
case OPT_DEBUG:
|
||||
if (pass == 1)
|
||||
debug_nasm = param ?
|
||||
strtoul(param, NULL, 10) : debug_nasm+1;
|
||||
erropt.debug_nasm = param ?
|
||||
strtoul(param, NULL, 10) : erropt.debug_nasm+1;
|
||||
break;
|
||||
case OPT_INFO:
|
||||
if (pass == 1)
|
||||
opt_verbose_info = param ?
|
||||
strtoul(param, NULL, 10) : opt_verbose_info+1;
|
||||
erropt.verbose_info = param ?
|
||||
strtoul(param, NULL, 10) : erropt.verbose_info+1;
|
||||
break;
|
||||
case OPT_REPRODUCIBLE:
|
||||
reproducible = true;
|
||||
@@ -1476,7 +1444,7 @@ static void open_and_process_respfile(char *respfile, int pass)
|
||||
process_respfile(rfile, pass);
|
||||
fclose(rfile);
|
||||
} else {
|
||||
nasm_nonfatalf(ERR_USAGE, "unable to open response file `%s'", respfile);
|
||||
nasm_fatalf(ERR_PERROR, "unable to open response file `%s'", respfile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1536,13 +1504,15 @@ static void parse_cmdline(int argc, char **argv, int pass)
|
||||
(outname && !strcmp(inname, outname)) ||
|
||||
(listname && !strcmp(inname, listname)) ||
|
||||
(depend_file && !strcmp(inname, depend_file)))
|
||||
nasm_fatalf(ERR_USAGE, "will not overwrite input file");
|
||||
nasm_fatal("will not overwrite input file");
|
||||
|
||||
if (errname) {
|
||||
error_file = nasm_open_write(errname, NF_TEXT);
|
||||
if (!error_file) {
|
||||
error_file = stderr; /* Revert to default! */
|
||||
nasm_fatalf(ERR_USAGE, "cannot open file `%s' for error messages", errname);
|
||||
FILE *error_file = nasm_open_write(errname, NF_TEXT);
|
||||
if (erropt.file) {
|
||||
erropt.file = error_file;
|
||||
} else {
|
||||
nasm_fatalf(ERR_PERROR, "cannot open file `%s' for error messages",
|
||||
errname);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1579,10 +1549,10 @@ static void forward_refs(insn *instruction)
|
||||
}
|
||||
}
|
||||
|
||||
static void print_pass_report(bool failure)
|
||||
void print_final_report(bool failure)
|
||||
{
|
||||
/* This test is here to reduce the likelihood of a recursive failure */
|
||||
if (unlikely(opt_verbose_info >= 1)) {
|
||||
if (unlikely(erropt.verbose_info >= 1)) {
|
||||
enum pass_type t = pass_type();
|
||||
|
||||
if (t >= PASS_FIRST) {
|
||||
@@ -1624,7 +1594,7 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
|
||||
remove(listname);
|
||||
}
|
||||
|
||||
while (!terminate_after_phase && !pass_final()) {
|
||||
while (!terminate_after_phase() && !pass_final()) {
|
||||
_passn++;
|
||||
switch (pass_type()) {
|
||||
case PASS_INIT:
|
||||
@@ -1639,30 +1609,15 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
|
||||
break;
|
||||
}
|
||||
|
||||
error_pass_start(pass_final());
|
||||
global_offset_changed = 0;
|
||||
|
||||
/*
|
||||
* Create a warning buffer list unless we are in
|
||||
* pass 2 (everything will be emitted immediately in pass 2.)
|
||||
*/
|
||||
if (warn_list) {
|
||||
if (warn_list->nstr || pass_final())
|
||||
strlist_free(&warn_list);
|
||||
}
|
||||
|
||||
if (!pass_final() && !warn_list)
|
||||
warn_list = strlist_alloc(false);
|
||||
|
||||
/* Suppress ERR_PASS2 unless we are actually in the final pass */
|
||||
errflags_never = 0;
|
||||
erropt.never = 0;
|
||||
if (!pass_final())
|
||||
errflags_never |= ERR_PASS2;
|
||||
erropt.never |= ERR_PASS2;
|
||||
|
||||
globl.bits = cmd_sb; /* set 'bits' to command line default */
|
||||
globl.bnd = false;
|
||||
globl.rel = 0;
|
||||
globl.reldef = EAF_FS|EAF_GS; /* For now, don't warn on fs:/gs: absolute */
|
||||
globl.dollarhex = true;
|
||||
reset_global_defaults(cmd_sb);
|
||||
|
||||
cpu = cmd_cpu;
|
||||
if (listname) {
|
||||
@@ -1723,9 +1678,6 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
|
||||
|
||||
pp_cleanup_pass();
|
||||
|
||||
/* We better not be having an error hold still... */
|
||||
nasm_assert(!errhold_stack);
|
||||
|
||||
if (global_offset_changed) {
|
||||
switch (pass_type()) {
|
||||
case PASS_OPT:
|
||||
@@ -1770,473 +1722,27 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
|
||||
}
|
||||
}
|
||||
|
||||
reset_warnings();
|
||||
error_pass_end();
|
||||
}
|
||||
|
||||
if (terminate_after_phase || pass_final())
|
||||
print_pass_report(terminate_after_phase);
|
||||
print_final_report(terminate_after_phase());
|
||||
|
||||
lfmt->cleanup();
|
||||
strlist_free(&warn_list);
|
||||
}
|
||||
|
||||
static bool skip_this_pass(errflags severity)
|
||||
void close_output(bool error)
|
||||
{
|
||||
errflags type = severity & ERR_MASK;
|
||||
|
||||
/*
|
||||
* See if it's a pass-specific error or warning which should be skipped.
|
||||
* We can never skip fatal errors as by definition they cannot be
|
||||
* resumed from.
|
||||
*/
|
||||
if (type >= ERR_FATAL)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* ERR_LISTMSG and ERR_NOTE messages are always skipped; the list
|
||||
* file receives them anyway as this function is not consulted for
|
||||
* sending to the list file.
|
||||
*/
|
||||
if (type <= ERR_NOTE)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* This message is not applicable unless it is the last pass we
|
||||
* are going to execute; this can be either the final
|
||||
* code-generation pass or the single pass executed in
|
||||
* preproc-only mode.
|
||||
*/
|
||||
return (severity & ERR_PASS2) && !pass_final_or_preproc();
|
||||
}
|
||||
|
||||
/**
|
||||
* check for suppressed message (usually warnings or notes)
|
||||
*
|
||||
* @param severity the severity of the warning or error
|
||||
* @return true if we should abort error/warning printing
|
||||
*/
|
||||
static bool is_suppressed(errflags flags)
|
||||
{
|
||||
const errflags severity = flags & ERR_MASK;
|
||||
const errflags level = WARN_IDX(flags);
|
||||
|
||||
if (severity >= ERR_FATAL) {
|
||||
/* Fatal errors or higher can never be suppressed */
|
||||
return false;
|
||||
}
|
||||
|
||||
if (flags & errflags_never)
|
||||
return true;
|
||||
|
||||
switch (severity) {
|
||||
case ERR_WARNING:
|
||||
if (!(warning_state[level] & WARN_ST_ENABLED))
|
||||
return true;
|
||||
break;
|
||||
|
||||
case ERR_INFO:
|
||||
if (!info_level(level))
|
||||
return true;
|
||||
break;
|
||||
|
||||
case ERR_DEBUG:
|
||||
if (!debug_level(level))
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Suppressed by the preprocessor? */
|
||||
if (!(flags & ERR_PP_LISTMACRO))
|
||||
return pp_suppress_error(flags);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the true error type (the ERR_MASK part) of the given
|
||||
* severity, accounting for warnings that may need to be promoted to
|
||||
* error.
|
||||
*
|
||||
* @param severity the severity of the warning or error
|
||||
* @return true if we should error out
|
||||
*/
|
||||
static errflags pure_func true_error_type(errflags severity)
|
||||
{
|
||||
const uint8_t warn_is_err = WARN_ST_ENABLED|WARN_ST_ERROR;
|
||||
int type;
|
||||
|
||||
type = severity & ERR_MASK;
|
||||
|
||||
if (type == ERR_WARNING) {
|
||||
/* Promote warning to error? */
|
||||
uint8_t state = warning_state[WARN_IDX(severity)];
|
||||
if ((state & warn_is_err) == warn_is_err)
|
||||
type = ERR_NONFATAL;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static const char no_file_name[] = "nasm"; /* What to print if no file name */
|
||||
|
||||
/*
|
||||
* For fatal/critical/panic errors, kill this process.
|
||||
*
|
||||
* For FATAL errors doing cleanups, tidying up the list process,
|
||||
* and so in is acceptable.
|
||||
*
|
||||
* For CRITICAL errors, minimize dependencies on memory allocation
|
||||
* and/or having a system valid state.
|
||||
*
|
||||
* For PANIC, if abort_on_panic is set, abort without any other action.
|
||||
*/
|
||||
static_fatal_func die_hard(errflags true_type, errflags severity)
|
||||
{
|
||||
if (true_type < ERR_PANIC || !abort_on_panic) {
|
||||
if (true_type < ERR_CRITICAL) {
|
||||
/* FATAL shutdown, general cleanup actions are valid */
|
||||
print_pass_report(true);
|
||||
lfmt->cleanup();
|
||||
}
|
||||
|
||||
fflush(NULL);
|
||||
|
||||
if (ofile) {
|
||||
fclose(ofile);
|
||||
if (!keep_all)
|
||||
remove(outname);
|
||||
ofile = NULL;
|
||||
}
|
||||
|
||||
if (severity & ERR_USAGE)
|
||||
usage();
|
||||
|
||||
/* Terminate immediately (exit closes any still open files) */
|
||||
exit(true_type - ERR_FATAL + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* abort() shouldn't ever return, but be paranoid about this,
|
||||
* plus it helps some compilers clue in to the fact that this
|
||||
* function can never, ever return.
|
||||
*/
|
||||
while (1)
|
||||
abort();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the struct src_location appropriate for use, after some
|
||||
* potential filename mangling.
|
||||
*/
|
||||
static struct src_location error_where(errflags severity)
|
||||
{
|
||||
struct src_location where;
|
||||
|
||||
if (severity & ERR_NOFILE) {
|
||||
where.filename = NULL;
|
||||
where.lineno = 0;
|
||||
} else {
|
||||
where = src_where_error();
|
||||
|
||||
if (!where.filename) {
|
||||
where.filename =
|
||||
inname && inname[0] ? inname :
|
||||
outname && outname[0] ? outname :
|
||||
NULL;
|
||||
where.lineno = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return where;
|
||||
}
|
||||
|
||||
/*
|
||||
* error reporting for critical and panic errors: minimize
|
||||
* the amount of system dependencies for getting a message out,
|
||||
* and in particular try to avoid memory allocations.
|
||||
*/
|
||||
fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list args)
|
||||
{
|
||||
struct src_location where;
|
||||
errflags true_type = severity & ERR_MASK;
|
||||
static bool been_here = false;
|
||||
|
||||
while (unlikely(been_here))
|
||||
abort(); /* Recursive critical error... just die */
|
||||
|
||||
been_here = true;
|
||||
|
||||
where = error_where(severity);
|
||||
if (!where.filename)
|
||||
where.filename = no_file_name;
|
||||
|
||||
fputs(error_pfx(severity), error_file);
|
||||
fputs(where.filename, error_file);
|
||||
if (where.lineno) {
|
||||
fprintf(error_file, "%s%"PRId32"%s",
|
||||
errfmt->beforeline, where.lineno, errfmt->afterline);
|
||||
}
|
||||
fputs(errfmt->beforemsg, error_file);
|
||||
vfprintf(error_file, fmt, args);
|
||||
fputc('\n', error_file);
|
||||
|
||||
die_hard(true_type, severity);
|
||||
unreachable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stack of tentative error hold lists.
|
||||
*/
|
||||
struct nasm_errtext {
|
||||
struct nasm_errtext *next;
|
||||
char *msg; /* Owned by this structure */
|
||||
struct src_location where; /* Owned by the srcfile system */
|
||||
errflags severity;
|
||||
errflags true_type;
|
||||
};
|
||||
struct nasm_errhold {
|
||||
struct nasm_errhold *up;
|
||||
struct nasm_errtext *head, **tail;
|
||||
};
|
||||
|
||||
static void nasm_free_error(struct nasm_errtext *et)
|
||||
{
|
||||
nasm_free(et->msg);
|
||||
nasm_free(et);
|
||||
}
|
||||
|
||||
static void nasm_issue_error(struct nasm_errtext *et);
|
||||
|
||||
struct nasm_errhold *nasm_error_hold_push(void)
|
||||
{
|
||||
struct nasm_errhold *eh;
|
||||
|
||||
nasm_new(eh);
|
||||
eh->up = errhold_stack;
|
||||
eh->tail = &eh->head;
|
||||
errhold_stack = eh;
|
||||
|
||||
return eh;
|
||||
}
|
||||
|
||||
/* Pop an error hold. Returns the highest severity issued or dropped. */
|
||||
errflags nasm_error_hold_pop(struct nasm_errhold *eh, bool issue)
|
||||
{
|
||||
struct nasm_errtext *et, *etmp;
|
||||
errflags worst = 0;
|
||||
|
||||
/*
|
||||
* Allow calling with a null argument saying no hold in the first place.
|
||||
*/
|
||||
if (!eh)
|
||||
return worst;
|
||||
|
||||
/* This *must* be the current top of the errhold stack */
|
||||
nasm_assert(eh == errhold_stack);
|
||||
|
||||
if (eh->head) {
|
||||
if (issue) {
|
||||
if (eh->up) {
|
||||
/* Commit the current hold list to the previous level */
|
||||
*eh->up->tail = eh->head;
|
||||
eh->up->tail = eh->tail;
|
||||
} else {
|
||||
/* Issue errors */
|
||||
list_for_each_safe(et, etmp, eh->head) {
|
||||
if (et->true_type > worst)
|
||||
worst = et->true_type;
|
||||
nasm_issue_error(et);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Free the list, drop errors */
|
||||
list_for_each_safe(et, etmp, eh->head) {
|
||||
if (et->true_type > worst)
|
||||
worst = et->true_type;
|
||||
nasm_free_error(et);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
errhold_stack = eh->up;
|
||||
nasm_free(eh);
|
||||
return worst;
|
||||
}
|
||||
|
||||
/**
|
||||
* common error reporting
|
||||
* This is the common back end of the error reporting schemes currently
|
||||
* implemented. It prints the nature of the warning and then the
|
||||
* specific error message to error_file and may or may not return. It
|
||||
* doesn't return if the error severity is a "panic" or "debug" type.
|
||||
*
|
||||
* @param severity the severity of the warning or error
|
||||
* @param fmt the printf style format string
|
||||
*/
|
||||
void nasm_verror(errflags severity, const char *fmt, va_list args)
|
||||
{
|
||||
struct nasm_errtext *et;
|
||||
errflags true_type = true_error_type(severity);
|
||||
|
||||
if (true_type >= ERR_CRITICAL) {
|
||||
nasm_verror_critical(severity, fmt, args);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (is_suppressed(severity))
|
||||
if (!ofile)
|
||||
return;
|
||||
|
||||
nasm_new(et);
|
||||
et->severity = severity;
|
||||
et->true_type = true_type;
|
||||
et->msg = nasm_vasprintf(fmt, args);
|
||||
et->where = error_where(severity);
|
||||
|
||||
if (errhold_stack && true_type <= ERR_NONFATAL) {
|
||||
/* It is a tentative error */
|
||||
*errhold_stack->tail = et;
|
||||
errhold_stack->tail = &et->next;
|
||||
if (ofile == stdout || ofile == stdin) {
|
||||
fflush(ofile);
|
||||
} else {
|
||||
nasm_issue_error(et);
|
||||
fclose(ofile);
|
||||
if (error && !keep_all)
|
||||
remove(outname);
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't do this before then, if we do, we lose messages in the list
|
||||
* file, as the list file is only generated in the last pass.
|
||||
*/
|
||||
if (skip_this_pass(severity))
|
||||
return;
|
||||
|
||||
if (!(severity & (ERR_HERE|ERR_PP_LISTMACRO)))
|
||||
pp_error_list_macros(severity);
|
||||
}
|
||||
|
||||
/*
|
||||
* Actually print, list and take action on an error
|
||||
*/
|
||||
static void nasm_issue_error(struct nasm_errtext *et)
|
||||
{
|
||||
const char *pfx;
|
||||
char warnsuf[64]; /* Warning suffix */
|
||||
char linestr[64]; /* Formatted line number if applicable */
|
||||
const errflags severity = et->severity;
|
||||
const errflags true_type = et->true_type;
|
||||
const struct src_location where = et->where;
|
||||
bool buffer = true_type < ERR_NONFATAL || (severity & ERR_HOLD);
|
||||
|
||||
if (severity & ERR_NO_SEVERITY)
|
||||
pfx = "";
|
||||
else
|
||||
pfx = error_pfx(true_type);
|
||||
|
||||
*warnsuf = 0;
|
||||
if (!(severity & (ERR_HERE|ERR_PP_LISTMACRO))) {
|
||||
const unsigned int level = WARN_IDX(severity);
|
||||
|
||||
switch (severity & ERR_MASK) {
|
||||
case ERR_WARNING:
|
||||
snprintf(warnsuf, sizeof warnsuf, " [-w+%s%s]",
|
||||
(true_type >= ERR_NONFATAL) ? "error=" : "",
|
||||
warning_name[level]);
|
||||
break;
|
||||
case ERR_DEBUG:
|
||||
snprintf(warnsuf, sizeof warnsuf, " [--debug=%u]", debug_nasm);
|
||||
break;
|
||||
case ERR_INFO:
|
||||
snprintf(warnsuf, sizeof warnsuf, " [--info=%u]", opt_verbose_info);
|
||||
break;
|
||||
default:
|
||||
/* Not WARNING, DEBUG or INFO, not suppressible */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*linestr = 0;
|
||||
if (where.lineno) {
|
||||
snprintf(linestr, sizeof linestr, "%s%"PRId32"%s",
|
||||
errfmt->beforeline, where.lineno, errfmt->afterline);
|
||||
}
|
||||
|
||||
if (!skip_this_pass(severity)) {
|
||||
const char *file = where.filename ? where.filename : no_file_name;
|
||||
const char *here = "";
|
||||
|
||||
if (severity & ERR_HERE) {
|
||||
here = where.filename ? " here" : " in an unknown location";
|
||||
}
|
||||
|
||||
if (!warn_list)
|
||||
buffer = false;
|
||||
|
||||
if (buffer) {
|
||||
/*
|
||||
* Buffer up warnings and held errors until we either get
|
||||
* an error or we are on the code-generation pass.
|
||||
*/
|
||||
strlist_printf(warn_list, "%s%s%s%s%s%s%s",
|
||||
file, linestr, errfmt->beforemsg,
|
||||
pfx, et->msg, here, warnsuf);
|
||||
} else {
|
||||
/*
|
||||
* Actually output an error. If we have buffered
|
||||
* warnings, and this is a non-warning, output them now.
|
||||
*/
|
||||
if (warn_list) {
|
||||
strlist_write(warn_list, "\n", error_file);
|
||||
strlist_free(&warn_list);
|
||||
}
|
||||
|
||||
fprintf(error_file, "%s%s%s%s%s%s%s\n",
|
||||
file, linestr, errfmt->beforemsg,
|
||||
pfx, et->msg, here, warnsuf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Are we recursing from error_list_macros? */
|
||||
if (severity & ERR_PP_LISTMACRO)
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* Don't suppress this with skip_this_pass(), or we don't get
|
||||
* pass1 or preprocessor warnings in the list file
|
||||
*/
|
||||
if (severity & ERR_HERE) {
|
||||
if (where.lineno)
|
||||
lfmt->error(severity, "%s%s at %s:%"PRId32"%s",
|
||||
pfx, et->msg, where.filename, where.lineno, warnsuf);
|
||||
else if (where.filename)
|
||||
lfmt->error(severity, "%s%s in file %s%s",
|
||||
pfx, et->msg, where.filename, warnsuf);
|
||||
else
|
||||
lfmt->error(severity, "%s%s in an unknown location%s",
|
||||
pfx, et->msg, warnsuf);
|
||||
} else {
|
||||
lfmt->error(severity, "%s%s%s", pfx, et->msg, warnsuf);
|
||||
}
|
||||
|
||||
if (skip_this_pass(severity))
|
||||
goto done;
|
||||
|
||||
if (true_type >= ERR_FATAL) {
|
||||
die_hard(true_type, severity);
|
||||
} else if (true_type >= ERR_NONFATAL && !buffer) {
|
||||
terminate_after_phase = true;
|
||||
errflags_never |= ERR_UNDEAD;
|
||||
}
|
||||
|
||||
done:
|
||||
nasm_free_error(et);
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(error_file,
|
||||
"Usage: %s [-@ response_file] [options...] [--] filename\n"
|
||||
" For additional help:\n"
|
||||
" %s -h [run|topics|all|-option]\n",
|
||||
_progname, _progname);
|
||||
ofile = NULL;
|
||||
}
|
||||
|
||||
enum help_with {
|
||||
|
||||
@@ -199,6 +199,7 @@ if ($what eq 'c') {
|
||||
print $out " const char *name;\n";
|
||||
print $out " enum warn_index warning;\n";
|
||||
print $out "};\n\n";
|
||||
printf $out "#define NUM_WARNINGS %d\n", $#warn_noall + 2;
|
||||
printf $out "#define NUM_WARNING_ALIAS %d\n", scalar(keys %aliases);
|
||||
|
||||
printf $out "extern const char * const warning_name[%d];\n",
|
||||
@@ -206,10 +207,8 @@ if ($what eq 'c') {
|
||||
printf $out "extern const char * const warning_help[%d];\n",
|
||||
$#warnings + 2;
|
||||
print $out "extern const struct warning_alias warning_alias[NUM_WARNING_ALIAS];\n";
|
||||
printf $out "extern const uint8_t warning_default[%d];\n",
|
||||
$#warn_noall + 2;
|
||||
printf $out "extern uint8_t warning_state[%d];\n",
|
||||
$#warn_noall + 2;
|
||||
printf $out "extern const uint8_t warning_default[NUM_WARNINGS];\n",
|
||||
printf $out "extern uint8_t warning_state[NUM_WARNINGS];\n",
|
||||
print $out "\n#endif /* $guard */\n";
|
||||
} elsif ($what eq 'doc') {
|
||||
my %wsec = ('on' => [], 'off' => [], 'err' => [],
|
||||
|
||||
@@ -15,6 +15,15 @@
|
||||
*/
|
||||
struct globalopt globl;
|
||||
|
||||
void reset_global_defaults(int bits)
|
||||
{
|
||||
globl.bits = bits;
|
||||
globl.bnd = false;
|
||||
globl.rel = 0;
|
||||
globl.reldef = EAF_FS|EAF_GS;
|
||||
globl.dollarhex = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Name of a register token, if applicable; otherwise NULL
|
||||
*/
|
||||
|
||||
109
common/errstubs.c
Normal file
109
common/errstubs.c
Normal file
@@ -0,0 +1,109 @@
|
||||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
/* Copyright 1996-2025 The NASM Authors - All Rights Reserved */
|
||||
|
||||
#include "compiler.h"
|
||||
#include "nasmlib.h"
|
||||
#include "error.h"
|
||||
|
||||
struct errinfo erropt;
|
||||
|
||||
/* Common function body */
|
||||
#define nasm_do_error(_sev,_flags) \
|
||||
do { \
|
||||
const errflags nde_severity = (_sev); \
|
||||
const errflags nde_flags = nde_severity | (_flags); \
|
||||
va_list ap; \
|
||||
va_start(ap, fmt); \
|
||||
if (nde_severity >= ERR_CRITICAL) { \
|
||||
nasm_verror_critical(nde_flags, fmt, ap); \
|
||||
unreachable(); \
|
||||
} else { \
|
||||
nasm_verror(nde_flags, fmt, ap); \
|
||||
if (nde_severity >= ERR_FATAL) \
|
||||
unreachable(); \
|
||||
} \
|
||||
va_end(ap); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* This is the generic function to use when the error type is not
|
||||
* known a priori. For ERR_DEBUG and ERR_INFO the level can be
|
||||
* included by
|
||||
*/
|
||||
void nasm_error(errflags flags, const char *fmt, ...)
|
||||
{
|
||||
nasm_do_error(flags & ERR_MASK, flags);
|
||||
}
|
||||
|
||||
#define nasm_err_helpers(_type, _name, _sev) \
|
||||
_type nasm_ ## _name ## f (errflags flags, const char *fmt, ...) \
|
||||
{ \
|
||||
nasm_do_error(_sev, flags); \
|
||||
} \
|
||||
_type nasm_ ## _name (const char *fmt, ...) \
|
||||
{ \
|
||||
nasm_do_error(_sev, 0); \
|
||||
}
|
||||
|
||||
nasm_err_helpers(void, listmsg, ERR_LISTMSG)
|
||||
nasm_err_helpers(void, note, ERR_NOTE)
|
||||
nasm_err_helpers(void, nonfatal, ERR_NONFATAL)
|
||||
nasm_err_helpers(fatal_func, fatal, ERR_FATAL)
|
||||
nasm_err_helpers(fatal_func, critical, ERR_CRITICAL)
|
||||
nasm_err_helpers(fatal_func, panic, ERR_PANIC)
|
||||
|
||||
/*
|
||||
* Strongly discourage warnings without level by require flags on warnings.
|
||||
* This means nasm_warn() is the equivalent of the -f variants of the
|
||||
* other ones.
|
||||
*
|
||||
* This is wrapped in a macro to be able to elide it if the warning is
|
||||
* disabled, hence the extra underscore.
|
||||
*/
|
||||
void nasm_warn_(errflags flags, const char *fmt, ...)
|
||||
{
|
||||
nasm_do_error(ERR_WARNING, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* nasm_info() and nasm_debug() takes mandatory enabling levels.
|
||||
*/
|
||||
void nasm_info_(unsigned int level, const char *fmt, ...)
|
||||
{
|
||||
if (info_level(level))
|
||||
nasm_do_error(ERR_INFO, LEVEL(level));
|
||||
}
|
||||
|
||||
void nasm_debug_(unsigned int level, const char *fmt, ...)
|
||||
{
|
||||
if (debug_level(level))
|
||||
nasm_do_error(ERR_DEBUG, LEVEL(level));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convenience function for nasm_nonfatal(ERR_HOLD, ...)
|
||||
*/
|
||||
void nasm_holderr(const char *fmt, ...)
|
||||
{
|
||||
nasm_do_error(ERR_NONFATAL, ERR_NONFATAL|ERR_HOLD);
|
||||
}
|
||||
|
||||
/*
|
||||
* panic() and nasm_assert()
|
||||
*/
|
||||
fatal_func nasm_panic_from_macro(const char *func, const char *file, int line)
|
||||
{
|
||||
if (!func)
|
||||
func = "<unknown>";
|
||||
|
||||
nasm_panic("internal error in %s at %s:%d\n", func, file, line);
|
||||
}
|
||||
|
||||
fatal_func nasm_assert_failed(const char *msg, const char *func,
|
||||
const char *file, int line)
|
||||
{
|
||||
if (!func)
|
||||
func = "<unknown>";
|
||||
|
||||
nasm_panic("assertion %s failed in %s at %s:%d", msg, func, file, line);
|
||||
}
|
||||
@@ -87,4 +87,8 @@ const uint8_t *parse_prefixes(struct prefix_info *pf, const uint8_t *data,
|
||||
_op; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Error module */
|
||||
void usage(void);
|
||||
|
||||
#endif
|
||||
|
||||
46
disasm/diserror.c
Normal file
46
disasm/diserror.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
/* Copyright 1996-2025 The NASM Authors - All Rights Reserved */
|
||||
|
||||
/*
|
||||
* diserror.c - stubs for the error functions for the disassembler
|
||||
*/
|
||||
|
||||
#include "compiler.h"
|
||||
#include "error.h"
|
||||
#include "disasm.h"
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
const char help[] =
|
||||
"usage: ndisasm [-aihlruvw] [-b bits] [-o origin] [-s sync...]\n"
|
||||
" [-e bytes] [-k start,bytes] [-p vendor] file\n"
|
||||
" -a or -i activates auto (intelligent) sync\n"
|
||||
" -b 16, -b 32 or -b 64 sets the processor mode\n"
|
||||
" -u same as -b 32\n"
|
||||
" -l same as -b 64\n"
|
||||
" -w wide output (avoids continuation lines)\n"
|
||||
" -h displays this text\n"
|
||||
" -r or -v displays the version number\n"
|
||||
" -e skips <bytes> bytes of header\n"
|
||||
" -k avoids disassembling <bytes> bytes from position <start>\n"
|
||||
" -p selects the preferred vendor instruction set (intel, amd, cyrix, idt)\n";
|
||||
|
||||
fputs(help, stderr);
|
||||
}
|
||||
|
||||
void nasm_verror(errflags severity, const char *fmt, va_list val)
|
||||
{
|
||||
severity &= ERR_MASK;
|
||||
|
||||
vfprintf(stderr, fmt, val);
|
||||
if (severity >= ERR_FATAL)
|
||||
exit(severity - ERR_FATAL + 1);
|
||||
}
|
||||
|
||||
fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list val)
|
||||
{
|
||||
nasm_verror(severity, fmt, val);
|
||||
abort();
|
||||
}
|
||||
|
||||
uint8_t warning_state[NUM_WARNINGS];
|
||||
@@ -18,42 +18,13 @@
|
||||
#include "sync.h"
|
||||
#include "disasm.h"
|
||||
|
||||
static int bpl = 8; /* bytes per line of hex dump */
|
||||
const char *_progname;
|
||||
|
||||
static const char *help =
|
||||
"usage: ndisasm [-aihlruvw] [-b bits] [-o origin] [-s sync...]\n"
|
||||
" [-e bytes] [-k start,bytes] [-p vendor] file\n"
|
||||
" -a or -i activates auto (intelligent) sync\n"
|
||||
" -b 16, -b 32 or -b 64 sets the processor mode\n"
|
||||
" -u same as -b 32\n"
|
||||
" -l same as -b 64\n"
|
||||
" -w wide output (avoids continuation lines)\n"
|
||||
" -h displays this text\n"
|
||||
" -r or -v displays the version number\n"
|
||||
" -e skips <bytes> bytes of header\n"
|
||||
" -k avoids disassembling <bytes> bytes from position <start>\n"
|
||||
" -p selects the preferred vendor instruction set (intel, amd, cyrix, idt)\n";
|
||||
static int bpl = 8; /* bytes per line of hex dump */
|
||||
|
||||
static void output_ins(uint64_t, const uint8_t *, int, const char *);
|
||||
static void skip(uint32_t dist, FILE * fp);
|
||||
|
||||
void nasm_verror(errflags severity, const char *fmt, va_list val)
|
||||
{
|
||||
severity &= ERR_MASK;
|
||||
|
||||
vfprintf(stderr, fmt, val);
|
||||
if (severity >= ERR_FATAL)
|
||||
exit(severity - ERR_FATAL + 1);
|
||||
}
|
||||
|
||||
fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list val)
|
||||
{
|
||||
nasm_verror(severity, fmt, val);
|
||||
abort();
|
||||
}
|
||||
|
||||
errflags errflags_never = 0;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
uint8_t buffer[INSN_MAX * 2], *p;
|
||||
@@ -72,6 +43,9 @@ int main(int argc, char **argv)
|
||||
int64_t offset;
|
||||
FILE *fp;
|
||||
|
||||
_progname = argv[0];
|
||||
|
||||
reset_global_defaults(0);
|
||||
nasm_ctype_init();
|
||||
iflag_clear_all(&prefer);
|
||||
|
||||
@@ -90,7 +64,7 @@ int main(int argc, char **argv)
|
||||
p++;
|
||||
break;
|
||||
case 'h':
|
||||
fputs(help, stderr);
|
||||
usage();
|
||||
return 0;
|
||||
case 'r':
|
||||
case 'v':
|
||||
@@ -253,8 +227,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (!filename) {
|
||||
fprintf(stderr, help, pname);
|
||||
return 0;
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(filename, "-")) {
|
||||
@@ -269,6 +243,8 @@ int main(int argc, char **argv)
|
||||
fp = stdin;
|
||||
}
|
||||
|
||||
reset_global_defaults(bits);
|
||||
|
||||
if (initskip > 0)
|
||||
skip(initskip, fp);
|
||||
|
||||
|
||||
@@ -477,4 +477,7 @@ static inline unsigned int watcom_switch_hack(uint64_t x)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* This should be set from main() */
|
||||
extern const char *_progname;
|
||||
|
||||
#endif /* NASM_COMPILER_H */
|
||||
|
||||
@@ -90,6 +90,7 @@ const char *error_pfx(errflags severity);
|
||||
#define ERR_PP_PRECOND 0x00000400 /* for preprocessor use */
|
||||
#define ERR_PP_LISTMACRO 0x00000800 /* from pp_error_list_macros() */
|
||||
#define ERR_HOLD 0x00001000 /* this error/warning can be held */
|
||||
#define ERR_PERROR 0x00002000 /* append strerror(errno) */
|
||||
|
||||
/*
|
||||
* These codes define specific types of suppressible warning.
|
||||
@@ -114,14 +115,28 @@ const char *error_pfx(errflags severity);
|
||||
#define WARN_INIT_ON WARN_ST_ENABLED
|
||||
#define WARN_INIT_ERR (WARN_ST_ENABLED|WARN_ST_ERROR)
|
||||
|
||||
/* Options and status to/from the error module */
|
||||
struct errinfo {
|
||||
FILE *file; /* Error output file pointer */
|
||||
errflags worst; /* Worst severity class encountered */
|
||||
errflags never; /* Error flags to unconditionally suppress */
|
||||
unsigned int debug_nasm; /* Debug message level */
|
||||
unsigned int verbose_info; /* Info message level */
|
||||
bool abort_on_panic; /* Call abort() on ERR_PANIC */
|
||||
};
|
||||
extern struct errinfo erropt;
|
||||
|
||||
int set_error_format(const char *fmt);
|
||||
void error_init(void);
|
||||
void error_pass_start(bool final);
|
||||
void error_pass_end(void);
|
||||
|
||||
/* Process a warning option or directive */
|
||||
bool set_warning_status(const char *value);
|
||||
|
||||
/* Warning stack management */
|
||||
void push_warnings(void);
|
||||
void pop_warnings(void);
|
||||
void init_warnings(void);
|
||||
void reset_warnings(void);
|
||||
|
||||
/*
|
||||
* Tentative error hold for warnings/errors indicated with ERR_HOLD.
|
||||
@@ -147,10 +162,9 @@ errflags nasm_error_hold_pop(errhold hold, bool issue);
|
||||
#include "warnings.h"
|
||||
|
||||
/* True if a warning is enabled, either as a warning or an error */
|
||||
extern errflags errflags_never;
|
||||
static inline bool warn_active(errflags warn)
|
||||
{
|
||||
if (warn & errflags_never)
|
||||
if (warn & erropt.never)
|
||||
return false;
|
||||
|
||||
return !!(warning_state[WARN_IDX(warn)] & WARN_ST_ENABLED);
|
||||
@@ -168,21 +182,19 @@ static inline bool warn_active(errflags warn)
|
||||
#endif
|
||||
|
||||
/* Debug level checks */
|
||||
extern unsigned int debug_nasm;
|
||||
static inline bool debug_level(unsigned int level)
|
||||
{
|
||||
if (is_constant(level) && level > MAX_DEBUG)
|
||||
return false;
|
||||
return unlikely(level <= debug_nasm);
|
||||
return unlikely(level <= erropt.debug_nasm);
|
||||
}
|
||||
|
||||
/* Info level checks */
|
||||
extern unsigned int opt_verbose_info;
|
||||
static inline bool info_level(unsigned int level)
|
||||
{
|
||||
if (is_constant(level) && level > MAX_INFO)
|
||||
return false;
|
||||
return unlikely(level <= opt_verbose_info);
|
||||
return unlikely(level <= erropt.verbose_info);
|
||||
}
|
||||
|
||||
#ifdef HAVE_VARIADIC_MACROS
|
||||
@@ -230,5 +242,11 @@ static inline bool info_level(unsigned int level)
|
||||
|
||||
#endif
|
||||
|
||||
/* Callbacks from the error module */
|
||||
void print_final_report(bool failure);
|
||||
void close_output(bool failure);
|
||||
bool pp_suppress_error(errflags flags);
|
||||
void pp_error_list_macros(errflags flags);
|
||||
|
||||
|
||||
#endif /* NASM_ERROR_H */
|
||||
|
||||
@@ -1569,6 +1569,7 @@ struct globalopt {
|
||||
bool dollarhex; /* $-prefixed hexadecimal numbers? */
|
||||
};
|
||||
extern struct globalopt globl;
|
||||
void reset_global_defaults(int bits);
|
||||
|
||||
extern const char *inname; /* primary input filename */
|
||||
extern const char *outname; /* output filename */
|
||||
|
||||
@@ -8,19 +8,12 @@
|
||||
#include "compiler.h"
|
||||
|
||||
#include "nctype.h"
|
||||
|
||||
#include "nasmlib.h"
|
||||
#include "nasm.h"
|
||||
#include "error.h"
|
||||
#include "nasm.h" /* For globl.dollarhex */
|
||||
|
||||
#define lib_isnumchar(c) (nasm_isalnum(c) || (c) == '$' || (c) == '_')
|
||||
|
||||
void warn_dollar_hex(void)
|
||||
{
|
||||
nasm_warn(WARN_NUMBER_DEPRECATED_HEX,
|
||||
"$ prefix for hexadecimal is deprecated");
|
||||
}
|
||||
|
||||
int64_t readnum(const char *str, bool *error)
|
||||
{
|
||||
const char *r = str, *q;
|
||||
|
||||
Reference in New Issue
Block a user