📄 rcio.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: WRC I/O routines.
*
****************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <time.h>
#ifndef __UNIX__
#include <process.h>
#endif
#include "watcom.h"
#include "wresall.h"
#include "global.h"
#include "pass2.h"
#include "semstr.h"
#include "rcmem.h"
#include "rctypes.h"
#include "errors.h"
#include "exeutil.h"
#include "rcio.h"
#include "preproc.h"
#include "reserr.h"
#include "tmpctl.h"
#include "autodep.h"
#include "errprt.h"
#include "util.h"
#include "rcldstr.h"
#include "iortns.h"
#include <banner.h>
#ifdef _BANEXTRA
#undef _BANEXTRA
#define _BANEXTRA _BANEXSHORT
#endif
#ifdef __UNIX__
#define PATH_SEP '/'
#define PATH_SPLIT ':'
#else
#define PATH_SEP '\\'
#define PATH_SPLIT ';'
#endif
#ifdef __OSI__
extern char *_Copyright;
#endif
#if !defined( DLL_COMPILE )
extern char *RcGetEnv( const char *name )
/****************************************/
{
return( getenv( name ) );
}
#endif
static void MakeTmpInSameDir( const char * dirfile, char * outfile, char * ext )
/******************************************************************************/
{
char drive[ _MAX_DRIVE ];
char dir[ _MAX_DIR ];
#ifdef __UNIX__
char fname[ 32 ];
#else
char *fname = "__TMP__";
#endif
_splitpath( dirfile, drive, dir, NULL, NULL );
#ifdef __UNIX__
// Must be able to run several "rc" executables simultaneously
// in the same directory
sprintf( fname, "__RCTMP%lu__", (unsigned long)getpid() );
#endif
_makepath( outfile, drive, dir, fname, ext );
} /* MakeTmpInSameDir */
static int Pass1InitRes( void )
/*****************************/
{
WResID null_id;
ResMemFlags null_memflags;
ResLocation null_loc;
/* put the temporary file in the same location as the output file */
CurrResFile.filename = CurrResFile.namebuf;
#ifdef USE_TEMPFILE
MakeTmpInSameDir( CmdLineParms.OutResFileName, CurrResFile.filename,
"res" );
#else
strcpy( CurrResFile.filename, CmdLineParms.OutResFileName );
#endif
/* initialize the directory */
CurrResFile.dir = WResInitDir();
if( CurrResFile.dir == NULL ) {
RcError( ERR_OUT_OF_MEMORY );
CurrResFile.IsOpen = false;
return( TRUE );
}
if( CmdLineParms.TargetOS == RC_TARGET_OS_WIN16 ) {
WResSetTargetOS( CurrResFile.dir, WRES_OS_WIN16 );
} else if( CmdLineParms.TargetOS == RC_TARGET_OS_WIN32 ) {
WResSetTargetOS( CurrResFile.dir, WRES_OS_WIN32 );
} else {
WResSetTargetOS( CurrResFile.dir, WRES_OS_OS2 );
}
/* open the tempory file */
if (CmdLineParms.MSResFormat) {
CurrResFile.IsWatcomRes = FALSE;
CurrResFile.handle = MResOpenNewFile( CurrResFile.filename );
/* write null header here if it is win32 */
if( CmdLineParms.TargetOS == RC_TARGET_OS_WIN32 &&
CmdLineParms.MSResFormat ) {
null_loc.start = SemStartResource();
null_loc.len = SemEndResource( null_loc.start );
null_id.IsName = FALSE;
null_id.ID.Num = 0;
null_memflags = 0;
SemAddResource( &null_id, &null_id, null_memflags, null_loc );
}
} else {
CurrResFile.IsWatcomRes = TRUE;
CurrResFile.handle = WResOpenNewFile( CurrResFile.filename );
}
if( CurrResFile.handle == -1 ) {
RcError( ERR_OPENING_TMP, CurrResFile.filename, LastWresErrStr() );
CurrResFile.IsOpen = false;
return( TRUE );
}
RegisterTmpFile( CurrResFile.filename );
CurrResFile.IsOpen = true;
CurrResFile.StringTable = NULL;
CurrResFile.ErrorTable = NULL;
CurrResFile.FontDir = NULL;
CurrResFile.NextCurOrIcon = 1;
return( FALSE );
} /* Pass1InitRes */
extern void RcFindResource( char *name, char *fullpath ) {
char *src;
char *dst;
char end;
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
fullpath[0] = '\0';
//if the filename has a drive or is an absolute path then ignore
//the include path and just look at the specified location
_splitpath( name, drive, dir, NULL, NULL );
if( drive[0] != '\0' || dir[0] ==PATH_SEP ) {
if( access( name, F_OK ) == 0 ) {
strcpy( fullpath, name );
}
return;
}
if( !CmdLineParms.IgnoreCWD && access( name, F_OK ) == 0 ) {
strcpy( fullpath, name );
return;
}
if( NewIncludeDirs != NULL ) {
src = NewIncludeDirs;
end = *NewIncludeDirs;
while( end != '\0' ) {
dst = fullpath;
while( *src != ';' && *src != PATH_SPLIT && *src != '\0' ) {
*dst = *src;
dst ++;
src ++;
}
end = *src;
src ++;
if( *( dst - 1 ) != PATH_SEP ) {
*dst = PATH_SEP;
dst++;
}
strcpy( dst, name );
if( access( fullpath, F_OK ) == 0 ) return;
}
}
fullpath[0] = '\0';
}
extern void RcTmpFileName( char * tmpfilename )
/*********************************************/
/* uses the TMP env. var. if it is set and puts the result into tmpfilename */
/* which is assumed to be a buffer of at least _MAX_PATH characters */
{
char * nextchar;
char * tmpdir;
tmpdir = RcGetEnv( "TMP" );
if( tmpdir != NULL ) {
/* leave room for the '\' and the filename */
strncpy( tmpfilename, tmpdir, _MAX_PATH - L_tmpnam - 1 );
nextchar = tmpfilename + strlen( tmpfilename ) - 1;
/* tack a '\' onto the end if it is not there already */
if( *nextchar != PATH_SEP ) {
nextchar++;
*nextchar = PATH_SEP;
}
nextchar++;
} else {
nextchar = tmpfilename;
}
tmpnam( nextchar );
}
static int PreprocessInputFile( void )
/************************************/
{
unsigned flags;
char rcdefine[13];
char **cppargs;
char *p;
int rc;
// We have already merged INCLUDE path with /i paths
flags = PPFLAG_IGNORE_INCLUDE;
if( CmdLineParms.IgnoreCWD ) {
flags |= PPFLAG_IGNORE_CWD;
}
rc = PP_Init2( CmdLineParms.InFileName, flags, NewIncludeDirs, CharSet );
if( rc != 0 ) {
RcError( ERR_CANT_OPEN_FILE, CmdLineParms.InFileName, strerror(errno) );
return( TRUE );
}
strcpy( rcdefine, "RC_INVOKED 1" );
PP_Define( rcdefine );
if( CmdLineParms.TargetOS == RC_TARGET_OS_WIN16 ) {
strcpy( rcdefine, "__WINDOWS__" );
PP_Define( rcdefine );
} else if( CmdLineParms.TargetOS == RC_TARGET_OS_WIN32 ) {
strcpy( rcdefine, "__NT__" );
PP_Define( rcdefine );
strcpy( rcdefine, "_WIN32" );
PP_Define( rcdefine );
} else if( CmdLineParms.TargetOS == RC_TARGET_OS_OS2 ) {
strcpy( rcdefine, "__OS2__" );
PP_Define( rcdefine );
}
cppargs = CmdLineParms.CPPArgs;
if( cppargs != NULL ) {
++cppargs;
for(;;) {
p = *cppargs;
if( p == NULL ) break;
for(;;) {
if( *p == '\0' ) break;
if( *p == '=' ) {
*p = ' ';
break;
}
++p;
}
p = *cppargs;
PP_Define( p + 2 ); // skip over -d
++cppargs;
}
}
return( FALSE ); // indicate no error
}
extern int RcPass1IoInit( void )
/******************************/
/* Open the two files for input and output. The input stream starts at the */
/* top infilename and continues as the directives in the file indicate */
/* Returns false if there is a problem opening one of the files. */
{
int error;
char *includepath = NULL;
if( !CmdLineParms.IgnoreINCLUDE ) {
if( CmdLineParms.TargetOS == RC_TARGET_OS_WIN16 ) {
includepath = RcGetEnv( "WINDOWS_INCLUDE" );
} else if( CmdLineParms.TargetOS == RC_TARGET_OS_WIN32 ) {
includepath = RcGetEnv( "NT_INCLUDE" );
} else if( CmdLineParms.TargetOS == RC_TARGET_OS_OS2 ) {
includepath = RcGetEnv( "OS2_INCLUDE" );
}
}
if( includepath != NULL ) {
AddNewIncludeDirs( includepath );
}
if( CmdLineParms.NoPreprocess ) {
RcIoTextInputInit();
error = RcIoPushInputFile( CmdLineParms.InFileName );
} else {
error = PreprocessInputFile();
if( error ) return( FALSE );
RcIoTextInputInit();
error = RcIoPushInputFile( CmdLineParms.InFileName );
}
if( error ) return( FALSE );
if( !CmdLineParms.PreprocessOnly ) {
error = Pass1InitRes();
}
if( error ) {
PP_Fini();
RcIoTextInputShutdown();
return( FALSE );
}
return( TRUE );
}
static int ChangeTmpToOutFile( const char * tmpfile, const char * outfile )
/**************************************************************************/
{
int fileerror; /* error while deleting or renaming */
/* remove the old copy of the output file */
fileerror = remove( outfile );
if( fileerror ) {
if( errno == ENOENT ) {
/* ignore the error if it says that the file doesn't exist */
errno = 0;
} else {
RcError( ERR_RENAMEING_TMP_FILE, tmpfile, outfile,
strerror( errno ) );
remove( tmpfile );
UnregisterTmpFile( tmpfile );
return( TRUE );
}
}
/* rename the temp file to the output file */
fileerror = rename( tmpfile, outfile );
if( fileerror ) {
RcError( ERR_RENAMEING_TMP_FILE, tmpfile, outfile,
strerror( errno ) );
remove( tmpfile );
UnregisterTmpFile( tmpfile );
return( TRUE );
}
return( FALSE );
} /* ChangeTmpToOutFile */
static int RemoveCurrResFile( void )
/**********************************/
{
int fileerror;
fileerror = remove( CurrResFile.filename );
UnregisterTmpFile( CurrResFile.filename );
if( fileerror ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -