mexec.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,143 行 · 第 1/4 页
C
2,143 行
newCommand = StartVec();
WriteVec( newCommand, "" );
index = 0;
start = index;
current = head;
while( current != NULL && ret == RET_SUCCESS &&
cmdText[index] != NULLCHAR ) {
// if the filename is the inline symbol then we need change
// the filename into a temp filename
if( strcmp( current->fileName, INLINE_SYMBOL ) == 0 ) {
for( ;; ) {
if( cmdText[index] == LESSTHAN ) {
if( cmdText[index + 1] == LESSTHAN ) {
index += 2;
break;
}
} else if( cmdText[index] == NULLCHAR ) {
/* not possible to come here*/
ret = RET_ERROR;
break;
}
++index;
}
if( ret == RET_ERROR ) {
break;
}
CatNStrToVec( newCommand, cmdText+start, index-start-2 );
start = index;
FreeSafe( current->fileName );
current->fileName = createTmpFileName();
CatStrToVec( newCommand, current->fileName );
}
if( !Glob.noexec ) {
ret = createFile( current );
} else {
if( current->keep == FALSE ) {
temp = NewNKList();
temp->fileName = StrDupSafe( current->fileName );
temp->next = noKeepList;
noKeepList = temp;
}
}
current = current->next;
}
CatNStrToVec( newCommand, cmdText+start, strlen( cmdText ) - start );
FreeSafe( cmdText );
*commandIn = FinishVec( newCommand );
return( ret );
}
STATIC int findInternal( const char *cmd )
/*****************************************
* check cmd for command.com command, return index if it is
* return CNUM if is of form x:
* otherwise return -1
* expects cmd to be just the command - ie: no args
*/
{
char * const *key;
size_t len;
char buff[COM_MAX_LEN];
assert( cmd != NULL );
/* test if of form x: */
if( isalpha( *cmd ) && cmd[1] == ':' && cmd[2] == NULLCHAR ) {
return( CNUM );
}
for( ;; ) {
key = bsearch( &cmd, dosInternals, CNUM, sizeof( char * ),
(int (*)( const void *, const void * ))KWCompare );
if( key != NULL ) {
break;
}
len = strlen( cmd );
if( len > 1 && len < COM_MAX_LEN ) {
if( cmd[len - 1] == '.' ) {
// should work if buff == cmd (i.e., cd..)
strcpy( buff, cmd );
buff[len - 1] = '\0';
cmd = buff;
continue;
}
}
return( -1 );
}
return( key - (char **)dosInternals );
}
STATIC RET_T percentMake( char *arg )
/************************************
* do a recursive make of the target in arg
*/
{
TARGET *calltarg;
RET_T ret;
char *buf;
char *start;
char *finish;
BOOLEAN newtarg;
BOOLEAN more_targets;
/* %make <target> <target> ... */
buf = MallocSafe( _MAX_PATH );
ret = RET_ERROR;
start = arg;
for( ;; ) {
start = SkipWS( start );
if( *start == NULLCHAR ) {
break;
}
more_targets = FALSE;
finish = start;
for( ;; ) {
if( *finish == NULLCHAR ) {
break;
}
if( isws( *finish ) ) {
more_targets = TRUE;
*finish = NULLCHAR;
break;
}
++finish;
}
/* try to find this file on path or in targets */
ret = TrySufPath( buf, start, &calltarg, FALSE );
newtarg = FALSE;
if( ( ret == RET_SUCCESS && calltarg == NULL ) || ret == RET_ERROR ) {
/* Either file doesn't exist, or it exists and we don't already
* have a target for it. Either way, we create a new target.
*/
calltarg = NewTarget( buf );
newtarg = TRUE;
}
ret = Update( calltarg );
if( newtarg && Glob.noexec == FALSE ) {
/* we created a target - don't need it any more */
KillTarget( calltarg->node.name );
}
if( more_targets ) {
*finish = ' ';
}
start = finish;
}
FreeSafe( buf );
return( ret );
}
STATIC void closeCurrentFile( void )
/**********************************/
{
if( currentFileHandle != -1 ) {
close( currentFileHandle );
}
if( currentFileName != NULL ) {
FreeSafe( currentFileName );
currentFileName = NULL;
}
CacheRelease(); /* so that the cache is updated */
}
STATIC RET_T percentWrite( char *arg, enum write_type type )
/**********************************************************/
{
char *p;
char const *text;
char *fn;
char const *cmd_name;
int open_flags;
size_t len;
assert( arg != NULL );
if( Glob.noexec ) {
return( RET_SUCCESS );
}
p = SkipWS( arg );
fn = p;
if( *p != DOUBLEQUOTE ) {
while( isfilec( *p ) ) {
++p;
}
} else {
++p; // Skip the first quote
++fn;
while( *p!= DOUBLEQUOTE && *p!= NULLCHAR ) {
++p;
}
if( *p!= NULLCHAR ) {
*p = NULLCHAR;
p++;
}
}
if( *p != NULLCHAR ) {
if( !isws( *p ) ) {
switch( type ) {
case WR_APPEND:
cmd_name = percentCmds[PER_APPEND];
break;
case WR_CREATE:
cmd_name = percentCmds[PER_CREATE];
break;
case WR_WRITE:
cmd_name = percentCmds[PER_WRITE];
break;
default:
cmd_name = "?";
break;
}
PrtMsg( ERR | SYNTAX_ERROR_IN, cmd_name );
closeCurrentFile();
return( RET_ERROR );
}
*p = '\0'; /* terminate file name */
++p;
text = p; /* set text pointer */
p += strlen( p ); /* find null terminator */
} else {
*p = '\0'; /* terminate file name */
text = p; /* set text pointer */
}
/* now text points to the beginning of string to write, and p points to
* the end of the string. fn points to the name of the file to write to
*/
FixName( fn );
if( type == WR_CREATE || currentFileName == NULL ||
FNameCmp( currentFileName, fn ) != 0 ) {
closeCurrentFile();
currentFileName = StrDupSafe( fn );
open_flags = O_WRONLY | O_CREAT | O_TEXT;
if( type == WR_APPEND ) {
open_flags |= O_APPEND;
} else {
open_flags |= O_TRUNC;
}
currentFileHandle = open( fn, open_flags, S_IWRITE | S_IREAD );
if( currentFileHandle == -1 ) {
PrtMsg( ERR | OPENING_FOR_WRITE, fn );
closeCurrentFile();
return( RET_ERROR );
}
}
if( type != WR_CREATE ) {
*p = '\n'; /* replace null terminator with newline */
len = (p - text) + 1;
if( write( currentFileHandle, text, len ) != len ) {
PrtMsg( ERR | DOING_THE_WRITE );
closeCurrentFile();
return( RET_ERROR );
}
}
CacheRelease(); /* so that the cache is updated */
return( RET_SUCCESS );
}
STATIC RET_T percentErase( char *arg )
/************************************/
{
if( 0 == unlink( FixName( arg ) ) ) {
return( RET_SUCCESS );
}
return( RET_ERROR );
}
STATIC RET_T percentRename( char *arg )
/************************************/
{
char *p;
char *fn1, *fn2;
assert( arg != NULL );
if( Glob.noexec ) {
return( RET_SUCCESS );
}
/* Get first file name, must end in space but may be surrounded by double quotes */
p = SkipWS( arg );
fn1 = p;
if( *p != DOUBLEQUOTE ) {
while( isfilec( *p ) ) {
++p;
}
} else {
++p; // Skip the first quote
++fn1;
while( *p!= DOUBLEQUOTE && *p!= NULLCHAR ) {
++p;
}
if( *p!= NULLCHAR ) {
*p = NULLCHAR;
p++;
}
}
if( *p == NULLCHAR || !isws( *p ) ) {
PrtMsg( ERR | SYNTAX_ERROR_IN, percentCmds[PER_RENAME] );
PrtMsg( INF | PRNTSTR, "First file" );
PrtMsg( INF | PRNTSTR, p );
return( RET_ERROR );
}
*p = '\0'; /* terminate first file name */
++p;
/* Get second file name as well */
p = SkipWS( p );
fn2 = p;
if( *p != DOUBLEQUOTE ) {
while( isfilec( *p ) ) {
++p;
}
} else {
++p; // Skip the first quote
++fn2;
while( *p!= DOUBLEQUOTE && *p!= NULLCHAR ) {
++p;
}
if( *p!= NULLCHAR ) {
*p = NULLCHAR;
p++;
}
}
if( *p != NULLCHAR && !isws( *p ) ) {
PrtMsg( ERR | SYNTAX_ERROR_IN, percentCmds[PER_RENAME] );
return( RET_ERROR );
}
*p = '\0'; /* terminate second file name */
if( rename( fn1, fn2 ) == 0)
return( RET_SUCCESS );
else
return( RET_ERROR );
}
STATIC RET_T percentCmd( const char *cmdname, char *arg )
/********************************************************
* handle our special percent commands
*/
{
char const * const *key;
char const *ptr;
int num;
assert( cmdname != NULL && arg != NULL );
ptr = cmdname + 1;
key = bsearch( &ptr, percentCmds, PNUM, sizeof( char * ),
(int (*)( const void*, const void* ))KWCompare );
if( key == NULL ) {
PrtMsg( ERR | UNKNOWN_PERCENT_CMD );
closeCurrentFile();
return( RET_ERROR );
} else {
num = key - (char const **)percentCmds;
}
if( Glob.noexec && num != PER_MAKE ) {
return( RET_SUCCESS );
}
switch( num ) {
case PER_ABORT:
closeCurrentFile();
exit( ExitSafe( EXIT_ERROR ) );
case PER_APPEND:
return( percentWrite( arg, WR_APPEND ) );
case PER_CREATE:
return( percentWrite( arg, WR_CREATE ) );
case PER_ERASE:
return( percentErase( arg ) );
case PER_MAKE:
return( percentMake( arg ) );
case PER_NULL:
break;
case PER_QUIT:
closeCurrentFile();
exit( ExitSafe( EXIT_OK ) );
case PER_RENAME:
return( percentRename( arg ) );
case PER_STOP:
closeCurrentFile();
if( !GetYes( DO_YOU_WISH_TO_CONT ) ) {
exit( ExitSafe( EXIT_OK ) );
}
break;
case PER_WRITE:
return( percentWrite( arg, WR_WRITE ) );
default:
assert( FALSE );
break;
};
return( RET_SUCCESS );
}
#ifdef __LINUX__
STATIC int intSystem( const char *cmd )
/**************************************
* interruptable "system" (so that ctrl-c works)
*/
{
pid_t pid = fork();
int status;
if( pid == -1 ) {
return( -1 );
}
if( pid == 0 ) {
execl( "/bin/sh", "sh", "-c", cmd, NULL );
exit( 127 );
}
for( ;; ) {
if( waitpid( pid, &status, 0 ) == -1 ) {
if( errno == EINTR ) {
continue;
}
status = -1;
} else if( WIFSIGNALED( status ) ) {
if( WTERMSIG( status ) > 0 && WTERMSIG( status ) <= 15 ) {
PrtMsg( INF | (SIG_ERR_0 + WTERMSIG( status ) ) );
} else {
PrtMsg( INF | SIG_ERR_0, WTERMSIG( status ) );
}
}
CheckForBreak();
return( status );
}
}
#endif
STATIC RET_T mySystem( const char *cmdname, const char *cmd )
/************************************************************
* execute a command using system()
*/
{
int retcode;
assert( cmd != NULL );
if( Glob.noexec ) {
return( RET_SUCCESS );
}
closeCurrentFile();
#ifdef __LINUX__
retcode = intSystem( cmd );
#else
retcode = system( cmd );
#endif
lastErrorLevel = (UINT8)retcode;
if( retcode < 0 ) {
PrtMsg( ERR | UNABLE_TO_EXEC, cmdname );
}
if( retcode != 0 ) {
return( RET_ERROR );
}
return( RET_SUCCESS );
}
STATIC RET_T handleSet( char *cmd )
/**********************************
* "SET" {ws}* <name> {ws}* "="[<value>]
*/
{
char *p; /* we walk cmd with this */
char *name; /* beginning of variable name */
char *endname; /* end of name */
ENV_TRACKER *env; /* space allocated for envvar */
int retcode; /* from putenv */
assert( cmd != NULL );
#ifdef DEVELOPMENT
PrtMsg( DBG | INF | INTERPRETING, dosInternals[COM_SET] );
#endif
if( Glob.noexec ) {
return( RET_SUCCESS );
}
p = SkipWS( cmd + 3 ); /* find first non-ws after "SET" */
if( *p == NULLCHAR ) { /* just "SET" with no options... pass on */
return( mySystem( cmd, cmd ) );
}
/* anything goes in a dos set name... even punctuation! */
name = p;
while( *p != NULLCHAR && !isws( *p ) && *p != '=' ) {
++p;
}
endname = p;
p = SkipWS( p ); /* trim ws after name */
if( *p != '=' || endname == name ) {
PrtMsg( ERR | SYNTAX_ERROR_IN, dosInternals[COM_SET] );
return( RET_ERROR );
}
*endname = NULLCHAR; /* null terminate name */
++p; /* advance to character after '=' */
/* +1 for '=' (already +1 for '\0' in ENV_TRACKER) */
env = MallocSafe( sizeof( *env ) + 1 + (endname - name) + strlen( p ) );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?