diff options
author | tma <tma@edf5b092-35ff-0310-97b2-ce42778d08ea> | 2005-10-04 18:34:21 +0000 |
---|---|---|
committer | tma <tma@edf5b092-35ff-0310-97b2-ce42778d08ea> | 2005-10-04 18:34:21 +0000 |
commit | 5406eab4f3e101162b2d8c9ef4e9ea66333e2462 (patch) | |
tree | e0c955134d3be535e7dc4c3423b7351e8cfd63d7 /code/tools/q3asm/q3asm.c | |
parent | 1f56a39f925eba4140d78883fb646f17aeab9e54 (diff) | |
download | ioquake3-aero-5406eab4f3e101162b2d8c9ef4e9ea66333e2462.tar.gz ioquake3-aero-5406eab4f3e101162b2d8c9ef4e9ea66333e2462.zip |
* Added install/uninstall rules to the lcc and q3asm Makefiles
* Moved the q3asm dir to asm so that is doesn't clash with the binary when
installed
git-svn-id: svn://svn.icculus.org/quake3/trunk@136 edf5b092-35ff-0310-97b2-ce42778d08ea
Diffstat (limited to 'code/tools/q3asm/q3asm.c')
-rw-r--r-- | code/tools/q3asm/q3asm.c | 1047 |
1 files changed, 0 insertions, 1047 deletions
diff --git a/code/tools/q3asm/q3asm.c b/code/tools/q3asm/q3asm.c deleted file mode 100644 index b19c361..0000000 --- a/code/tools/q3asm/q3asm.c +++ /dev/null @@ -1,1047 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "cmdlib.h" -#include "mathlib.h" -#include "qfiles.h" - -/* MSVC-ism fix. */ -#define atoi(s) strtoul(s,NULL,10) - -char outputFilename[MAX_OS_PATH]; - -// the zero page size is just used for detecting run time faults -#define ZERO_PAGE_SIZE 0 // 256 - -typedef enum { - OP_UNDEF, - - OP_IGNORE, - - OP_BREAK, - - OP_ENTER, - OP_LEAVE, - OP_CALL, - OP_PUSH, - OP_POP, - - OP_CONST, - OP_LOCAL, - - OP_JUMP, - - //------------------- - - OP_EQ, - OP_NE, - - OP_LTI, - OP_LEI, - OP_GTI, - OP_GEI, - - OP_LTU, - OP_LEU, - OP_GTU, - OP_GEU, - - OP_EQF, - OP_NEF, - - OP_LTF, - OP_LEF, - OP_GTF, - OP_GEF, - - //------------------- - - OP_LOAD1, - OP_LOAD2, - OP_LOAD4, - OP_STORE1, - OP_STORE2, - OP_STORE4, // *(stack[top-1]) = stack[yop - OP_ARG, - OP_BLOCK_COPY, - - //------------------- - - OP_SEX8, - OP_SEX16, - - OP_NEGI, - OP_ADD, - OP_SUB, - OP_DIVI, - OP_DIVU, - OP_MODI, - OP_MODU, - OP_MULI, - OP_MULU, - - OP_BAND, - OP_BOR, - OP_BXOR, - OP_BCOM, - - OP_LSH, - OP_RSHI, - OP_RSHU, - - OP_NEGF, - OP_ADDF, - OP_SUBF, - OP_DIVF, - OP_MULF, - - OP_CVIF, - OP_CVFI -} opcode_t; - -typedef struct { - int imageBytes; // after decompression - int entryPoint; - int stackBase; - int stackSize; -} executableHeader_t; - -typedef enum { - CODESEG, - DATASEG, // initialized 32 bit data, will be byte swapped - LITSEG, // strings - BSSSEG, // 0 filled - NUM_SEGMENTS -} segmentName_t; - -#define MAX_IMAGE 0x400000 - -typedef struct { - byte image[MAX_IMAGE]; - int imageUsed; - int segmentBase; // only valid on second pass -} segment_t; - -typedef struct symbol_s { - struct symbol_s *next; - int hash; - segment_t *segment; - char *name; - int value; -} symbol_t; - - -segment_t segment[NUM_SEGMENTS]; -segment_t *currentSegment; - -int passNumber; - -int numSymbols; -int errorCount; - -symbol_t *symbols; -symbol_t *lastSymbol; - - -#define MAX_ASM_FILES 256 -int numAsmFiles; -char *asmFiles[MAX_ASM_FILES]; -char *asmFileNames[MAX_ASM_FILES]; - -int currentFileIndex; -char *currentFileName; -int currentFileLine; - -//int stackSize = 16384; -int stackSize = 0x10000; - -// we need to convert arg and ret instructions to -// stores to the local stack frame, so we need to track the -// characteristics of the current functions stack frame -int currentLocals; // bytes of locals needed by this function -int currentArgs; // bytes of largest argument list called from this function -int currentArgOffset; // byte offset in currentArgs to store next arg, reset each call - -#define MAX_LINE_LENGTH 1024 -char lineBuffer[MAX_LINE_LENGTH]; -int lineParseOffset; -char token[MAX_LINE_LENGTH]; - -int instructionCount; - -typedef struct { - char *name; - int opcode; -} sourceOps_t; - -sourceOps_t sourceOps[] = { -#include "opstrings.h" -}; - -#define NUM_SOURCE_OPS ( sizeof( sourceOps ) / sizeof( sourceOps[0] ) ) - -int opcodesHash[ NUM_SOURCE_OPS ]; - - -/* -============= -HashString -============= -*/ -int HashString( char *s ) { - int v = 0; - - while ( *s ) { - v += *s; - s++; - } - return v; -} - - -/* -============ -CodeError -============ -*/ -void CodeError( char *fmt, ... ) { - va_list argptr; - - errorCount++; - - printf( "%s:%i ", currentFileName, currentFileLine ); - - va_start( argptr,fmt ); - vprintf( fmt,argptr ); - va_end( argptr ); -} - -/* -============ -EmitByte -============ -*/ -void EmitByte( segment_t *seg, int v ) { - if ( seg->imageUsed >= MAX_IMAGE ) { - Error( "MAX_IMAGE" ); - } - seg->image[ seg->imageUsed ] = v; - seg->imageUsed++; -} - -/* -============ -EmitInt -============ -*/ -void EmitInt( segment_t *seg, int v ) { - if ( seg->imageUsed >= MAX_IMAGE - 4) { - Error( "MAX_IMAGE" ); - } - seg->image[ seg->imageUsed ] = v & 255; - seg->image[ seg->imageUsed + 1 ] = ( v >> 8 ) & 255; - seg->image[ seg->imageUsed + 2 ] = ( v >> 16 ) & 255; - seg->image[ seg->imageUsed + 3 ] = ( v >> 24 ) & 255; - seg->imageUsed += 4; -} - -/* -============ -DefineSymbol - -Symbols can only be defined on pass 0 -============ -*/ -void DefineSymbol( char *sym, int value ) { - symbol_t *s, *after; - char expanded[MAX_LINE_LENGTH]; - int hash; - - if ( passNumber == 1 ) { - return; - } - - // TTimo - // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=381 - // as a security, bail out if vmMain entry point is not first - if (!Q_stricmp(sym, "vmMain")) - if (value) - Error( "vmMain must be the first symbol in the qvm (got offset %d)\n", value ); - - // add the file prefix to local symbols to guarantee unique - if ( sym[0] == '$' ) { - sprintf( expanded, "%s_%i", sym, currentFileIndex ); - sym = expanded; - } - - hash = HashString( sym ); - - for ( s = symbols ; s ; s = s->next ) { - if ( hash == s->hash && !strcmp( sym, s->name ) ) { - CodeError( "Multiple definitions for %s\n", sym ); - return; - } - } - - s = malloc( sizeof( *s ) ); - s->name = copystring( sym ); - s->hash = hash; - s->value = value; - s->segment = currentSegment; - - lastSymbol = s; /* for the move-to-lit-segment byteswap hack */ - - // insert it in order - if ( !symbols || s->value < symbols->value ) { - s->next = symbols; - symbols = s; - return; - } - - for ( after = symbols ; after->next && after->next->value < value ; after = after->next ) { - } - s->next = after->next; - after->next = s; -} - - -/* -============ -LookupSymbol - -Symbols can only be evaluated on pass 1 -============ -*/ -int LookupSymbol( char *sym ) { - symbol_t *s; - char expanded[MAX_LINE_LENGTH]; - int hash; - - if ( passNumber == 0 ) { - return 0; - } - - // add the file prefix to local symbols to guarantee unique - if ( sym[0] == '$' ) { - sprintf( expanded, "%s_%i", sym, currentFileIndex ); - sym = expanded; - } - - hash = HashString( sym ); - for ( s = symbols ; s ; s = s->next ) { - if ( hash == s->hash && !strcmp( sym, s->name ) ) { - return s->segment->segmentBase + s->value; - } - } - - CodeError( "ERROR: symbol %s undefined\n", sym ); - passNumber = 0; - DefineSymbol( sym, 0 ); // so more errors aren't printed - passNumber = 1; - return 0; -} - - -/* -============== -ExtractLine - -Extracts the next line from the given text block. -If a full line isn't parsed, returns NULL -Otherwise returns the updated parse pointer -=============== -*/ -char *ExtractLine( char *data ) { - int i; - - currentFileLine++; - lineParseOffset = 0; - token[0] = 0; - - if ( data[0] == 0 ) { - lineBuffer[0] = 0; - return NULL; - } - - for ( i = 0 ; i < MAX_LINE_LENGTH ; i++ ) { - if ( data[i] == 0 || data[i] == '\n' ) { - break; - } - } - if ( i == MAX_LINE_LENGTH ) { - CodeError( "MAX_LINE_LENGTH" ); - return data; - } - memcpy( lineBuffer, data, i ); - lineBuffer[i] = 0; - data += i; - if ( data[0] == '\n' ) { - data++; - } - return data; -} - - -/* -============== -Parse - -Parse a token out of linebuffer -============== -*/ -qboolean Parse( void ) { - int c; - int len; - - len = 0; - token[0] = 0; - - // skip whitespace - while ( lineBuffer[ lineParseOffset ] <= ' ' ) { - if ( lineBuffer[ lineParseOffset ] == 0 ) { - return qfalse; - } - lineParseOffset++; - } - - // skip ; comments - c = lineBuffer[ lineParseOffset ]; - if ( c == ';' ) { - return qfalse; - } - - - // parse a regular word - do { - token[len] = c; - len++; - lineParseOffset++; - c = lineBuffer[ lineParseOffset ]; - } while (c>32); - - token[len] = 0; - return qtrue; -} - - -/* -============== -ParseValue -============== -*/ -int ParseValue( void ) { - Parse(); - return atoi( token ); -} - - -/* -============== -ParseExpression -============== -*/ -int ParseExpression(void) { - int i, j; - char sym[MAX_LINE_LENGTH]; - int v; - - if ( token[0] == '-' ) { - i = 1; - } else { - i = 0; - } - - for ( ; i < MAX_LINE_LENGTH ; i++ ) { - if ( token[i] == '+' || token[i] == '-' || token[i] == 0 ) { - break; - } - } - - memcpy( sym, token, i ); - sym[i] = 0; - - if ( ( sym[0] >= '0' && sym[0] <= '9' ) || sym[0] == '-' ) { - v = atoi( sym ); - } else { - v = LookupSymbol( sym ); - } - - // parse add / subtract offsets - while ( token[i] != 0 ) { - for ( j = i + 1 ; j < MAX_LINE_LENGTH ; j++ ) { - if ( token[j] == '+' || token[j] == '-' || token[j] == 0 ) { - break; - } - } - - memcpy( sym, token+i+1, j-i-1 ); - sym[j-i-1] = 0; - - if ( token[i] == '+' ) { - v += atoi( sym ); - } - if ( token[i] == '-' ) { - v -= atoi( sym ); - } - i = j; - } - - return v; -} - - -/* -============== -HackToSegment - -BIG HACK: I want to put all 32 bit values in the data -segment so they can be byte swapped, and all char data in the lit -segment, but switch jump tables are emited in the lit segment and -initialized strng variables are put in the data segment. - -I can change segments here, but I also need to fixup the -label that was just defined - -Note that the lit segment is read-write in the VM, so strings -aren't read only as in some architectures. -============== -*/ -void HackToSegment( segmentName_t seg ) { - if ( currentSegment == &segment[seg] ) { - return; - } - - currentSegment = &segment[seg]; - if ( passNumber == 0 ) { - lastSymbol->segment = currentSegment; - lastSymbol->value = currentSegment->imageUsed; - } -} - -/* -============== -AssembleLine - -============== -*/ -void AssembleLine( void ) { - int v, v2; - int i; - int hash; - - Parse(); - if ( !token[0] ) { - return; - } - - hash = HashString( token ); - - for ( i = 0 ; i < NUM_SOURCE_OPS ; i++ ) { - if ( hash == opcodesHash[i] && !strcmp( token, sourceOps[i].name ) ) { - int opcode; - int expression; - - if ( sourceOps[i].opcode == OP_UNDEF ) { - CodeError( "Undefined opcode: %s\n", token ); - } - if ( sourceOps[i].opcode == OP_IGNORE ) { - return; // we ignore most conversions - } - - // sign extensions need to check next parm - opcode = sourceOps[i].opcode; - if ( opcode == OP_SEX8 ) { - Parse(); - if ( token[0] == '1' ) { - opcode = OP_SEX8; - } else if ( token[0] == '2' ) { - opcode = OP_SEX16; - } else { - CodeError( "Bad sign extension: %s\n", token ); - return; - } - } - - // check for expression - Parse(); - if ( token[0] && sourceOps[i].opcode != OP_CVIF - && sourceOps[i].opcode != OP_CVFI ) { - expression = ParseExpression(); - - // code like this can generate non-dword block copies: - // auto char buf[2] = " "; - // we are just going to round up. This might conceivably - // be incorrect if other initialized chars follow. - if ( opcode == OP_BLOCK_COPY ) { - expression = ( expression + 3 ) & ~3; - } - - EmitByte( &segment[CODESEG], opcode ); - EmitInt( &segment[CODESEG], expression ); - } else { - EmitByte( &segment[CODESEG], opcode ); - } - - instructionCount++; - return; - } - } - - // call instructions reset currentArgOffset - if ( !strncmp( token, "CALL", 4 ) ) { - EmitByte( &segment[CODESEG], OP_CALL ); - instructionCount++; - currentArgOffset = 0; - return; - } - - // arg is converted to a reversed store - if ( !strncmp( token, "ARG", 3 ) ) { - EmitByte( &segment[CODESEG], OP_ARG ); - instructionCount++; - if ( 8 + currentArgOffset >= 256 ) { - CodeError( "currentArgOffset >= 256" ); - return; - } - EmitByte( &segment[CODESEG], 8 + currentArgOffset ); - currentArgOffset += 4; - return; - } - - // ret just leaves something on the op stack - if ( !strncmp( token, "RET", 3 ) ) { - EmitByte( &segment[CODESEG], OP_LEAVE ); - instructionCount++; - EmitInt( &segment[CODESEG], 8 + currentLocals + currentArgs ); - return; - } - - // pop is needed to discard the return value of - // a function - if ( !strncmp( token, "pop", 3 ) ) { - EmitByte( &segment[CODESEG], OP_POP ); - instructionCount++; - return; - } - - // address of a parameter is converted to OP_LOCAL - if ( !strncmp( token, "ADDRF", 5 ) ) { - instructionCount++; - Parse(); - v = ParseExpression(); - v = 16 + currentArgs + currentLocals + v; - EmitByte( &segment[CODESEG], OP_LOCAL ); - EmitInt( &segment[CODESEG], v ); - return; - } - - // address of a local is converted to OP_LOCAL - if ( !strncmp( token, "ADDRL", 5 ) ) { - instructionCount++; - Parse(); - v = ParseExpression(); - v = 8 + currentArgs + v; - EmitByte( &segment[CODESEG], OP_LOCAL ); - EmitInt( &segment[CODESEG], v ); - return; - } - - if ( !strcmp( token, "proc" ) ) { - char name[1024]; - - Parse(); // function name - strcpy( name, token ); - - DefineSymbol( token, instructionCount ); // segment[CODESEG].imageUsed ); - - currentLocals = ParseValue(); // locals - currentLocals = ( currentLocals + 3 ) & ~3; - currentArgs = ParseValue(); // arg marshalling - currentArgs = ( currentArgs + 3 ) & ~3; - - if ( 8 + currentLocals + currentArgs >= 32767 ) { - CodeError( "Locals > 32k in %s\n", name ); - } - - instructionCount++; - EmitByte( &segment[CODESEG], OP_ENTER ); - EmitInt( &segment[CODESEG], 8 + currentLocals + currentArgs ); - return; - } - if ( !strcmp( token, "endproc" ) ) { - Parse(); // skip the function name - v = ParseValue(); // locals - v2 = ParseValue(); // arg marshalling - - // all functions must leave something on the opstack - instructionCount++; - EmitByte( &segment[CODESEG], OP_PUSH ); - - instructionCount++; - EmitByte( &segment[CODESEG], OP_LEAVE ); - EmitInt( &segment[CODESEG], 8 + currentLocals + currentArgs ); - - return; - } - - - if ( !strcmp( token, "address" ) ) { - Parse(); - v = ParseExpression(); - - HackToSegment( DATASEG ); - EmitInt( currentSegment, v ); - return; - } - if ( !strcmp( token, "export" ) ) { - return; - } - if ( !strcmp( token, "import" ) ) { - return; - } - if ( !strcmp( token, "code" ) ) { - currentSegment = &segment[CODESEG]; - return; - } - if ( !strcmp( token, "bss" ) ) { - currentSegment = &segment[BSSSEG]; - return; - } - if ( !strcmp( token, "data" ) ) { - currentSegment = &segment[DATASEG]; - return; - } - if ( !strcmp( token, "lit" ) ) { - currentSegment = &segment[LITSEG]; - return; - } - if ( !strcmp( token, "line" ) ) { - return; - } - if ( !strcmp( token, "file" ) ) { - return; - } - - if ( !strcmp( token, "equ" ) ) { - char name[1024]; - - Parse(); - strcpy( name, token ); - Parse(); - DefineSymbol( name, atoi(token) ); - return; - } - - if ( !strcmp( token, "align" ) ) { - v = ParseValue(); - currentSegment->imageUsed = (currentSegment->imageUsed + v - 1 ) & ~( v - 1 ); - return; - } - - if ( !strcmp( token, "skip" ) ) { - v = ParseValue(); - currentSegment->imageUsed += v; - return; - } - - if ( !strcmp( token, "byte" ) ) { - v = ParseValue(); - v2 = ParseValue(); - - if ( v == 1 ) { - HackToSegment( LITSEG ); - } else if ( v == 4 ) { - HackToSegment( DATASEG ); - } else if ( v == 2 ) { - CodeError( "16 bit initialized data not supported" ); - } - - // emit little endien - for ( i = 0 ; i < v ; i++ ) { - EmitByte( currentSegment, v2 ); - v2 >>= 8; - } - return; - } - - // code labels are emited as instruction counts, not byte offsets, - // because the physical size of the code will change with - // different run time compilers and we want to minimize the - // size of the required translation table - if ( !strncmp( token, "LABEL", 5 ) ) { - Parse(); - if ( currentSegment == &segment[CODESEG] ) { - DefineSymbol( token, instructionCount ); - } else { - DefineSymbol( token, currentSegment->imageUsed ); - } - return; - } - - CodeError( "Unknown token: %s\n", token ); -} - -/* -============== -InitTables -============== -*/ -void InitTables( void ) { - int i; - - for ( i = 0 ; i < NUM_SOURCE_OPS ; i++ ) { - opcodesHash[i] = HashString( sourceOps[i].name ); - } -} - - -/* -============== -WriteMapFile -============== -*/ -void WriteMapFile( void ) { - FILE *f; - symbol_t *s; - char imageName[MAX_OS_PATH]; - int seg; - - strcpy( imageName, outputFilename ); - StripExtension( imageName ); - strcat( imageName, ".map" ); - - printf( "Writing %s...\n", imageName ); - f = SafeOpenWrite( imageName ); - for ( seg = CODESEG ; seg <= BSSSEG ; seg++ ) { - for ( s = symbols ; s ; s = s->next ) { - if ( s->name[0] == '$' ) { - continue; // skip locals - } - if ( &segment[seg] != s->segment ) { - continue; - } - fprintf( f, "%i %8x %s\n", seg, s->value, s->name ); - } - } - fclose( f ); -} - -/* -=============== -WriteVmFile -=============== -*/ -void WriteVmFile( void ) { - char imageName[MAX_OS_PATH]; - vmHeader_t header; - FILE *f; - - printf( "%i total errors\n", errorCount ); - strcpy( imageName, outputFilename ); - StripExtension( imageName ); - strcat( imageName, ".qvm" ); - - remove( imageName ); - - printf( "code segment: %7i\n", segment[CODESEG].imageUsed ); - printf( "data segment: %7i\n", segment[DATASEG].imageUsed ); - printf( "lit segment: %7i\n", segment[LITSEG].imageUsed ); - printf( "bss segment: %7i\n", segment[BSSSEG].imageUsed ); - printf( "instruction count: %i\n", instructionCount ); - if ( errorCount != 0 ) { - printf( "Not writing a file due to errors\n" ); - return; - } - - header.vmMagic = VM_MAGIC; - header.instructionCount = instructionCount; - header.codeOffset = sizeof( header ); - header.codeLength = segment[CODESEG].imageUsed; - header.dataOffset = header.codeOffset + segment[CODESEG].imageUsed; - header.dataLength = segment[DATASEG].imageUsed; - header.litLength = segment[LITSEG].imageUsed; - header.bssLength = segment[BSSSEG].imageUsed; - - printf( "Writing to %s\n", imageName ); - - CreatePath( imageName ); - f = SafeOpenWrite( imageName ); - SafeWrite( f, &header, sizeof( header ) ); - SafeWrite( f, &segment[CODESEG].image, segment[CODESEG].imageUsed ); - SafeWrite( f, &segment[DATASEG].image, segment[DATASEG].imageUsed ); - SafeWrite( f, &segment[LITSEG].image, segment[LITSEG].imageUsed ); - fclose( f ); -} - -/* -=============== -Assemble -=============== -*/ -void Assemble( void ) { - int i; - char filename[MAX_OS_PATH]; - char *ptr; - - printf( "outputFilename: %s\n", outputFilename ); - - for ( i = 0 ; i < numAsmFiles ; i++ ) { - strcpy( filename, asmFileNames[ i ] ); - DefaultExtension( filename, ".asm" ); - LoadFile( filename, (void **)&asmFiles[i] ); - } - - // assemble - for ( passNumber = 0 ; passNumber < 2 ; passNumber++ ) { - segment[LITSEG].segmentBase = segment[DATASEG].imageUsed; - segment[BSSSEG].segmentBase = segment[LITSEG].segmentBase + segment[LITSEG].imageUsed; - for ( i = 0 ; i < NUM_SEGMENTS ; i++ ) { - segment[i].imageUsed = 0; - } - segment[DATASEG].imageUsed = 4; // skip the 0 byte, so NULL pointers are fixed up properly - instructionCount = 0; - - for ( i = 0 ; i < numAsmFiles ; i++ ) { - currentFileIndex = i; - currentFileName = asmFileNames[ i ]; - currentFileLine = 0; - printf("pass %i: %s\n", passNumber, currentFileName ); - ptr = asmFiles[i]; - while ( ptr ) { - ptr = ExtractLine( ptr ); - AssembleLine(); - } - } - - // align all segment - for ( i = 0 ; i < NUM_SEGMENTS ; i++ ) { - segment[i].imageUsed = (segment[i].imageUsed + 3) & ~3; - } - } - - // reserve the stack in bss - DefineSymbol( "_stackStart", segment[BSSSEG].imageUsed ); - segment[BSSSEG].imageUsed += stackSize; - DefineSymbol( "_stackEnd", segment[BSSSEG].imageUsed ); - - // write the image - WriteVmFile(); - - // write the map file even if there were errors - WriteMapFile(); -} - - -/* -============= -ParseOptionFile - -============= -*/ -void ParseOptionFile( const char *filename ) { - char expanded[MAX_OS_PATH]; - char *text, *text_p; - - strcpy( expanded, filename ); - DefaultExtension( expanded, ".q3asm" ); - LoadFile( expanded, (void **)&text ); - if ( !text ) { - return; - } - - text_p = text; - - while( ( text_p = COM_Parse( text_p ) ) != 0 ) { - if ( !strcmp( com_token, "-o" ) ) { - // allow output override in option file - text_p = COM_Parse( text_p ); - if ( text_p ) { - strcpy( outputFilename, com_token ); - } - continue; - } - - asmFileNames[ numAsmFiles ] = copystring( com_token ); - numAsmFiles++; - } -} - -/* -============== -main -============== -*/ -int main( int argc, char **argv ) { - int i; - double start, end; - -// _chdir( "/quake3/jccode/cgame/lccout" ); // hack for vc profiler - - if ( argc < 2 ) { - Error( "usage: q3asm [-o output] <files> or q3asm -f <listfile>\n" ); - } - - start = I_FloatTime (); - InitTables(); - - // default filename is "q3asm" - strcpy( outputFilename, "q3asm" ); - numAsmFiles = 0; - - for ( i = 1 ; i < argc ; i++ ) { - if ( argv[i][0] != '-' ) { - break; - } - if ( !strcmp( argv[i], "-o" ) ) { - if ( i == argc - 1 ) { - Error( "-o must preceed a filename" ); - } - strcpy( outputFilename, argv[ i+1 ] ); - i++; - continue; - } - - if ( !strcmp( argv[i], "-f" ) ) { - if ( i == argc - 1 ) { - Error( "-f must preceed a filename" ); - } - ParseOptionFile( argv[ i+1 ] ); - i++; - continue; - } - Error( "Unknown option: %s", argv[i] ); - } - - // the rest of the command line args are asm files - for ( ; i < argc ; i++ ) { - asmFileNames[ numAsmFiles ] = copystring( argv[ i ] ); - numAsmFiles++; - } - - Assemble(); - - end = I_FloatTime (); - printf ("%5.0f seconds elapsed\n", end-start); - - return 0; -} - |