jwasm/errmsg.c
2014-06-18 19:16:56 +04:00

373 lines
11 KiB
C

/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Diagnostics routines: (fatal) errors, warnings, notes
*
****************************************************************************/
#include <stdarg.h>
#include <ctype.h>
#include <setjmp.h>
#include "globals.h"
#include "memalloc.h"
#include "parser.h"
#include "input.h"
#include "tokenize.h"
#include "macro.h"
#include "msgtext.h"
#include "listing.h"
#include "segment.h"
extern void print_source_nesting_structure( void );
extern jmp_buf jmpenv;
//static bool Errfile_Written;
//static void PrtMsg( int severity, int msgnum, va_list args1, va_list args2 );
//void PutMsg( FILE *fp, int severity, int msgnum, va_list args );
char banner_printed = FALSE;
static const char usage[] = {
#include "usage.h"
};
#ifdef DEBUG_OUT
/* there are intransparent IDEs that don't want to tell you the real, current command line arguments
* and often those tools also swallow anything that is written to stdout or stderr.
* To make jwasm write a trace log to a file, enable the next line!
* Additionally, you'll probably have to enable line Set_dt() in cmdline.c, function ParseCmdline().
*/
//#define DBGLOGFILE "jwasm.log"
#ifdef DBGLOGFILE
FILE *fdbglog = NULL;
#endif
void DoDebugMsg( const char *format, ... )
/****************************************/
{
va_list args;
if( !Options.debug ) return;
if( ModuleInfo.cref == FALSE && CurrFName[ASM] != NULL )
return;
va_start( args, format );
#ifdef DBGLOGFILE
if ( fdbglog == NULL )
fdbglog = fopen( DBGLOGFILE, "w" );
vfprintf( fdbglog, format, args );
#else
vprintf( format, args );
#endif
va_end( args );
#if 0
#ifdef DBGLOGFILE
fflush( fdbglog );
#else
fflush( stdout );
#endif
#endif
}
void DoDebugMsg1( const char *format, ... )
/****************************************/
{
va_list args;
char buffer[MAX_LINE_LEN];
if( !Options.debug ) return;
if( ModuleInfo.cref == FALSE ) return;
#ifdef DBGLOGFILE
if ( fdbglog == NULL )
fdbglog = fopen( DBGLOGFILE, "w" );
#endif
//if ( CurrFName[ASM] )
if ( ModuleInfo.g.src_stack ) {
#ifdef DBGLOGFILE
fprintf( fdbglog, "%" I32_SPEC "u%s. ", GetLineNumber(), GetTopLine( buffer ) );
#else
printf( "%" I32_SPEC "u%s. ", GetLineNumber(), GetTopLine( buffer ) );
#endif
}
va_start( args, format );
#ifdef DBGLOGFILE
vfprintf( fdbglog, format, args );
#else
vprintf( format, args );
#endif
va_end( args );
#if 0
#ifdef DBGLOGFILE
fflush( fdbglog );
#else
fflush( stdout );
#endif
#endif
}
#endif
int write_logo( void )
/********************/
{
if( banner_printed == FALSE ) {
banner_printed = TRUE;
printf( "%s, %s\n", MsgGetEx( MSG_JWASM ), MsgGetEx( MSG_JWASM2 ) );
return( 4 ); /* return number of lines printed */
}
return( 0 );
}
void PrintUsage( void )
/*********************/
{
const char *p;
write_logo();
for ( p = usage; *p != '\n'; ) {
const char *p2 = p + strlen( p ) + 1;
printf("%-20s %s\n", p, p2 );
p = p2 + strlen( p2 ) + 1;
}
}
static void PutMsg( FILE *fp, int severity, int msgnum, va_list args )
/********************************************************************/
{
int i,j;
const char *type;
const char *pMsg;
char buffer[MAX_LINE_LEN+128];
if( fp != NULL ) {
if ( severity && ( j = GetCurrSrcPos( buffer ) ) ) {
fwrite( buffer, 1, j, fp );
}
pMsg = MsgGetEx( msgnum );
switch (severity ) {
case 1: type = MsgGetEx( MSG_FATAL_PREFIX ); break;
case 2: type = MsgGetEx( MSG_ERROR_PREFIX ); break;
case 4: type = MsgGetEx( MSG_WARNING_PREFIX ); break;
default: type = NULL; i = 0; break;
}
if ( type )
i = sprintf( buffer, "%s A%4u: ", type, severity * 1000 + msgnum );
i += vsprintf( buffer+i, pMsg, args );
//buffer[i] = NULLC;
fwrite( buffer, 1, i, fp );
fwrite( "\n", 1, 1, fp );
/* if in Pass 1, add the error msg to the listing */
if ( CurrFile[LST] &&
severity &&
Parse_Pass == PASS_1 &&
fp == CurrFile[ERR] ) {
LstWrite( LSTTYPE_DIRECTIVE, GetCurrOffset(), 0 );
/* size of "blank" prefix to be explained! */
LstPrintf( " %s", buffer );
LstNL();
}
}
}
static void PrtMsg( int severity, int msgnum, va_list args1, va_list args2 )
/**************************************************************************/
{
#ifndef __SW_BD
write_logo();
#endif
/* open .err file if not already open and a name is given */
if( CurrFile[ERR] == NULL && CurrFName[ERR] != NULL ) {
CurrFile[ERR] = fopen( CurrFName[ERR], "w" );
if( CurrFile[ERR] == NULL ) {
/* v2.06: no fatal error anymore if error file cannot be written */
char *p = CurrFName[ERR];
CurrFName[ERR] = NULL; /* set to NULL before EmitErr()! */
Options.no_error_disp = FALSE; /* disable -eq! */
EmitErr( CANNOT_OPEN_FILE, p, ErrnoStr() );
LclFree( p );
}
}
/* v2.05: new option -eq */
if ( Options.no_error_disp == FALSE ) {
PutMsg( errout, severity, msgnum, args1 );
fflush( errout ); /* 27-feb-90 */
}
if( CurrFile[ERR] ) {
//Errfile_Written = TRUE;
PutMsg( CurrFile[ERR], severity, msgnum, args2 );
}
}
/* notes: "included by", "macro called from", ... */
void PrintNote( int msgnum, ... )
/*******************************/
{
va_list args1, args2;
va_start( args1, msgnum );
va_start( args2, msgnum );
PrtMsg( 0, msgnum, args1, args2 );
va_end( args1 );
va_end( args2 );
}
int EmitErr( int msgnum, ... )
/****************************/
{
va_list args1, args2;
#ifdef DEBUG_OUT
printf( "%s\n", ModuleInfo.tokenarray ? ModuleInfo.tokenarray[0].tokpos : "" );
#endif
va_start( args1, msgnum );
va_start( args2, msgnum );
PrtMsg( 2, msgnum, args1, args2 );
va_end( args1 );
va_end( args2 );
ModuleInfo.g.error_count++;
write_to_file = FALSE;
print_source_nesting_structure();
if( Options.error_limit != -1 && ModuleInfo.g.error_count == Options.error_limit+1 )
Fatal( TOO_MANY_ERRORS );
return( ERROR );
}
int EmitError( int msgnum )
/*************************/
{
return( EmitErr( msgnum ) );
}
void EmitWarn( int level, int msgnum, ... )
/*****************************************/
{
va_list args1, args2;
if( level <= Options.warning_level ) {
#ifdef DEBUG_OUT
printf( "%s\n", ModuleInfo.tokenarray ? ModuleInfo.tokenarray[0].tokpos : "" );
#endif
va_start( args1, msgnum );
va_start( args2, msgnum );
if( !Options.warning_error ) {
PrtMsg( 4, msgnum, args1, args2 );
ModuleInfo.g.warning_count++;
} else {
PrtMsg( 2, msgnum, args1, args2 );
ModuleInfo.g.error_count++;
}
va_end( args1 );
va_end( args2 );
print_source_nesting_structure();
}
}
char *ErrnoStr( void )
/********************/
{
static char buffer[32];
return( ( errno == ENOENT ) ? "ENOENT" : myltoa( errno, buffer, 10, FALSE, FALSE ) );
}
/* fatal error (out of memory, unable to open files for write, ...)
* don't use functions which need to alloc memory here!
* v2.08: do not exit(), just a longjmp() into AssembleModule().
*/
void Fatal( int msgnum, ... )
/***************************/
{
va_list args1, args2;
/* v2.11: call PrtMsg() instead of PutMsg().
* Makes the fatal error appear in the .ERR and .LST files
*/
va_start( args1, msgnum );
va_start( args2, msgnum );
PrtMsg( 1, msgnum, args1, args2 );
va_end( args1 );
va_end( args2 );
ModuleInfo.g.error_count++;
//write_to_file = FALSE;
/* setjmp() has been called in AssembleModule().
* if a fatal error happens outside of this function, longjmp()
* is NOT to be used ( out of memory condition, @cmd file open error, ... )
*/
if ( CurrFName[ASM] )
longjmp( jmpenv, 2 );
exit(1);
}
#if 0
void SeekError( void )
/********************/
{
DebugMsg(("SeekError occured\n"));
Fatal( FILE_SEEK_ERROR, CurrFName[OBJ], errno );
};
#endif
void WriteError( void )
/*********************/
{
DebugMsg(("WriteError occured\n"));
Fatal( FILE_WRITE_ERROR, CurrFName[OBJ], errno );
};
#ifndef NDEBUG
int InternalError( const char *file, unsigned line )
/**************************************************/
/* it's used by myassert() function in debug version */
{
#if 1
char buffer[MAX_LINE_LEN];
DebugMsg(("InternalError enter\n"));
ModuleInfo.g.error_count++;
GetCurrSrcPos( buffer );
fprintf( errout, "%s", buffer );
fprintf( errout, MsgGetEx( INTERNAL_ERROR ), file, line );
close_files();
exit( EXIT_FAILURE );
#else
Fatal( INTERNAL_ERROR, file, line );
#endif
return( 0 );
}
#endif