/* * Add one more symbol. */ static orl_return do_orl_symbol( orl_symbol_handle o_symbol ) /***********************************************************/ { char * name; char * namecopy; name = ORLSymbolGetName( o_symbol ); if( !is_name_mangled( name ) ) { namecopy = DupStrMem( name ); InsertHash( hashtable, namecopy ); } return( ORL_OKAY ); }
/* * Add one more parameter to the section specified by block. Reallocates * memory if necessary, and does all necessary bookkeeping. */ void AppendCmdLine( CmdLine *cmdLine, int section, const char *parm ) /*******************************************************************/ { /*** Allocate GRANULARITY more elements if we're out of room ***/ if( section < 0 || section >= cmdLine->numSections ) Zoinks(); if( cmdLine[section].curItems+2 > cmdLine[section].maxItems ) { cmdLine[section].args = ReallocMem( cmdLine[section].args, (cmdLine[section].maxItems+GRANULARITY) * sizeof(char*) ); cmdLine[section].maxItems += GRANULARITY; } /*** Store the specified pointer and update curItems ***/ if( parm != NULL ) parm = DupStrMem( parm ); /* copy it */ cmdLine[section].args[ cmdLine[section].curItems ] = (char*)parm; cmdLine[section].args[ cmdLine[section].curItems+1 ] = NULL;/* last one */ cmdLine[section].curItems++; }
/* * Returns the actual name of 'filename', searching 'libpaths' if necessary. * The caller is responsible for freeing the returned memory. If the file * cannot be found, NULL is returned. */ static char *find_file( const char *filename, const char *libpaths[] ) /********************************************************************/ { int rc; unsigned count; char * tryme; size_t len; const char * p; bool hasbackslash; /*** We might not have to go searching for it ***/ rc = access( filename, F_OK ); if( rc == 0 ) { return( DupStrMem( filename ) ); } /*** Not found, so check any directories in 'libpaths' ***/ if( libpaths != NULL ) { for( count=0; libpaths[count]!=NULL; count++ ) { /*** Determine if we need to add a backslash to the path ***/ len = strlen( libpaths[count] ); if( len == 0 ) Zoinks(); p = libpaths[count] + len - 1; if( *p == '\\' ) { hasbackslash = TRUE; } else { hasbackslash = FALSE; } /*** See if the file exists here ***/ len = strlen( libpaths[count] ) + ( hasbackslash ? 0 : 1 ) + strlen( filename ) + 1; tryme = AllocMem( len ); sprintf( tryme, "%s%s%s", libpaths[count], hasbackslash ? "" : "\\", filename ); rc = access( tryme, F_OK ); if( rc == 0 ) { return( tryme ); } else { FreeMem( tryme ); } } } return( NULL ); }
/* * Process output from the WLIB DLL. */ static int wlib_output( const char *text ) /****************************************/ { bool badness = false; if( ( strncmp( text, "Error!", 6 ) == 0 ) || ( strncmp( text, "Warning!", 8 ) == 0 ) ) { badness = true; } if( !badness ) { if( strchr( text, ' ' ) == NULL ) { InsertHash( hashtable, (void*)DupStrMem( (char*)text ) ); } return( 1 ); } else { Warning( "Message from WLIB DLL: %s", text ); return( 0 ); } }
/* * Perform fuzzy matching on the given symbol. If exactly one match is * found, a pointer to the real symbol name (in ' quotes) is returned; * the caller is responsible for freeing this memory. In all other cases, * NULL is returned. */ char *MatchFuzzy( const char *entryname ) /***************************************/ { MatchingInfo info; char * retval; char * tmp; unsigned numfound = 0; ListElem * curelem; if( hashtable == NULL ) Zoinks(); /*** Strip quotes from 'entryname' ***/ tmp = DupStrMem( entryname ); if( *tmp == '\'' ) { info.basename = DupStrMem( tmp + 1 ); info.basename[ strlen(info.basename) - 1 ] = '\0'; FreeMem( tmp ); } else { info.basename = tmp; } /*** Check for an exact match ***/ info.findmode = MATCH_MODE_EXACT; info.found = NULL; WalkBucketHash( hashtable, info.basename, matching_callback, &info ); /*** Check for _symbol ***/ if( info.found == NULL ) { info.findmode = MATCH_MODE_UNDERBAR_SYMBOL; WalkBucketHash( hashtable, info.basename, matching_callback, &info ); } /*** Check for symbol_ ***/ if( info.found == NULL ) { info.findmode = MATCH_MODE_SYMBOL_UNDERBAR; WalkBucketHash( hashtable, info.basename, matching_callback, &info ); } /*** Check for _symbol@number ***/ if( info.found == NULL ) { info.findmode = MATCH_MODE_UNDERBAR_SYMBOL_AT_NUMBER; WalkBucketHash( hashtable, info.basename, matching_callback, &info ); } /*** Count how many matches we got ***/ numfound = 0; curelem = info.found; while( curelem != NULL ) { numfound++; curelem = curelem->next; } /*** If there was more than one match, complain ***/ if( numfound > 1 ) { Warning( "Symbol with entry name %s has %u matching internal names:", entryname, numfound ); curelem = info.found; while( curelem != NULL ) { Information( "%s", curelem->buff ); curelem = curelem->next; } Information( "Symbol will be ignored!" ); } /*** Return an appropriate value ***/ if( numfound == 1 ) { retval = DupQuoteStrMem( info.found->buff, '\'' ); } else { retval = NULL; } free_list( info.found ); return( retval ); }
/* * Hash a symbol name. */ static unsigned hash_symbol_name( const void *symbol ) /****************************************************/ { char * namecopy; char * namestart; char * p; unsigned * s; unsigned len; unsigned mask; unsigned c; unsigned g; unsigned h; unsigned const namecmpmask[5] = { 0x00000000, 0x000000FF, 0x0000FFFF, 0x00FFFFFF, 0xFFFFFFFF }; /* * We want 'foo', '_foo', 'foo_', '_foo@8', and so on all to hash to * the same value, so strip off stuff from each end if necessary to * get the root name. */ namecopy = DupStrMem( symbol ); namestart = namecopy; while( *namestart == '_' ) namestart++; len = (unsigned)strlen( namestart ); if( len > 0 ) { p = namestart + len - 1; while( p >= namestart && ( isdigit(*p) || *p=='@' || *p=='_' ) ) { *p = '\0'; p--; } } /* * Ok, now do the actual hashing. */ s = (unsigned *)namestart; len = (unsigned)strlen( namestart ); h = len; c = len; if( len > sizeof( unsigned ) ) { do { c ^= *s; h = ( h << 4 ) + c; g = h & ~0x00FFFFFF; h ^= g; h ^= g >> (4+4+4+4+4); ++s; len -= sizeof( unsigned ); } while( len > sizeof( unsigned ) ); } mask = namecmpmask[ len ]; c ^= *s & mask; h = ( h << 4 ) + c; g = h & ~0x00FFFFFF; h ^= g; h ^= g >> (4+4+4+4+4); g = h & ~0x0FFF; h ^= g; h ^= g >> (4+4+4); h ^= h >> (2+4); FreeMem( namecopy ); return( h ); }
/* * Examine a file's extension to determine what type of file it is. If the * file has no extension, a warning is issued and TYPE_ASSUME_FILE is assumed. */ static int file_type( const char *filename ) /******************************************/ { char * newfilename; char * tempfilename; char ext[_MAX_EXT]; int type; /*** Strip quotes from filename ***/ newfilename = DupStrMem( filename ); if( *newfilename == '"' ) { tempfilename = newfilename + 1; /* skip leading " */ tempfilename[ strlen(tempfilename)-1 ] = '\0'; /* smite trailing " */ } else { tempfilename = newfilename; } _splitpath( tempfilename, NULL, NULL, NULL, ext ); if( allowC && !stricmp( ext, ".c" ) ) { type = TYPE_C_FILE; } else if( allowCPP && !stricmp( ext, ".cc" ) ) { type = TYPE_CPP_FILE; } else if( allowCPP && !stricmp( ext, ".cpp" ) ) { type = TYPE_CPP_FILE; } else if( allowCPP && !stricmp( ext, ".cxx" ) ) { type = TYPE_CPP_FILE; } else if( allowCPP && !stricmp( ext, ".odl" ) ) { type = TYPE_CPP_FILE; } else if( allowCPP && !stricmp( ext, ".idl" ) ) { type = TYPE_CPP_FILE; } else if( allowDEF && !stricmp( ext, ".def" ) ) { type = TYPE_DEF_FILE; } else if( allowOBJ && !stricmp( ext, ".obj" ) ) { type = TYPE_OBJ_FILE; } else if( allowLIB && !stricmp( ext, ".lib" ) ) { type = TYPE_LIB_FILE; } else if( allowRC && !stricmp( ext, ".rc" ) ) { type = TYPE_RC_FILE; } else if( allowRES && !stricmp( ext, ".res" ) ) { type = TYPE_RES_FILE; } else if( allowRBJ && !stricmp( ext, ".rbj" ) ) { type = TYPE_RBJ_FILE; } else if( allowRS && !stricmp( ext, ".rs" ) ) { type = TYPE_RS_FILE; } else if( allowEXP && !stricmp( ext, ".exp" ) ) { type = TYPE_EXP_FILE; } else { if( defaultType == TYPE_INVALID_FILE ) { Zoinks(); } if( languageToForce == FORCE_NONE ) { Warning( "Unrecognized file type '%s' -- %s file assumed", filename, defaultName ); } type = defaultType; } if( type == TYPE_C_FILE && languageToForce == FORCE_CPP_COMPILE ) { type = TYPE_CPP_FILE; } else if( type == TYPE_CPP_FILE && languageToForce == FORCE_C_COMPILE ) { type = TYPE_C_FILE; } FreeMem( newfilename ); return( type ); }
/* * Scan a string. No leading whitespace is allowed. Returns a pointer * to newly allocated memory containing the string. If leading whitespace * is found, returns NULL. Quotes embedded within a string must be escaped * by a preceding backslash; two consecutive backslashes are reduced to one. */ char *CmdScanString( void ) /*************************/ { const char quotechar = '"'; int ch; int inQuote = Quoted; /* true if inside a quoted string */ int backslash = 0; /* true if last char was a '\\' */ int start; /* context offset of string start */ char * buf = DupStrMem( "" ); size_t bufsize = 0; size_t offset = 0; /*** Return NULL if there's leading whitespace or no more data ***/ ch = GetCharContext(); if( !Quoted && isspace( ch ) ) { UngetCharContext(); return( NULL ); } else if( ch != '\0' ) { UngetCharContext(); } else { return( NULL ); } /*** Count the number of characters in the string ***/ start = GetPosContext(); for( ;; ) { ch = GetCharContext(); if( ch == 0 ) break; if( !inQuote && isspace( ch ) ) break; if( ch == quotechar ) { if( backslash ) { backslash = 0; /* handle \" within a string */ } else if( inQuote ) { if( Quoted ) { Quoted = 0; return( buf ); } inQuote = 0; /* end of a quoted portion */ } else { inQuote = 1; /* start of a quoted portion */ } buf = got_char( buf, &bufsize, offset, ch ); offset++; } else if( ch == '\\' ) { if( backslash ) { buf = got_char( buf, &bufsize, offset, ch ); offset++; backslash = 0; /* second '\\' of a pair */ if( GetCharContext() == quotechar ) buf = got_char( buf, &bufsize, offset++, '\\' ); UngetCharContext(); } else { backslash = 1; /* first '\\' of a pair */ } } else { if( backslash ) { buf = got_char( buf, &bufsize, offset, '\\' ); offset++; backslash = 0; } buf = got_char( buf, &bufsize, offset, ch ); offset++; } } if( backslash ) { /* store any leftover backslash */ buf = got_char( buf, &bufsize, offset, '\\' ); offset++; } if( ch != 0 ) UngetCharContext(); return( buf ); }