int compile_varspace( VARSPACE * n, segment * data, int additive, int copies, int padding, VARSPACE ** collision, int alignment, int duplicateignore ) { int i, j, total_count, last_count = 0 ; int base_offset = data->current ; int total_length ; int size, count ; int code ; expresion_result res ; VARIABLE * var ; int unsigned_prefix = 0; int signed_prefix = 0; BASETYPE basetype = TYPE_UNDEFINED ; TYPEDEF type, typeaux; segment * segm = NULL ; PROCDEF * proc = NULL; /* Backup vars */ BASETYPE basetypeb = TYPE_UNDEFINED ; TYPEDEF typeb; segment * segmb = NULL ; /* Initialize some stuffs */ type = typedef_new( TYPE_UNDEFINED ) ; typeb = typedef_new( TYPE_UNDEFINED ) ; for ( ;; ) { if ( n->reserved == n->count ) varspace_alloc( n, 16 ) ; if ( alignment && ( n->size % alignment ) > 0 ) { int extra = alignment - ( n->size % alignment ); if ( n->reserved <= n->count + extra ) { varspace_alloc( n, extra + 16 ); } if ( data->reserved <= data->current + extra ) { segment_alloc( data, extra + 16 ); } n->size += extra; data->current += extra; } token_next() ; /* Se salta comas y puntos y coma */ if ( token.type == NOTOKEN ) break ; if ( token.type != IDENTIFIER ) compile_error( MSG_INCOMP_TYPE ) ; if ( token.code == identifier_comma ) { basetype = basetypeb ; type = typeb ; segm = segmb ; continue ; } else if ( token.code == identifier_semicolon ) { basetype = TYPE_UNDEFINED ; set_type( &type, TYPE_UNDEFINED ) ; basetypeb = basetype ; typeb = type ; segm = NULL ; proc = NULL ; continue ; } else if ( token.code == identifier_end ) { break ; } /* "Unsigned" */ if ( token.code == identifier_unsigned ) { unsigned_prefix = 1; token_next(); } else if ( token.code == identifier_signed ) { signed_prefix = 1; token_next(); } /* Tipos de datos básicos */ if ( token.code == identifier_dword ) { basetype = signed_prefix ? TYPE_INT : TYPE_DWORD ; signed_prefix = unsigned_prefix = 0; token_next() ; } else if ( token.code == identifier_word ) { basetype = signed_prefix ? TYPE_SHORT : TYPE_WORD ; signed_prefix = unsigned_prefix = 0; token_next() ; } else if ( token.code == identifier_byte ) { basetype = signed_prefix ? TYPE_SBYTE : TYPE_BYTE ; signed_prefix = unsigned_prefix = 0; token_next() ; } else if ( token.code == identifier_int ) { basetype = unsigned_prefix ? TYPE_DWORD : TYPE_INT; signed_prefix = unsigned_prefix = 0; token_next() ; } else if ( token.code == identifier_short ) { basetype = unsigned_prefix ? TYPE_WORD : TYPE_SHORT; signed_prefix = unsigned_prefix = 0; token_next() ; } else if ( token.code == identifier_char ) { basetype = TYPE_CHAR ; token_next() ; } else if ( token.code == identifier_float ) { basetype = TYPE_FLOAT ; token_next() ; } else if ( token.code == identifier_string ) { basetype = TYPE_STRING ; token_next() ; } else { if ( !proc && ( proc = procdef_search( token.code ) ) ) /* Variables tipo proceso, Splinter */ { basetype = TYPE_INT ; token_next(); } else { if ( token.type == IDENTIFIER && token.code >= reserved_words && !segment_by_name( token.code ) ) { int code = token.code; token_next(); if ( token.type == IDENTIFIER && token.code >= reserved_words ) { proc = procdef_new( procdef_getid(), code ); basetype = TYPE_INT ; } else { token_back(); } } } } if ( signed_prefix || unsigned_prefix ) compile_error( MSG_INVALID_TYPE ); if ( basetype != TYPE_STRUCT ) type = typedef_new( basetype ) ; if ( basetype == TYPE_UNDEFINED ) type = typedef_new( TYPE_INT ) ; /* Tipos de datos definidos por el usuario */ if ( basetype != TYPE_STRUCT && ( segm = segment_by_name( token.code ) ) ) { basetype = TYPE_STRUCT ; type = * typedef_by_name( token.code ) ; token_next() ; } if ( token.type == IDENTIFIER && token.code == identifier_struct ) { type.chunk[0].type = TYPE_STRUCT ; type.chunk[0].count = 1 ; type.depth = 1 ; token_next() ; segm = 0 ; } basetypeb = basetype ; typeb = type ; segmb = segm ; /* Tipos de datos derivados */ while ( token.type == IDENTIFIER && ( token.code == identifier_pointer || token.code == identifier_multiply ) ) { type = typedef_enlarge( type ) ; type.chunk[0].type = TYPE_POINTER ; basetype = TYPE_POINTER ; segm = NULL ; token_next() ; } /* Nombre del dato */ if ( token.type != IDENTIFIER ) compile_error( MSG_IDENTIFIER_EXP ) ; if ( token.code < reserved_words ) { if ( proc ) compile_error( MSG_VARIABLE_ERROR ); token_back() ; break ; } if (( var = varspace_search( n, token.code ) ) ) { if ( duplicateignore ) { int skip_all_until_semicolon = 0; int skip_equal = 0; if ( debug ) compile_warning( 0, MSG_VARIABLE_REDECLARE ) ; for ( ;; ) { token_next() ; /* Se salta todo hasta el puntos y coma o en el end o la coma si no hay asignacion */ if ( token.type == NOTOKEN ) break ; if ( token.type == IDENTIFIER ) { if ( !skip_equal && token.code == identifier_equal ) { skip_all_until_semicolon = 1; continue; } if ( !skip_all_until_semicolon && token.code == identifier_comma ) break; if ( token.code == identifier_semicolon ) break ; if ( token.code == identifier_end ) break ; } } token_back(); continue; } else compile_error( MSG_VARIABLE_REDECLARE ) ; } /* (2006/11/19 19:34 GMT-03:00, Splinter - [email protected]) */ if ( collision ) for ( i = 0; collision[i];i++ ) if ( varspace_search( collision[i], token.code ) ) compile_error( MSG_VARIABLE_REDECLARE ) ; /* (2006/11/19 19:34 GMT-03:00, Splinter - [email protected]) */ if ( constants_search( token.code ) ) compile_error( MSG_CONSTANT_REDECLARED_AS_VARIABLE ) ; code = token.code ; n->vars[n->count].code = token.code ; n->vars[n->count].offset = data->current; /* Non-additive STRUCT; use zero-based member offsets */ if ( !additive ) n->vars[n->count].offset -= base_offset; token_next() ; /* Compila una estructura no predefinida */ if ( !segm && typedef_is_struct( type ) ) { VARSPACE * members ; type.chunk[0].count = 1 ; count = 1 ; while ( token.type == IDENTIFIER && token.code == identifier_leftb ) { res = compile_expresion( 1, 0, 0, TYPE_INT ) ; if ( !typedef_is_integer( res.type ) ) compile_error( MSG_INTEGER_REQUIRED ) ; count *= res.value + 1 ; type = typedef_enlarge( type ) ; type.chunk[0].type = TYPE_ARRAY ; type.chunk[0].count = res.value + 1 ; token_next() ; if ( token.type != IDENTIFIER || token.code != identifier_rightb ) compile_error( MSG_EXPECTED, "]" ) ; token_next() ; } token_back() ; /* Da la vuelta a los índices [10][5] -> [5][10] */ for ( i = 0 ; i < type.depth ; i++ ) if ( type.chunk[i].type != TYPE_ARRAY ) break ; i--; for ( j = 0 ; j <= i ; j++ ) typeaux.chunk[ j ] = type.chunk[ i - j ]; for ( j = 0 ; j <= i ; j++ ) type.chunk[ j ] = typeaux.chunk[ j ]; members = ( VARSPACE * )calloc( 1, sizeof( VARSPACE ) ) ; if ( !members ) { fprintf( stdout, "compile_varspace: out of memory\n" ) ; exit( 1 ) ; } varspace_init( members ) ; size = compile_varspace( members, data, 0, count, 0, NULL, 0, duplicateignore ) ; type.varspace = members ; token_next() ; if ( token.type == IDENTIFIER && token.code == identifier_equal ) { i = data->current ; data->current = n->vars[n->count].offset ; compile_struct_data( members, data, count, 0 ); data->current = i ; } else { token_back() ; } for ( i = 0 ; i < members->stringvar_count ; i++ ) varspace_varstring( n, members->stringvars[i] ) ; n->size += typedef_size( type ) ; n->vars[n->count].type = type ; n->count++ ; continue ; /* No ; */ } else if ( token.type == IDENTIFIER && token.code == identifier_leftb ) /* Compila un array */ { total_count = 1 ; while ( token.type == IDENTIFIER && token.code == identifier_leftb ) { if ( type.depth == MAX_TYPECHUNKS ) compile_error( MSG_TOO_MANY_AL ) ; type = typedef_enlarge( type ) ; type.chunk[0].type = TYPE_ARRAY ; token_next() ; if ( token.type == IDENTIFIER && token.code == identifier_rightb ) { type.chunk[0].count = 0 ; if ( total_count != 1 ) compile_error( MSG_VTA ) ; total_count = 0 ; last_count = 0 ; } else { token_back() ; res = compile_expresion( 1, 0, 0, TYPE_DWORD ) ; if ( !total_count ) compile_error( MSG_VTA ) ; total_count *= res.value + 1 ; last_count = res.value + 1 ; type.chunk[0].count = res.value + 1 ; token_next() ; if ( token.type != IDENTIFIER || token.code != identifier_rightb ) compile_error( MSG_EXPECTED, "]" ) ; } token_next() ; } /* Da la vuelta a los índices [10][5] -> [5][10] */ for ( i = 0 ; i < type.depth ; i++ ) if ( type.chunk[i].type != TYPE_ARRAY ) break ; i--; for ( j = 0 ; j <= i ; j++ ) typeaux.chunk[ j ] = type.chunk[ i - j ]; for ( j = 0 ; j <= i ; j++ ) type.chunk[ j ] = typeaux.chunk[ j ]; if ( segm && token.type == IDENTIFIER && token.code == identifier_equal ) { for ( i = 0 ; i < total_count ; i++ ) segment_add_from( data, segm ) ; i = data->current ; data->current = n->vars[n->count].offset ; compile_struct_data( type.varspace, data, typedef_count( type ), 0 ); if ( !type.chunk[0].count ) type.chunk[0].count = ( data->current - i ) / typedef_size( typeb ); else data->current = i; /* Solo si ya habia sido alocada */ } else if ( token.type == IDENTIFIER && token.code == identifier_equal ) { /* if (basetype == TYPE_UNDEFINED) basetype = TYPE_INT; */ i = compile_array_data( n, data, total_count, last_count, &basetype ) ; assert( basetype != TYPE_UNDEFINED ) ; set_type( &type, basetype ) ; if ( total_count == 0 ) { type.chunk[0].count = i; } else if ( i < total_count ) { for ( ; i < total_count; i++ ) { if ( basetype == TYPE_STRING ) varspace_varstring( n, data->current ) ; segment_add_as( data, 0, basetype ) ; } } } else if ( segm ) { int string_offset = 0, j; if ( total_count == 0 ) compile_error( MSG_EXPECTED, "=" ) ; for ( i = 0; i < total_count; i++ ) { segment_add_from( data, segm ) ; for ( j = 0; j < type.varspace->stringvar_count; j++ ) varspace_varstring( n, type.varspace->stringvars[j] + string_offset ); string_offset += type.varspace->size; } token_back() ; } else { if ( basetype == TYPE_UNDEFINED ) { basetype = TYPE_INT; set_type( &type, basetype ) ; } if ( type.chunk[0].count == 0 ) compile_error( MSG_EXPECTED, "=" ) ; for ( i = 0; i < total_count; i++ ) { if ( basetype == TYPE_STRING ) varspace_varstring( n, data->current ) ; segment_add_as( data, 0, basetype ) ; } token_back() ; } } else if ( segm && token.type == IDENTIFIER && token.code == identifier_equal ) /* Compila una asignación de valores por defecto */ { segment_add_from( data, segm ) ; i = data->current ; data->current = n->vars[n->count].offset ; if ( !additive ) data->current += base_offset; compile_struct_data( type.varspace, data, 1, 0 ); data->current = i ; } else if ( token.type == IDENTIFIER && token.code == identifier_equal ) { res = compile_expresion( 1, 0, 0, basetype ) ; if ( basetype == TYPE_UNDEFINED ) { basetype = typedef_base( res.type ) ; if ( basetype == TYPE_UNDEFINED ) compile_error( MSG_INCOMP_TYPE ) ; set_type( &type, basetype ) ; } if ( basetype == TYPE_FLOAT ) { segment_add_as( data, *( int * )&res.fvalue, basetype ) ; } else { if ( basetype == TYPE_STRING ) varspace_varstring( n, data->current ) ; segment_add_as( data, res.value, basetype ) ; } } else if ( !segm ) /* Asigna valores por defecto (0) */ { if ( basetype == TYPE_UNDEFINED ) { basetype = TYPE_INT; set_type( &type, basetype ) ; } if ( basetype == TYPE_STRING ) varspace_varstring( n, data->current ) ; segment_add_as( data, 0, basetype ) ; token_back() ; } else { if ( typedef_is_struct( type ) ) for ( i = 0 ; i < type.varspace->stringvar_count ; i++ ) varspace_varstring( n, type.varspace->stringvars[i] + n->size ); segment_add_from( data, segm ) ; token_back() ; } n->size += typedef_size( type ) ; n->vars[n->count].type = type ; /* Variables tipo proceso, asigno varspace al tipo. Splinter */ if ( proc ) n->vars[n->count].type.varspace = proc->pubvars; n->count++ ; token_next() ; if ( token.type == IDENTIFIER && token.code == identifier_comma ) { token_back() ; continue ; } if ( token.type == IDENTIFIER && token.code == identifier_semicolon ) { token_back() ; continue ; } compile_error( MSG_EXPECTED, ";" ) ; token_back() ; break ; } if ( padding && ( data->current % padding ) > 0 ) { padding -= data->current % padding; data->current += padding; n->size += padding; if ( data->reserved <= data->current ) segment_alloc( data, data->reserved - data->current + 32 ); } n->last_offset = data->current ; total_length = data->current - base_offset ; /* n->size *= copies ; */ while ( copies-- > 1 ) { int i ; for ( i = 0 ; i < n->stringvar_count ; i++ ) { if ( n->stringvars[i] >= base_offset && n->stringvars[i] < base_offset + total_length ) { varspace_varstring( n, n->stringvars[i] - base_offset + data->current ) ; } } segment_copy( data, base_offset, total_length ) ; base_offset += total_length ; } return total_length ; }
int main( int argc, char *argv[] ) { time_t curtime; struct tm *loctime; int value, code; char * d, *d1; char * sourcefile = 0; char basepathname[__MAX_PATH] = ""; char dcbname[__MAX_PATH] = ""; char stubname[__MAX_PATH] = ""; char importname[__MAX_PATH] = ""; char compilerimport[__MAX_PATH] = ""; int i, j; char *ptr; /* get my executable name */ ptr = argv[0] + strlen( argv[0] ); while ( ptr > argv[0] && ptr[-1] != '\\' && ptr[-1] != '/' ) ptr-- ; appexename = strdup( ptr ); /* get executable full pathname */ appexefullpath = getfullpath( argv[0] ); if ( ( !strchr( argv[0], '\\' ) && !strchr( argv[0], '/' ) ) && !file_exists( appexefullpath ) ) { char *p = whereis( appexename ); if ( p ) { char * tmp = calloc( 1, strlen( p ) + strlen( appexename ) + 2 ); free( appexefullpath ); sprintf( tmp, "%s/%s", p, appexename ); appexefullpath = getfullpath( tmp ); free( tmp ); } } /* get pathname of executable */ ptr = strstr( appexefullpath, appexename ); appexepath = calloc( 1, ptr - appexefullpath + 1 ); strncpy( appexepath, appexefullpath, ptr - appexefullpath ); printf( BGDC_VERSION "\n" "Bennu Game Development Compiler\n" "\n" "Copyright (c) 2006-2016 SplinterGU (Fenix/BennuGD)\n" "Copyright (c) 2002-2006 Fenix Team (Fenix)\n" "Copyright (c) 1999-2002 José Luis Cebrián Pagüe (Fenix)\n" "\n" ); /* Default lang to EN */ strcpy( langinfo, "EN" ); /* LANG detect */ #ifdef WIN32 GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_SABBREVCTRYNAME, langinfo, 64 ); strlwr( langinfo ); #else if ( getenv( "LANG" ) != NULL && strlen( getenv( "LANG" ) ) >= 2 ) strcpy( langinfo, getenv( "LANG" ) ); #endif langinfo[2] = 0; srand( time( NULL ) ); /* build error messages list */ err_buildErrorTable(); init_c_type(); identifier_init(); constants_init(); string_init(); compile_init(); mainproc = procdef_new( procdef_getid(), identifier_search_or_add( "MAIN" ) ) ; /* Init vars */ char tmp_version[ 32 ]; sprintf( tmp_version, "\"%s\"", VERSION ); add_simple_define( "COMPILER_VERSION", tmp_version ); add_simple_define( "__VERSION__", tmp_version ); curtime = time( NULL ); /* Get the current time. */ loctime = localtime( &curtime ); /* Convert it to local time representation. */ strftime( timebuff, sizeof( timebuff ), "%Y/%m/%d", loctime ); value = string_new( timebuff ); code = identifier_search_or_add( "__DATE__" ) ; constants_add( code, typedef_new( TYPE_STRING ), value ) ; strftime( timebuff, sizeof( timebuff ), "%H:%M:%S", loctime ); value = string_new( timebuff ); code = identifier_search_or_add( "__TIME__" ) ; constants_add( code, typedef_new( TYPE_STRING ), value ) ; /* value = string_new( VERSION ); code = identifier_search_or_add( "__VERSION__" ) ; constants_add( code, typedef_new( TYPE_STRING ), value ) ; code = identifier_search_or_add( "COMPILER_VERSION" ) ; constants_add( code, typedef_new( TYPE_STRING ), value ) ; */ strcpy( _tmp, VERSION ); d = strchr( _tmp, '.' ); *d = '\0'; add_simple_define( "__BGD__", _tmp ); d1 = d + 1; d = strchr( d1, '.' ); *d = '\0'; add_simple_define( "__BGD_MINOR__", d1 ); d1 = d + 1; add_simple_define( "__BGD_PATCHLEVEL__", d1 ); memset( &dcb, 0, sizeof( dcb ) ); core_init(); sysproc_init(); /* Get command line parameters */ for ( i = 1 ; i < argc ; i++ ) { if ( argv[i][0] == '-' ) { if ( !strcmp( argv[i], "--pedantic" ) ) { autodeclare = 0 ; continue; } if ( !strcmp( argv[i], "--libmode" ) ) { libmode = 1 ; continue; } j = 1; while ( argv[i][j] ) { if ( argv[i][j] == 'd' ) { if ( argv[i][j + 1] >= '0' && argv[i][j + 1] <= '9' ) { debug = atoi( &argv[i][j + 1] ); } else { debug = 1; } } if ( argv[i][j] == 'o' ) { if ( argv[i][j + 1] ) strncpy( dcbname, &argv[i][j + 1], sizeof( dcbname ) ); else if ( argv[i + 1] && argv[i + 1][0] != '-' ) strncpy( dcbname, argv[++i], sizeof( dcbname ) ); break; } if ( argv[i][j] == 'c' ) dos_chars = 1; if ( argv[i][j] == 'a' ) autoinclude = 1; if ( argv[i][j] == 'g' ) dcb_options |= DCB_DEBUG; if ( argv[i][j] == 'p' ) autodeclare = 0 ; if ( argv[i][j] == 's' ) { /* -s "stub": Use a stub */ if ( argv[i][j + 1] ) strncpy( stubname, &argv[i][j + 1], __MAX_PATH ); else if ( argv[i + 1] && argv[i + 1][0] != '-' ) strncpy( stubname, argv[++i], __MAX_PATH ); break; } if ( argv[i][j] == 'f' ) { /* -f "file": Embed a file to the DCB */ if ( argv[i][j + 1] ) dcb_add_file( &argv[i][j + 1] ); else while ( argv[i + 1] ) { if ( argv[i + 1][0] == '-' ) break; dcb_add_file( argv[i + 1] ); i++; } break; } if ( argv[i][j] == 'i' ) { /* -i "path": add a file to the path for include files */ if ( argv[i][j + 1] == 0 ) { if ( i == argc - 1 ) { printf( MSG_DIRECTORY_MISSING "\n" ); exit( 1 ); } file_addp( argv[i + 1] ); i++; break; } file_addp( &argv[i][j + 1] ); break; } if ( argv[i][j] == 'l' ) { /* -lLANG: Set the language for errors and messages */ if ( argv[i][j + 1] == 0 ) { if ( i != argc - 1 ) { strcpy( langinfo, argv[i + 1] ); } i++; break; } strcpy( langinfo, &argv[i][j + 1] ); break; } if ( argv[i][j] == 'D' ) { char * macro = NULL ; char * text = NULL ; /* -D<macro>=<text> */ if ( argv[i][j + 1] ) { macro = strdup( &argv[i][j + 1] ); } else { if ( argv[i + 1][0] == '-' ) break; macro = strdup( argv[i + 1] ); i++; } if (( text = strchr( macro, '=' ) ) ) { * text = '\0'; text++; } else { text = ""; } add_simple_define( macro, text ); free( macro ); break; } if ( argv[i][j] == 'C' ) { if ( argv[i][j + 1] == 'a' ) autodeclare = 1 ; break; } if ( argv[i][j] == 'L' ) { int r = 1; char * f; if ( argv[i][j + 1] ) r = dcb_load_lib( ( f = &argv[i][j + 1] ) ); else if ( argv[i + 1] && argv[i + 1][0] != '-' ) { r = dcb_load_lib( ( f = argv[i + 1] ) ); i++; } switch ( r ) { case 0: printf( "ERROR: %s doesn't exist or isn't version DCB compatible\n", f ) ; exit( -1 ); case -1: printf( "ERROR: %s isn't 7.10 DCB version, you need a 7.10 version or greater for use this feature\n", f ) ; exit( -1 ); } break; } j++; } } else { /* if ( sourcefile ) { printf( MSG_TOO_MANY_FILES "\n" ); return 0; } */ char * p, * pathend = NULL; sourcefile = argv[i]; p = main_path = strdup( argv[i] ); while ( p && *p ) { if ( *p == ':' || *p == '\\' || *p == '/' ) pathend = p; p++; } if ( pathend ) { *( pathend + 1 ) = '\0'; file_addp( main_path ); } else { free( main_path ); main_path = getcwd(malloc(__MAX_PATH), __MAX_PATH); strcat(main_path, PATH_SEP); } /* Files names */ strcpy( basepathname, sourcefile ); REMOVE_EXT( basepathname ); /* Default compiler imports */ strcpy( compilerimport, argv[0] ); #ifdef WIN32 REMOVE_EXT( compilerimport ); #endif strcat( compilerimport, ".imp" ); import_files( compilerimport ); strcat( compilerimport, "ort" ); /* name.import */ import_files( compilerimport ); /* Project imports */ strcpy( importname, basepathname ); strcat( importname, ".imp" ); import_files( importname ); strcat( importname, "ort" ); /* name.import */ import_files( importname ); /* Load Main Source File */ load_file( sourcefile ); if ( !dcbname[0] ) { strcpy( dcbname, basepathname ); strcat( dcbname, !libmode ? ".dcb" : ".dcl" ); } } } if ( !sourcefile ) { printf( MSG_USING MSG_OPTION_D MSG_OPTIONS MSG_LICENSE, argv[0] ); return 0; } compile_program(); if ( stubname[0] != 0 ) { if ( !file_exists( stubname ) ) { #ifdef WIN32 char exepath[__MAX_PATH]; GetModuleFileName( NULL, exepath, sizeof( exepath ) ); PathRemoveFileSpec( exepath ); strcat( exepath, "\\" ); memmove( stubname + strlen( exepath ), stubname, strlen( stubname ) + 1 ); memcpy( stubname, exepath, strlen( exepath ) ); #else const char * ptr = argv[0] + strlen( argv[0] ); while ( ptr > argv[0] && *ptr != '\\' && *ptr != '/' ) ptr--; if ( *ptr == '\\' || *ptr == '/' ) ptr++; if ( ptr > argv[0] ) { memmove( stubname + ( ptr - argv[0] ), stubname, strlen( stubname ) + 1 ); memcpy( stubname, argv[0], ptr - argv[0] ); } #endif if ( !file_exists( stubname ) ) { #ifdef WIN32 strcat( stubname, ".exe" ); if ( !file_exists( stubname ) ) { #endif compile_error( "Can't open stub file %s", stubname ); #ifdef WIN32 return -1; } #endif } } REMOVE_EXT( dcbname ); #ifdef WIN32 strcat( dcbname, ".exe" ); #endif dcb_save( dcbname, dcb_options, stubname ); } else { dcb_save( dcbname, dcb_options, NULL ); } /* destroy error messages list */ err_destroyErrorTable(); return 1; }