2004-08-23 01:38:21 +00:00
# ifndef MINIMAL
# include "qcc.h"
# ifdef QCC
# define print printf
# endif
2005-04-02 18:00:45 +00:00
# include "time.h"
2004-08-23 01:38:21 +00:00
2012-01-04 16:08:33 +00:00
# ifdef _WIN64
2012-01-04 16:51:50 +00:00
# ifdef _SDL
# define snprintf linuxlike_snprintf
int VARGS linuxlike_snprintf ( char * buffer , int size , const char * format , . . . ) LIKEPRINTF ( 3 ) ;
# define vsnprintf linuxlike_vsnprintf
int VARGS linuxlike_vsnprintf ( char * buffer , int size , const char * format , va_list argptr ) ;
//void *__imp__vsnprintf = vsnprintf;
# endif
2012-01-04 16:08:33 +00:00
# endif
2004-08-23 01:38:21 +00:00
# define MEMBERFIELDNAME "__m%s"
# define STRCMP(s1,s2) (((*s1)!=(*s2)) || strcmp(s1+1,s2+1)) //saves about 2-6 out of 120 - expansion of idea from fastqcc
void QCC_PR_ConditionCompilation ( void ) ;
pbool QCC_PR_UndefineName ( char * name ) ;
char * QCC_PR_CheakCompConstString ( char * def ) ;
CompilerConstant_t * QCC_PR_CheckCompConstDefined ( char * def ) ;
pbool QCC_Include ( char * filename ) ;
char * compilingfile ;
int pr_source_line ;
char * pr_file_p ;
char * pr_line_start ; // start of current source line
int pr_bracelevel ;
char pr_token [ 8192 ] ;
token_type_t pr_token_type ;
QCC_type_t * pr_immediate_type ;
QCC_eval_t pr_immediate ;
char pr_immediate_string [ 8192 ] ;
int pr_error_count ;
2005-12-16 17:15:43 +00:00
int pr_warning_count ;
2004-08-23 01:38:21 +00:00
CompilerConstant_t * CompilerConstant ;
int numCompilerConstants ;
2008-11-09 22:29:28 +00:00
extern pbool expandedemptymacro ;
2004-08-23 01:38:21 +00:00
char * pr_punctuation [ ] =
// longer symbols must be before a shorter partial match
2008-11-09 22:29:28 +00:00
{ " && " , " || " , " <= " , " >= " , " == " , " != " , " /= " , " *= " , " += " , " -= " , " (+) " , " (-) " , " |= " , " &~= " , " ++ " , " -- " , " -> " , " :: " , " ; " , " , " , " ! " , " * " , " / " , " ( " , " ) " , " - " , " + " , " = " , " [ " , " ] " , " { " , " } " , " ... " , " .. " , " . " , " << " , " < " , " >> " , " > " , " ? " , " # " , " @ " , " & " , " | " , " ^ " , " : " , NULL } ;
2004-11-18 17:55:04 +00:00
char * pr_punctuationremap [ ] = //a nice bit of evilness.
2008-11-09 22:29:28 +00:00
//(+) -> |=
2004-11-18 17:55:04 +00:00
//-> -> .
2008-11-09 22:29:28 +00:00
//(-) -> &~=
{ " && " , " || " , " <= " , " >= " , " == " , " != " , " /= " , " *= " , " += " , " -= " , " |= " , " &~= " , " |= " , " &~= " , " ++ " , " -- " , " . " , " :: " , " ; " , " , " , " ! " , " * " , " / " , " ( " , " ) " , " - " , " + " , " = " , " [ " , " ] " , " { " , " } " , " ... " , " .. " , " . " , " << " , " < " , " >> " , " > " , " ? " , " # " , " @ " , " & " , " | " , " ^ " , " : " , NULL } ;
2004-08-23 01:38:21 +00:00
// simple types. function types are dynamically allocated
QCC_type_t * type_void ; // = {ev_void/*, &def_void*/};
QCC_type_t * type_string ; // = {ev_string/*, &def_string*/};
QCC_type_t * type_float ; // = {ev_float/*, &def_float*/};
QCC_type_t * type_vector ; // = {ev_vector/*, &def_vector*/};
QCC_type_t * type_entity ; // = {ev_entity/*, &def_entity*/};
QCC_type_t * type_field ; // = {ev_field/*, &def_field*/};
QCC_type_t * type_function ; // = {ev_function/*, &def_function*/,NULL,&type_void};
// type_function is a void() function used for state defs
QCC_type_t * type_pointer ; // = {ev_pointer/*, &def_pointer*/};
QCC_type_t * type_integer ; // = {ev_integer/*, &def_integer*/};
2005-02-28 07:16:19 +00:00
QCC_type_t * type_variant ; // = {ev_integer/*, &def_integer*/};
2004-08-23 01:38:21 +00:00
QCC_type_t * type_floatfield ; // = {ev_field/*, &def_field*/, NULL, &type_float};
/*QCC_def_t def_void = {type_void, "temp"};
QCC_def_t def_string = { type_string , " temp " } ;
QCC_def_t def_float = { type_float , " temp " } ;
QCC_def_t def_vector = { type_vector , " temp " } ;
QCC_def_t def_entity = { type_entity , " temp " } ;
QCC_def_t def_field = { type_field , " temp " } ;
QCC_def_t def_function = { type_function , " temp " } ;
QCC_def_t def_pointer = { type_pointer , " temp " } ;
QCC_def_t def_integer = { type_integer , " temp " } ;
*/
QCC_def_t def_ret , def_parms [ MAX_PARMS ] ;
//QCC_def_t *def_for_type[9] = {&def_void, &def_string, &def_float, &def_vector, &def_entity, &def_field, &def_function, &def_pointer, &def_integer};
void QCC_PR_LexWhitespace ( void ) ;
//for compiler constants and file includes.
qcc_includechunk_t * currentchunk ;
2008-01-27 01:14:44 +00:00
void QCC_PR_IncludeChunkEx ( char * data , pbool duplicate , char * filename , CompilerConstant_t * cnst )
2004-08-23 01:38:21 +00:00
{
qcc_includechunk_t * chunk = qccHunkAlloc ( sizeof ( qcc_includechunk_t ) ) ;
chunk - > prev = currentchunk ;
currentchunk = chunk ;
chunk - > currentdatapoint = pr_file_p ;
chunk - > currentlinenumber = pr_source_line ;
2008-01-27 01:14:44 +00:00
chunk - > cnst = cnst ;
if ( cnst )
{
cnst - > inside + + ;
}
2004-08-23 01:38:21 +00:00
if ( duplicate )
{
pr_file_p = qccHunkAlloc ( strlen ( data ) + 1 ) ;
strcpy ( pr_file_p , data ) ;
}
else
pr_file_p = data ;
}
2008-01-27 01:14:44 +00:00
void QCC_PR_IncludeChunk ( char * data , pbool duplicate , char * filename )
{
QCC_PR_IncludeChunkEx ( data , duplicate , filename , NULL ) ;
}
2004-08-23 01:38:21 +00:00
pbool QCC_PR_UnInclude ( void )
{
if ( ! currentchunk )
return false ;
2008-01-27 01:14:44 +00:00
if ( currentchunk - > cnst )
currentchunk - > cnst - > inside - - ;
2004-08-23 01:38:21 +00:00
pr_file_p = currentchunk - > currentdatapoint ;
pr_source_line = currentchunk - > currentlinenumber ;
currentchunk = currentchunk - > prev ;
return true ;
}
/*
= = = = = = = = = = = = = =
PR_PrintNextLine
= = = = = = = = = = = = = =
*/
void QCC_PR_PrintNextLine ( void )
{
char * t ;
printf ( " %3i: " , pr_source_line ) ;
for ( t = pr_line_start ; * t & & * t ! = ' \n ' ; t + + )
printf ( " %c " , * t ) ;
printf ( " \n " ) ;
}
2005-08-27 05:45:45 +00:00
extern char qccmsourcedir [ ] ;
//also meant to include it.
void QCC_FindBestInclude ( char * newfile , char * currentfile , char * rootpath )
{
2010-07-03 21:49:48 +00:00
char fullname [ 1024 ] ;
2006-03-23 19:22:12 +00:00
int doubledots ;
2005-08-27 05:45:45 +00:00
char * end = fullname ;
if ( ! * newfile )
return ;
2006-03-23 19:22:12 +00:00
doubledots = 0 ;
2011-05-20 04:10:46 +00:00
/*count how far up we need to go*/
2006-03-23 19:22:12 +00:00
while ( ! strncmp ( newfile , " ../ " , 3 ) | | ! strncmp ( newfile , " .. \\ " , 3 ) )
{
newfile + = 3 ;
doubledots + + ;
}
2005-09-08 22:52:46 +00:00
currentfile + = strlen ( rootpath ) ; //could this be bad?
2011-05-20 04:10:46 +00:00
strcpy ( fullname , rootpath ) ;
end = fullname + strlen ( end ) ;
if ( * fullname & & end [ - 1 ] ! = ' / ' )
{
strcpy ( end , " / " ) ;
end = end + strlen ( end ) ;
}
strcpy ( end , currentfile ) ;
end = end + strlen ( end ) ;
while ( end > fullname )
2005-08-27 05:45:45 +00:00
{
2011-05-20 04:10:46 +00:00
end - - ;
/*stop at the slash, unless we're meant to go further*/
if ( * end = = ' / ' | | * end = = ' \\ ' )
2006-03-23 19:22:12 +00:00
{
2011-05-20 04:10:46 +00:00
if ( ! doubledots )
2006-03-23 19:22:12 +00:00
{
2011-05-20 04:10:46 +00:00
end + + ;
2006-03-23 19:22:12 +00:00
break ;
}
2011-05-20 04:10:46 +00:00
doubledots - - ;
2006-03-23 19:22:12 +00:00
}
2005-08-27 05:45:45 +00:00
}
2011-05-20 04:10:46 +00:00
2005-08-27 05:45:45 +00:00
strcpy ( end , newfile ) ;
QCC_Include ( fullname ) ;
}
2010-05-01 22:47:47 +00:00
pbool defaultnoref ;
2009-03-29 23:47:29 +00:00
pbool defaultstatic ;
2004-08-23 01:38:21 +00:00
int ForcedCRC ;
int QCC_PR_LexInteger ( void ) ;
void QCC_AddFile ( char * filename ) ;
void QCC_PR_LexString ( void ) ;
pbool QCC_PR_SimpleGetToken ( void ) ;
2005-02-28 07:16:19 +00:00
2008-10-16 23:04:36 +00:00
int ParsePrecompilerIf ( void )
{
CompilerConstant_t * c ;
2011-05-15 13:23:13 +00:00
int eval = 0 ;
2011-11-08 06:00:35 +00:00
pbool notted = false ;
/*skip whitespace*/
while ( * pr_file_p & & * pr_file_p < = ' ' & & * pr_file_p ! = ' \n ' )
{
pr_file_p + + ;
}
if ( * pr_file_p = = ' ! ' )
{
pr_file_p + + ;
notted = true ;
while ( * pr_file_p & & * pr_file_p < = ' ' & & * pr_file_p ! = ' \n ' )
{
pr_file_p + + ;
}
}
2008-10-16 23:04:36 +00:00
if ( ! QCC_PR_SimpleGetToken ( ) )
2010-12-08 14:42:05 +00:00
{
2008-10-16 23:04:36 +00:00
if ( * pr_file_p = = ' ( ' )
{
2011-11-08 06:00:35 +00:00
pr_file_p + + ;
2008-10-16 23:04:36 +00:00
eval = ParsePrecompilerIf ( ) ;
while ( * pr_file_p = = ' ' | | * pr_file_p = = ' \t ' )
pr_file_p + + ;
if ( * pr_file_p ! = ' ) ' )
QCC_PR_ParseError ( ERR_EXPECTED , " unclosed bracket condition \n " ) ;
2011-11-08 06:00:35 +00:00
pr_file_p + + ;
2008-10-16 23:04:36 +00:00
}
else
QCC_PR_ParseError ( ERR_EXPECTED , " expected bracket or constant \n " ) ;
}
else if ( ! strcmp ( pr_token , " defined " ) )
{
while ( * pr_file_p = = ' ' | | * pr_file_p = = ' \t ' )
pr_file_p + + ;
if ( * pr_file_p ! = ' ( ' )
QCC_PR_ParseError ( ERR_EXPECTED , " no opening bracket after defined \n " ) ;
else
{
pr_file_p + + ;
QCC_PR_SimpleGetToken ( ) ;
eval = ! ! QCC_PR_CheckCompConstDefined ( pr_token ) ;
while ( * pr_file_p = = ' ' | | * pr_file_p = = ' \t ' )
pr_file_p + + ;
if ( * pr_file_p ! = ' ) ' )
QCC_PR_ParseError ( ERR_EXPECTED , " unclosed defined condition \n " ) ;
pr_file_p + + ;
}
}
else
{
c = QCC_PR_CheckCompConstDefined ( pr_token ) ;
if ( ! c )
2009-05-24 10:11:17 +00:00
eval = atoi ( pr_token ) ;
2008-10-16 23:04:36 +00:00
else
eval = atoi ( c - > value ) ;
}
2011-11-08 06:00:35 +00:00
if ( notted )
eval = ! eval ;
2008-10-16 23:04:36 +00:00
QCC_PR_SimpleGetToken ( ) ;
if ( ! strcmp ( pr_token , " || " ) )
eval = ParsePrecompilerIf ( ) | | eval ;
else if ( ! strcmp ( pr_token , " && " ) )
eval = ParsePrecompilerIf ( ) & & eval ;
else if ( ! strcmp ( pr_token , " <= " ) )
eval = eval < = ParsePrecompilerIf ( ) ;
else if ( ! strcmp ( pr_token , " >= " ) )
eval = eval > = ParsePrecompilerIf ( ) ;
else if ( ! strcmp ( pr_token , " < " ) )
eval = eval < ParsePrecompilerIf ( ) ;
else if ( ! strcmp ( pr_token , " > " ) )
eval = eval > ParsePrecompilerIf ( ) ;
else if ( ! strcmp ( pr_token , " != " ) )
eval = eval ! = ParsePrecompilerIf ( ) ;
return eval ;
}
2005-02-28 07:16:19 +00:00
/*
= = = = = = = = = = = = = =
QCC_PR_Precompiler
= = = = = = = = = = = = = =
Runs precompiler stage
*/
pbool QCC_PR_Precompiler ( void )
2004-08-23 01:38:21 +00:00
{
char msg [ 1024 ] ;
int ifmode ;
int a ;
static int ifs = 0 ;
int level ; //#if level
pbool eval = false ;
2005-02-28 07:16:19 +00:00
if ( * pr_file_p = = ' # ' )
2004-08-23 01:38:21 +00:00
{
2004-10-14 11:24:13 +00:00
char * directive ;
2005-02-28 07:16:19 +00:00
for ( directive = pr_file_p + 1 ; * directive ; directive + + ) //so # define works
2004-08-23 01:38:21 +00:00
{
2004-10-14 11:24:13 +00:00
if ( * directive = = ' \r ' | | * directive = = ' \n ' )
QCC_PR_ParseError ( ERR_UNKNOWNPUCTUATION , " Hanging # with no directive \n " ) ;
if ( * directive > ' ' )
break ;
2004-08-23 01:38:21 +00:00
}
2004-10-14 11:24:13 +00:00
if ( ! strncmp ( directive , " define " , 6 ) )
2004-08-23 01:38:21 +00:00
{
2004-10-14 11:24:13 +00:00
pr_file_p = directive ;
QCC_PR_ConditionCompilation ( ) ;
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
{
pr_file_p + + ;
}
2004-08-23 01:38:21 +00:00
}
2004-10-14 11:24:13 +00:00
else if ( ! strncmp ( directive , " undef " , 5 ) )
2004-08-23 01:38:21 +00:00
{
2004-10-14 11:24:13 +00:00
pr_file_p = directive + 5 ;
while ( * pr_file_p < = ' ' )
pr_file_p + + ;
QCC_PR_SimpleGetToken ( ) ;
QCC_PR_UndefineName ( pr_token ) ;
// QCC_PR_ConditionCompilation();
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
{
pr_file_p + + ;
}
2004-08-23 01:38:21 +00:00
}
2004-10-14 11:24:13 +00:00
else if ( ! strncmp ( directive , " if " , 2 ) )
2004-08-23 01:38:21 +00:00
{
2005-07-28 15:52:31 +00:00
int originalline = pr_source_line ;
2004-10-14 11:24:13 +00:00
pr_file_p = directive + 2 ;
if ( ! strncmp ( pr_file_p , " def " , 4 ) )
{
ifmode = 0 ;
pr_file_p + = 4 ;
}
else if ( ! strncmp ( pr_file_p , " ndef " , 5 ) )
{
ifmode = 1 ;
pr_file_p + = 5 ;
}
else
{
ifmode = 2 ;
pr_file_p + = 0 ;
//QCC_PR_ParseError("bad \"#if\" type");
}
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
if ( ifmode = = 2 )
{
2008-10-16 23:04:36 +00:00
eval = ParsePrecompilerIf ( ) ;
if ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
{
QCC_PR_ParseError ( ERR_NOENDIF , " junk on the end of #if line " ) ;
}
2004-10-14 11:24:13 +00:00
}
else
{
2008-10-16 23:04:36 +00:00
QCC_PR_SimpleGetToken ( ) ;
2004-10-14 11:24:13 +00:00
// if (!STRCMP(pr_token, "COOP_MODE"))
// eval = false;
if ( QCC_PR_CheckCompConstDefined ( pr_token ) )
eval = true ;
2004-08-23 01:38:21 +00:00
2005-02-28 07:16:19 +00:00
if ( ifmode = = 1 )
2010-12-08 14:42:05 +00:00
eval = eval ? false : true ;
2004-10-14 11:24:13 +00:00
}
2004-08-23 01:38:21 +00:00
2008-10-16 23:04:36 +00:00
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
{
pr_file_p + + ;
}
level = 1 ;
2004-10-14 11:24:13 +00:00
if ( eval )
ifs + = 1 ;
else
{
while ( 1 )
{
2004-11-04 04:19:10 +00:00
while ( * pr_file_p & & ( * pr_file_p = = ' ' | | * pr_file_p = = ' \t ' ) )
2004-10-14 11:24:13 +00:00
pr_file_p + + ;
2004-11-04 04:19:10 +00:00
if ( ! * pr_file_p )
{
2005-07-28 15:52:31 +00:00
pr_source_line = originalline ;
2004-11-04 04:19:10 +00:00
QCC_PR_ParseError ( ERR_NOENDIF , " #if with no endif " ) ;
}
2004-10-14 11:24:13 +00:00
if ( * pr_file_p = = ' # ' )
{
pr_file_p + + ;
while ( * pr_file_p = = ' ' | | * pr_file_p = = ' \t ' )
pr_file_p + + ;
if ( ! strncmp ( pr_file_p , " endif " , 5 ) )
level - - ;
if ( ! strncmp ( pr_file_p , " if " , 2 ) )
level + + ;
if ( ! strncmp ( pr_file_p , " else " , 4 ) & & level = = 1 )
{
ifs + = 1 ;
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
{
pr_file_p + + ;
}
break ;
}
}
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
{
pr_file_p + + ;
}
if ( level < = 0 )
break ;
pr_file_p + + ; //next line
pr_source_line + + ;
}
}
}
else if ( ! strncmp ( directive , " else " , 4 ) )
2004-08-23 01:38:21 +00:00
{
2005-07-28 15:52:31 +00:00
int originalline = pr_source_line ;
2004-11-04 04:19:10 +00:00
2004-10-14 11:24:13 +00:00
ifs - = 1 ;
level = 1 ;
2005-02-28 07:16:19 +00:00
2004-10-14 11:24:13 +00:00
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
{
pr_file_p + + ;
}
2004-08-23 01:38:21 +00:00
while ( 1 )
{
2004-11-04 04:19:10 +00:00
while ( * pr_file_p & & ( * pr_file_p = = ' ' | | * pr_file_p = = ' \t ' ) )
2004-08-23 01:38:21 +00:00
pr_file_p + + ;
2004-11-04 04:19:10 +00:00
if ( ! * pr_file_p )
{
2005-07-28 15:52:31 +00:00
pr_source_line = originalline ;
2004-11-04 04:19:10 +00:00
QCC_PR_ParseError ( ERR_NOENDIF , " #if with no endif " ) ;
}
2004-10-14 11:24:13 +00:00
if ( * pr_file_p = = ' # ' )
2004-08-23 01:38:21 +00:00
{
2004-10-14 11:24:13 +00:00
pr_file_p + + ;
while ( * pr_file_p = = ' ' | | * pr_file_p = = ' \t ' )
2004-08-23 01:38:21 +00:00
pr_file_p + + ;
2004-10-14 11:24:13 +00:00
if ( ! strncmp ( pr_file_p , " endif " , 5 ) )
level - - ;
if ( ! strncmp ( pr_file_p , " if " , 2 ) )
level + + ;
if ( ! strncmp ( pr_file_p , " else " , 4 ) & & level = = 1 )
{
ifs + = 1 ;
break ;
2004-08-23 01:38:21 +00:00
}
}
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
{
pr_file_p + + ;
}
if ( level < = 0 )
break ;
2004-10-14 11:24:13 +00:00
pr_file_p + + ; //go off the end
2004-08-23 01:38:21 +00:00
pr_source_line + + ;
}
}
2004-10-14 11:24:13 +00:00
else if ( ! strncmp ( directive , " endif " , 5 ) )
2010-12-08 14:42:05 +00:00
{
2004-10-14 11:24:13 +00:00
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
{
pr_file_p + + ;
2010-12-08 14:42:05 +00:00
}
2004-10-14 11:24:13 +00:00
if ( ifs < = 0 )
QCC_PR_ParseError ( ERR_NOPRECOMPILERIF , " unmatched #endif " ) ;
else
ifs - = 1 ;
2004-08-23 01:38:21 +00:00
}
2004-10-14 11:24:13 +00:00
else if ( ! strncmp ( directive , " eof " , 3 ) )
2004-08-23 01:38:21 +00:00
{
2004-10-14 11:24:13 +00:00
pr_file_p = NULL ;
2005-02-28 07:16:19 +00:00
return true ;
2004-10-14 11:24:13 +00:00
}
else if ( ! strncmp ( directive , " error " , 5 ) )
2010-12-08 14:42:05 +00:00
{
2004-10-14 11:24:13 +00:00
pr_file_p = directive + 5 ;
2010-07-03 21:49:48 +00:00
for ( a = 0 ; a < sizeof ( msg ) - 1 & & pr_file_p [ a ] ! = ' \n ' & & pr_file_p [ a ] ! = ' \0 ' ; a + + )
2004-10-14 11:24:13 +00:00
msg [ a ] = pr_file_p [ a ] ;
2011-11-08 06:00:35 +00:00
msg [ a ] = ' \0 ' ;
2004-10-14 11:24:13 +00:00
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line, yes, I KNOW we are going to register an error, and not properly leave this function tree, but...
2004-08-23 01:38:21 +00:00
{
2004-10-14 11:24:13 +00:00
pr_file_p + + ;
2004-08-23 01:38:21 +00:00
}
2004-10-14 11:24:13 +00:00
QCC_PR_ParseError ( ERR_HASHERROR , " #Error: %s " , msg ) ;
}
else if ( ! strncmp ( directive , " warning " , 7 ) )
2010-12-08 14:42:05 +00:00
{
2004-10-14 11:24:13 +00:00
pr_file_p = directive + 7 ;
for ( a = 0 ; a < 1023 & & pr_file_p [ a ] ! = ' \n ' & & pr_file_p [ a ] ! = ' \0 ' ; a + + )
msg [ a ] = pr_file_p [ a ] ;
msg [ a - 1 ] = ' \0 ' ;
2004-08-23 01:38:21 +00:00
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
{
pr_file_p + + ;
}
2004-10-14 11:24:13 +00:00
QCC_PR_ParseWarning ( WARN_PRECOMPILERMESSAGE , " #warning: %s " , msg ) ;
2004-08-23 01:38:21 +00:00
}
2004-10-14 11:24:13 +00:00
else if ( ! strncmp ( directive , " message " , 7 ) )
2010-12-08 14:42:05 +00:00
{
2004-10-14 11:24:13 +00:00
pr_file_p = directive + 7 ;
for ( a = 0 ; a < 1023 & & pr_file_p [ a ] ! = ' \n ' & & pr_file_p [ a ] ! = ' \0 ' ; a + + )
msg [ a ] = pr_file_p [ a ] ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
msg [ a - 1 ] = ' \0 ' ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
{
pr_file_p + + ;
}
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
printf ( " #message: %s \n " , msg ) ;
2004-08-23 01:38:21 +00:00
}
2004-10-14 11:24:13 +00:00
else if ( ! strncmp ( directive , " copyright " , 9 ) )
{
pr_file_p = directive + 9 ;
2010-07-03 21:49:48 +00:00
for ( a = 0 ; a < sizeof ( msg ) - 1 & & pr_file_p [ a ] ! = ' \n ' & & pr_file_p [ a ] ! = ' \0 ' ; a + + )
2004-10-14 11:24:13 +00:00
msg [ a ] = pr_file_p [ a ] ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
msg [ a - 1 ] = ' \0 ' ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
{
pr_file_p + + ;
}
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
if ( strlen ( msg ) > = sizeof ( QCC_copyright ) )
QCC_PR_ParseWarning ( WARN_STRINGTOOLONG , " Copyright message is too long \n " ) ;
strncpy ( QCC_copyright , msg , sizeof ( QCC_copyright ) - 1 ) ;
2004-08-23 01:38:21 +00:00
}
2004-10-14 11:24:13 +00:00
else if ( ! strncmp ( directive , " pack " , 4 ) )
{
ifmode = 0 ;
pr_file_p = directive + 4 ;
if ( ! strncmp ( pr_file_p , " id " , 2 ) )
pr_file_p + = 3 ;
2010-12-08 14:42:05 +00:00
else
2004-10-14 11:24:13 +00:00
{
2010-12-08 14:42:05 +00:00
ifmode = QCC_PR_LexInteger ( ) ;
2004-10-14 11:24:13 +00:00
if ( ifmode = = 0 )
ifmode = 1 ;
pr_file_p + + ;
}
2010-07-03 21:49:48 +00:00
for ( a = 0 ; a < sizeof ( msg ) - 1 & & pr_file_p [ a ] ! = ' \n ' & & pr_file_p [ a ] ! = ' \0 ' ; a + + )
2004-10-14 11:24:13 +00:00
msg [ a ] = pr_file_p [ a ] ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
msg [ a - 1 ] = ' \0 ' ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
{
pr_file_p + + ;
}
2004-08-23 01:38:21 +00:00
if ( ifmode = = 0 )
2004-10-14 11:24:13 +00:00
QCC_packid = atoi ( msg ) ;
else if ( ifmode < = 5 )
strcpy ( QCC_Packname [ ifmode - 1 ] , msg ) ;
else
2010-12-08 14:42:05 +00:00
QCC_PR_ParseError ( ERR_TOOMANYPACKFILES , " No more than 5 packs are allowed " ) ;
2004-08-23 01:38:21 +00:00
}
2004-10-14 11:24:13 +00:00
else if ( ! strncmp ( directive , " forcecrc " , 8 ) )
2010-12-08 14:42:05 +00:00
{
2004-10-14 11:24:13 +00:00
pr_file_p = directive + 8 ;
2004-08-23 01:38:21 +00:00
2010-12-08 14:42:05 +00:00
ForcedCRC = QCC_PR_LexInteger ( ) ;
2004-08-23 01:38:21 +00:00
pr_file_p + + ;
2010-12-08 14:42:05 +00:00
2010-07-03 21:49:48 +00:00
for ( a = 0 ; a < sizeof ( msg ) - 1 & & pr_file_p [ a ] ! = ' \n ' & & pr_file_p [ a ] ! = ' \0 ' ; a + + )
2004-10-14 11:24:13 +00:00
msg [ a ] = pr_file_p [ a ] ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
msg [ a - 1 ] = ' \0 ' ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
{
pr_file_p + + ;
2010-12-08 14:42:05 +00:00
}
2004-10-14 11:24:13 +00:00
}
else if ( ! strncmp ( directive , " includelist " , 11 ) )
{
pr_file_p = directive + 11 ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
while ( * pr_file_p < = ' ' )
pr_file_p + + ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
while ( 1 )
{
QCC_PR_LexWhitespace ( ) ;
if ( ! QCC_PR_SimpleGetToken ( ) )
{
if ( ! * pr_file_p )
QCC_Error ( ERR_EOF , " eof in includelist " ) ;
else
{
pr_file_p + + ;
pr_source_line + + ;
}
continue ;
}
if ( ! strcmp ( pr_token , " #endlist " ) )
break ;
2005-08-27 05:45:45 +00:00
QCC_FindBestInclude ( pr_token , compilingfile , qccmsourcedir ) ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
if ( * pr_file_p = = ' \r ' )
pr_file_p + + ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
2004-08-23 01:38:21 +00:00
{
pr_file_p + + ;
}
}
2010-12-08 14:42:05 +00:00
2004-10-14 11:24:13 +00:00
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
{
pr_file_p + + ;
}
}
else if ( ! strncmp ( directive , " include " , 7 ) )
2005-05-04 14:45:00 +00:00
{
2005-04-17 02:22:51 +00:00
char sm ;
2005-04-16 16:21:27 +00:00
2004-10-14 11:24:13 +00:00
pr_file_p = directive + 7 ;
while ( * pr_file_p < = ' ' )
pr_file_p + + ;
2005-08-27 05:45:45 +00:00
msg [ 0 ] = ' \0 ' ;
2004-11-04 04:19:10 +00:00
if ( * pr_file_p = = ' \" ' )
2005-04-16 16:21:27 +00:00
sm = ' \" ' ;
else if ( * pr_file_p = = ' < ' )
sm = ' > ' ;
else
2004-11-04 04:19:10 +00:00
{
2006-02-23 23:03:12 +00:00
QCC_PR_ParseError ( 0 , " Not a string literal (on a #include) " ) ;
2005-04-16 16:21:27 +00:00
sm = 0 ;
2004-11-04 04:19:10 +00:00
}
2005-08-27 05:45:45 +00:00
pr_file_p + + ;
a = 0 ;
while ( * pr_file_p ! = sm )
2004-11-04 04:19:10 +00:00
{
2005-08-27 05:45:45 +00:00
if ( * pr_file_p = = ' \n ' )
2004-11-04 04:19:10 +00:00
{
2011-03-04 15:35:16 +00:00
QCC_PR_ParseError ( 0 , " #include continued over line boundry \n " ) ;
2005-04-16 16:21:27 +00:00
break ;
2004-11-04 04:19:10 +00:00
}
2005-08-27 05:45:45 +00:00
msg [ a + + ] = * pr_file_p ;
pr_file_p + + ;
2004-11-04 04:19:10 +00:00
}
2005-08-27 05:45:45 +00:00
msg [ a ] = 0 ;
2005-04-16 16:21:27 +00:00
2005-08-27 05:45:45 +00:00
QCC_FindBestInclude ( msg , compilingfile , qccmsourcedir ) ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
pr_file_p + + ;
2004-08-23 01:38:21 +00:00
2004-11-04 04:19:10 +00:00
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' & & * pr_file_p < = ' ' )
pr_file_p + + ;
2004-08-23 01:38:21 +00:00
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
{
pr_file_p + + ;
}
}
2004-10-14 11:24:13 +00:00
else if ( ! strncmp ( directive , " datafile " , 8 ) )
2010-12-08 14:42:05 +00:00
{
2004-10-14 11:24:13 +00:00
pr_file_p = directive + 8 ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
while ( * pr_file_p < = ' ' )
pr_file_p + + ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
QCC_PR_LexString ( ) ;
printf ( " Including datafile: %s \n " , pr_token ) ;
QCC_AddFile ( pr_token ) ;
2004-08-23 01:38:21 +00:00
pr_file_p + + ;
2010-07-03 21:49:48 +00:00
for ( a = 0 ; a < sizeof ( msg ) - 1 & & pr_file_p [ a ] ! = ' \n ' & & pr_file_p [ a ] ! = ' \0 ' ; a + + )
2004-10-14 11:24:13 +00:00
msg [ a ] = pr_file_p [ a ] ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
msg [ a - 1 ] = ' \0 ' ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
{
pr_file_p + + ;
}
2004-08-23 01:38:21 +00:00
}
2004-10-14 11:24:13 +00:00
else if ( ! strncmp ( directive , " output " , 6 ) )
{
extern char destfile [ 1024 ] ;
pr_file_p = directive + 6 ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
while ( * pr_file_p < = ' ' )
pr_file_p + + ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
QCC_PR_LexString ( ) ;
strcpy ( destfile , pr_token ) ;
printf ( " Outputfile: %s \n " , destfile ) ;
2004-08-23 01:38:21 +00:00
pr_file_p + + ;
2010-12-08 14:42:05 +00:00
2010-07-03 21:49:48 +00:00
for ( a = 0 ; a < sizeof ( msg ) - 1 & & pr_file_p [ a ] ! = ' \n ' & & pr_file_p [ a ] ! = ' \0 ' ; a + + )
2004-10-14 11:24:13 +00:00
msg [ a ] = pr_file_p [ a ] ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
msg [ a - 1 ] = ' \0 ' ;
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
2004-08-23 01:38:21 +00:00
{
2004-10-14 11:24:13 +00:00
pr_file_p + + ;
2004-08-23 01:38:21 +00:00
}
}
2004-10-14 11:24:13 +00:00
else if ( ! strncmp ( directive , " pragma " , 6 ) )
2004-08-23 01:38:21 +00:00
{
2004-10-14 11:24:13 +00:00
pr_file_p = directive + 6 ;
while ( * pr_file_p < = ' ' )
pr_file_p + + ;
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
qcc_token [ 0 ] = ' \0 ' ;
for ( a = 0 ; * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ; pr_file_p + + ) //read on until the end of the line
{
2004-11-13 17:18:34 +00:00
if ( ( * pr_file_p = = ' ' | | * pr_file_p = = ' \t ' | | * pr_file_p = = ' ( ' ) & & ! * qcc_token )
2004-10-14 11:24:13 +00:00
{
msg [ a ] = ' \0 ' ;
strcpy ( qcc_token , msg ) ;
a = 0 ;
continue ;
}
msg [ a + + ] = * pr_file_p ;
}
2010-12-08 14:42:05 +00:00
2004-10-14 11:24:13 +00:00
msg [ a ] = ' \0 ' ;
{
char * end ;
for ( end = msg + a - 1 ; end > = msg & & * end < = ' ' ; end - - )
* end = ' \0 ' ;
}
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
if ( ! * qcc_token )
{
strcpy ( qcc_token , msg ) ;
msg [ 0 ] = ' \0 ' ;
}
2004-08-23 01:38:21 +00:00
{
2004-10-14 11:24:13 +00:00
char * end ;
for ( end = msg + a - 1 ; end > = msg & & * end < = ' ' ; end - - )
* end = ' \0 ' ;
}
2004-08-23 01:38:21 +00:00
2004-10-14 11:24:13 +00:00
if ( ! QC_strcasecmp ( qcc_token , " DONT_COMPILE_THIS_FILE " ) )
{
while ( * pr_file_p )
2004-08-23 01:38:21 +00:00
{
2004-10-14 11:24:13 +00:00
while ( * pr_file_p ! = ' \n ' & & * pr_file_p ! = ' \0 ' ) //read on until the end of the line
pr_file_p + + ;
if ( * pr_file_p = = ' \n ' )
{
pr_file_p + + ;
2008-11-09 22:29:28 +00:00
QCC_PR_NewLine ( false ) ;
2004-10-14 11:24:13 +00:00
}
2004-08-23 01:38:21 +00:00
}
}
2004-10-14 11:24:13 +00:00
else if ( ! QC_strcasecmp ( qcc_token , " COPYRIGHT " ) )
2004-08-23 01:38:21 +00:00
{
2004-10-14 11:24:13 +00:00
if ( strlen ( msg ) > = sizeof ( QCC_copyright ) )
QCC_PR_ParseWarning ( WARN_STRINGTOOLONG , " Copyright message is too long \n " ) ;
strncpy ( QCC_copyright , msg , sizeof ( QCC_copyright ) - 1 ) ;
}
2009-05-24 10:11:17 +00:00
else if ( ! strncmp ( qcc_token , " compress " , 8 ) )
{
extern pbool compressoutput ;
compressoutput = atoi ( msg ) ;
}
2008-11-09 22:29:28 +00:00
else if ( ! strncmp ( qcc_token , " forcecrc " , 8 ) )
2005-08-26 22:56:51 +00:00
{
ForcedCRC = atoi ( msg ) ;
}
2010-05-01 22:47:47 +00:00
else if ( ! strncmp ( qcc_token , " noref " , 8 ) )
{
defaultnoref = atoi ( msg ) ;
}
2009-03-29 23:47:29 +00:00
else if ( ! strncmp ( qcc_token , " defaultstatic " , 13 ) )
{
defaultstatic = atoi ( msg ) ;
}
2011-08-16 04:12:15 +00:00
else if ( ! strncmp ( qcc_token , " wrasm " , 5 ) )
{
pbool on = atoi ( msg ) ;
if ( asmfile & & ! on )
{
fclose ( asmfile ) ;
asmfile = NULL ;
}
if ( ! asmfile & & on )
asmfile = fopen ( " qc.asm " , " wb " ) ;
}
2008-11-09 22:29:28 +00:00
else if ( ! strncmp ( qcc_token , " sourcefile " , 10 ) )
{
# define MAXSOURCEFILESLIST 8
extern char sourcefileslist [ MAXSOURCEFILESLIST ] [ 1024 ] ;
2011-05-15 13:23:13 +00:00
//extern int currentsourcefile; // warning: unused variable <20> currentsourcefile<6C>
2008-11-09 22:29:28 +00:00
extern int numsourcefiles ;
int i ;
QCC_COM_Parse ( msg ) ;
for ( i = 0 ; i < numsourcefiles ; i + + )
{
if ( ! strcmp ( sourcefileslist [ i ] , qcc_token ) )
break ;
}
2011-10-03 02:45:44 +00:00
if ( i = = numsourcefiles & & numsourcefiles < MAXSOURCEFILESLIST )
2008-11-09 22:29:28 +00:00
strcpy ( sourcefileslist [ numsourcefiles + + ] , qcc_token ) ;
}
2004-10-14 11:24:13 +00:00
else if ( ! QC_strcasecmp ( qcc_token , " TARGET " ) )
{
if ( qcc_targetformat = = QCF_HEXEN2 & & numstatements )
2004-08-23 01:38:21 +00:00
QCC_PR_ParseWarning ( WARN_BADTARGET , " Cannot switch from hexen2 target \' %s \' . Ignored. " , msg ) ;
2005-02-28 07:16:19 +00:00
else if ( ! QC_strcasecmp ( msg , " H2 " ) | | ! QC_strcasecmp ( msg , " HEXEN2 " ) )
2004-10-14 11:24:13 +00:00
{
if ( numstatements )
2011-10-03 02:45:44 +00:00
QCC_PR_ParseWarning ( WARN_BADTARGET , " Cannot switch to hexen2 target \' %s \' . Ignored. " , msg ) ;
2004-10-14 11:24:13 +00:00
else
qcc_targetformat = QCF_HEXEN2 ;
}
else if ( ! QC_strcasecmp ( msg , " KK7 " ) )
qcc_targetformat = QCF_KK7 ;
2008-10-16 23:04:36 +00:00
else if ( ! QC_strcasecmp ( msg , " DP " ) | | ! QC_strcasecmp ( msg , " DARKPLACES " ) )
qcc_targetformat = QCF_DARKPLACES ;
2004-10-14 11:24:13 +00:00
else if ( ! QC_strcasecmp ( msg , " FTEDEBUG " ) )
qcc_targetformat = QCF_FTEDEBUG ;
else if ( ! QC_strcasecmp ( msg , " FTE " ) )
qcc_targetformat = QCF_FTE ;
else if ( ! QC_strcasecmp ( msg , " STANDARD " ) | | ! QC_strcasecmp ( msg , " ID " ) )
qcc_targetformat = QCF_STANDARD ;
else if ( ! QC_strcasecmp ( msg , " DEBUG " ) )
2005-02-28 07:16:19 +00:00
qcc_targetformat = QCF_FTEDEBUG ;
2011-03-04 13:59:06 +00:00
else if ( ! QC_strcasecmp ( msg , " QTEST " ) )
qcc_targetformat = QCF_QTEST ;
2004-08-23 01:38:21 +00:00
else
2004-10-14 11:24:13 +00:00
QCC_PR_ParseWarning ( WARN_BADTARGET , " Unknown target \' %s \' . Ignored. " , msg ) ;
}
else if ( ! QC_strcasecmp ( qcc_token , " PROGS_SRC " ) )
{ //doesn't make sence, but silenced if you are switching between using a certain precompiler app used with CuTF.
2004-08-23 01:38:21 +00:00
}
2004-10-14 11:24:13 +00:00
else if ( ! QC_strcasecmp ( qcc_token , " PROGS_DAT " ) )
{ //doesn't make sence, but silenced if you are switching between using a certain precompiler app used with CuTF.
extern char destfile [ 1024 ] ;
2006-04-02 23:47:27 +00:00
# ifndef QCCONLY
extern char qccmfilename [ 1024 ] ;
int p ;
char * s , * s2 ;
# endif
2004-10-14 11:24:13 +00:00
QCC_COM_Parse ( msg ) ;
2006-04-02 23:47:27 +00:00
# ifndef QCCONLY
p = 0 ;
2010-12-08 14:42:05 +00:00
s2 = qcc_token ;
2006-04-02 23:47:27 +00:00
if ( ! strncmp ( s2 , " ./ " , 2 ) )
s2 + = 2 ;
else
{
while ( ! strncmp ( s2 , " ../ " , 3 ) )
{
s2 + = 3 ;
p + + ;
}
}
strcpy ( qccmfilename , qccmsourcedir ) ;
for ( s = qccmfilename + strlen ( qccmfilename ) ; p & & s > = qccmfilename ; s - - )
{
if ( * s = = ' / ' | | * s = = ' \\ ' )
{
* ( s + 1 ) = ' \0 ' ;
p - - ;
}
}
sprintf ( destfile , " %s " , s2 ) ;
while ( p > 0 )
{
memmove ( destfile + 3 , destfile , strlen ( destfile ) + 1 ) ;
destfile [ 0 ] = ' . ' ;
destfile [ 1 ] = ' . ' ;
destfile [ 2 ] = ' / ' ;
p - - ;
}
# else
2004-10-14 11:24:13 +00:00
strcpy ( destfile , qcc_token ) ;
2006-04-02 23:47:27 +00:00
# endif
2004-10-14 11:24:13 +00:00
printf ( " Outputfile: %s \n " , destfile ) ;
}
2005-04-16 16:21:27 +00:00
else if ( ! QC_strcasecmp ( qcc_token , " keyword " ) | | ! QC_strcasecmp ( qcc_token , " flag " ) )
{
char * s ;
int st ;
s = QCC_COM_Parse ( msg ) ;
if ( ! QC_strcasecmp ( qcc_token , " enable " ) | | ! QC_strcasecmp ( qcc_token , " on " ) )
st = 1 ;
2005-04-17 10:05:33 +00:00
else if ( ! QC_strcasecmp ( qcc_token , " disable " ) | | ! QC_strcasecmp ( qcc_token , " off " ) )
st = 0 ;
2005-04-16 16:21:27 +00:00
else
{
QCC_PR_ParseWarning ( WARN_BADPRAGMA , " compiler flag state not recognised " ) ;
st = - 1 ;
}
if ( st < 0 )
QCC_PR_ParseWarning ( WARN_BADPRAGMA , " warning id not recognised " ) ;
else
{
int f ;
s = QCC_COM_Parse ( s ) ;
for ( f = 0 ; compiler_flag [ f ] . enabled ; f + + )
{
if ( ! QC_strcasecmp ( compiler_flag [ f ] . abbrev , qcc_token ) )
{
if ( compiler_flag [ f ] . flags & FLAG_MIDCOMPILE )
* compiler_flag [ f ] . enabled = st ;
else
QCC_PR_ParseWarning ( WARN_BADPRAGMA , " Cannot enable/disable keyword/flag via a pragma " ) ;
break ;
}
}
if ( ! compiler_flag [ f ] . enabled )
QCC_PR_ParseWarning ( WARN_BADPRAGMA , " keyword/flag not recognised " ) ;
}
}
2004-11-13 17:18:34 +00:00
else if ( ! QC_strcasecmp ( qcc_token , " warning " ) )
2004-08-23 01:38:21 +00:00
{
2004-11-13 17:18:34 +00:00
int st ;
char * s ;
s = QCC_COM_Parse ( msg ) ;
if ( ! stricmp ( qcc_token , " enable " ) | | ! stricmp ( qcc_token , " on " ) )
st = 0 ;
else if ( ! stricmp ( qcc_token , " disable " ) | | ! stricmp ( qcc_token , " off " ) )
st = 1 ;
else if ( ! stricmp ( qcc_token , " toggle " ) )
st = 2 ;
else
2005-04-16 16:21:27 +00:00
{
QCC_PR_ParseWarning ( WARN_BADPRAGMA , " warning state not recognised " ) ;
2004-11-13 17:18:34 +00:00
st = - 1 ;
2005-04-16 16:21:27 +00:00
}
2004-11-13 17:18:34 +00:00
if ( st > = 0 )
{
int wn ;
s = QCC_COM_Parse ( s ) ;
wn = QCC_WarningForName ( qcc_token ) ;
if ( wn < 0 )
QCC_PR_ParseWarning ( WARN_BADPRAGMA , " warning id not recognised " ) ;
else
{
if ( st = = 2 ) //toggle
qccwarningdisabled [ wn ] = true - qccwarningdisabled [ wn ] ;
else
qccwarningdisabled [ wn ] = st ;
}
}
2004-08-23 01:38:21 +00:00
}
else
2004-10-14 11:24:13 +00:00
QCC_PR_ParseWarning ( WARN_BADPRAGMA , " Unknown pragma \' %s \' " , qcc_token ) ;
2004-08-23 01:38:21 +00:00
}
2005-02-28 07:16:19 +00:00
return true ;
}
return false ;
}
/*
= = = = = = = = = = = = = =
PR_NewLine
Call at start of file and when * pr_file_p = = ' \n '
= = = = = = = = = = = = = =
*/
void QCC_PR_NewLine ( pbool incomment )
{
pr_source_line + + ;
pr_line_start = pr_file_p ;
while ( * pr_file_p = = ' ' | | * pr_file_p = = ' \t ' )
pr_file_p + + ;
if ( incomment ) //no constants if in a comment.
{
}
else if ( QCC_PR_Precompiler ( ) )
{
2004-08-23 01:38:21 +00:00
}
// if (pr_dumpasm)
// PR_PrintNextLine ();
}
/*
= = = = = = = = = = = = = =
PR_LexString
Parses a quoted string
= = = = = = = = = = = = = =
*/
#if 0
void QCC_PR_LexString ( void )
{
int c ;
int len ;
char tmpbuf [ 2048 ] ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
char * text ;
char * oldf ;
int oldline ;
bool fromfile = true ;
len = 0 ;
text = pr_file_p ;
do
{
QCC_COM_Parse ( text ) ;
// print("Next token is \"%s\"\n", com_token);
if ( * text = = ' \" ' )
{
text + + ;
if ( fromfile ) pr_file_p + + ;
}
do
{
c = * text + + ;
if ( fromfile ) pr_file_p + + ;
if ( ! c )
QCC_PR_ParseError ( " EOF inside quote " ) ;
if ( c = = ' \n ' )
QCC_PR_ParseError ( " newline inside quote " ) ;
if ( c = = ' \\ ' )
{ // escape char
c = * text + + ;
if ( fromfile ) pr_file_p + + ;
if ( ! c )
QCC_PR_ParseError ( " EOF inside quote " ) ;
if ( c = = ' n ' )
c = ' \n ' ;
else if ( c = = ' " ' )
c = ' " ' ;
else if ( c = = ' \\ ' )
c = ' \\ ' ;
else
QCC_PR_ParseError ( " Unknown escape char " ) ;
}
else if ( c = = ' \" ' )
{
if ( fromfile ) pr_file_p + + ;
break ;
}
tmpbuf [ len ] = c ;
len + + ;
} while ( 1 ) ;
tmpbuf [ len ] = 0 ;
// if (fromfile) pr_file_p++;
pr_immediate_type = NULL ;
oldline = pr_source_line ;
oldf = pr_file_p ;
QCC_PR_Lex ( ) ;
if ( pr_immediate_type = = & type_string )
{
// print("Appending \"%s\" to \"%s\"\n", pr_immediate_string, tmpbuf);
strcat ( tmpbuf , pr_immediate_string ) ;
len + = strlen ( pr_immediate_string ) ;
}
else
{
pr_source_line = oldline ;
pr_file_p = oldf - 1 ;
QCC_PR_LexWhitespace ( ) ;
if ( * pr_file_p ! = ' \" ' ) //annother string
2010-12-08 14:42:05 +00:00
break ;
2004-08-23 01:38:21 +00:00
}
QCC_PR_LexWhitespace ( ) ;
2010-12-08 14:42:05 +00:00
text = pr_file_p ;
2004-08-23 01:38:21 +00:00
} while ( 1 ) ;
strcpy ( pr_token , tmpbuf ) ;
pr_token_type = tt_immediate ;
pr_immediate_type = & type_string ;
strcpy ( pr_immediate_string , pr_token ) ;
// print("Found \"%s\"\n", pr_immediate_string);
}
# else
void QCC_PR_LexString ( void )
{
int c ;
int len ;
char * end , * cnst ;
int texttype = 0 ;
2010-07-03 21:49:48 +00:00
2004-08-23 01:38:21 +00:00
len = 0 ;
pr_file_p + + ;
do
{
c = * pr_file_p + + ;
if ( ! c )
QCC_PR_ParseError ( ERR_EOF , " EOF inside quote " ) ;
if ( c = = ' \n ' )
QCC_PR_ParseError ( ERR_INVALIDSTRINGIMMEDIATE , " newline inside quote " ) ;
if ( c = = ' \\ ' )
{ // escape char
c = * pr_file_p + + ;
if ( ! c )
QCC_PR_ParseError ( ERR_EOF , " EOF inside quote " ) ;
if ( c = = ' n ' )
c = ' \n ' ;
else if ( c = = ' r ' )
c = ' \r ' ;
else if ( c = = ' " ' )
c = ' " ' ;
else if ( c = = ' t ' )
c = ' \t ' ;
2004-11-04 04:19:10 +00:00
else if ( c = = ' a ' )
c = ' \a ' ;
else if ( c = = ' v ' )
c = ' \v ' ;
else if ( c = = ' f ' )
c = ' \f ' ;
2004-08-23 01:38:21 +00:00
else if ( c = = ' s ' | | c = = ' b ' )
{
texttype ^ = 128 ;
continue ;
}
else if ( c = = ' [ ' )
c = 16 ;
else if ( c = = ' ] ' )
c = 17 ;
else if ( c = = ' { ' )
{
int d ;
c = 0 ;
while ( ( d = * pr_file_p + + ) ! = ' } ' )
{
c = c * 10 + d - ' 0 ' ;
if ( d < ' 0 ' | | d > ' 9 ' | | c > 255 )
2008-01-28 13:28:35 +00:00
QCC_PR_ParseError ( ERR_BADCHARACTERCODE , " Bad character code " ) ;
2004-08-23 01:38:21 +00:00
}
}
else if ( c = = ' < ' )
c = 29 ;
else if ( c = = ' - ' )
c = 30 ;
else if ( c = = ' > ' )
c = 31 ;
2006-09-17 00:59:22 +00:00
else if ( c = = ' x ' | | c = = ' X ' )
{
int d ;
c = 0 ;
d = ( unsigned char ) * pr_file_p + + ;
if ( d > = ' 0 ' & & d < = ' 9 ' )
c + = d - ' 0 ' ;
else if ( d > = ' A ' & & d < = ' F ' )
c + = d - ' A ' + 10 ;
else if ( d > = ' a ' & & d < = ' f ' )
c + = d - ' a ' + 10 ;
else
2008-01-28 13:28:35 +00:00
QCC_PR_ParseError ( ERR_BADCHARACTERCODE , " Bad character code " ) ;
2006-09-17 00:59:22 +00:00
c * = 16 ;
d = ( unsigned char ) * pr_file_p + + ;
if ( d > = ' 0 ' & & d < = ' 9 ' )
c + = d - ' 0 ' ;
else if ( d > = ' A ' & & d < = ' F ' )
c + = d - ' A ' + 10 ;
else if ( d > = ' a ' & & d < = ' f ' )
c + = d - ' a ' + 10 ;
else
2008-01-28 13:28:35 +00:00
QCC_PR_ParseError ( ERR_BADCHARACTERCODE , " Bad character code " ) ;
2006-09-17 00:59:22 +00:00
}
2004-08-23 01:38:21 +00:00
else if ( c = = ' \\ ' )
c = ' \\ ' ;
else if ( c = = ' \' ' )
c = ' \' ' ;
else if ( c > = ' 0 ' & & c < = ' 9 ' )
2005-03-20 02:57:11 +00:00
c = 18 + c - ' 0 ' ;
2004-08-23 01:38:21 +00:00
else if ( c = = ' \r ' )
{ //sigh
c = * pr_file_p + + ;
if ( c ! = ' \n ' )
QCC_PR_ParseWarning ( WARN_HANGINGSLASHR , " Hanging \\ \\ \r " ) ;
pr_source_line + + ;
}
else if ( c = = ' \n ' )
{ //sigh
pr_source_line + + ;
}
else
QCC_PR_ParseError ( ERR_INVALIDSTRINGIMMEDIATE , " Unknown escape char %c " , c ) ;
}
else if ( c = = ' \" ' )
{
if ( len > = sizeof ( pr_immediate_string ) - 1 )
QCC_Error ( ERR_INVALIDSTRINGIMMEDIATE , " String length exceeds %i " , sizeof ( pr_immediate_string ) - 1 ) ;
2004-09-21 03:22:55 +00:00
while ( * pr_file_p & & * pr_file_p < = ' ' )
2004-11-04 04:19:10 +00:00
{
if ( * pr_file_p = = ' \n ' )
2008-11-09 22:29:28 +00:00
{
pr_file_p + + ;
2004-11-04 04:19:10 +00:00
QCC_PR_NewLine ( false ) ;
2008-11-09 22:29:28 +00:00
}
else
pr_file_p + + ;
2004-11-04 04:19:10 +00:00
}
2004-09-21 03:22:55 +00:00
if ( * pr_file_p = = ' \" ' ) //have annother go
{
pr_file_p + + ;
continue ;
}
2004-08-23 01:38:21 +00:00
pr_token [ len ] = 0 ;
pr_token_type = tt_immediate ;
pr_immediate_type = type_string ;
2010-12-08 14:42:05 +00:00
strcpy ( pr_immediate_string , pr_token ) ;
2004-08-23 01:38:21 +00:00
return ;
}
else if ( c = = ' # ' )
{
for ( end = pr_file_p ; ; end + + )
{
if ( * end < = ' ' )
break ;
if ( * end = = ' ) '
| | * end = = ' ( '
| | * end = = ' + '
| | * end = = ' - '
| | * end = = ' * '
| | * end = = ' / '
| | * end = = ' \\ '
| | * end = = ' | '
| | * end = = ' & '
| | * end = = ' = '
| | * end = = ' ^ '
| | * end = = ' ~ '
| | * end = = ' [ '
| | * end = = ' ] '
| | * end = = ' \" '
| | * end = = ' { '
| | * end = = ' } '
| | * end = = ' ; '
| | * end = = ' : '
| | * end = = ' , '
| | * end = = ' . '
| | * end = = ' # ' )
break ;
}
c = * end ;
* end = ' \0 ' ;
cnst = QCC_PR_CheakCompConstString ( pr_file_p ) ;
if ( cnst = = pr_file_p )
cnst = NULL ;
* end = c ;
c = ' # ' ; //undo
if ( cnst )
{
QCC_PR_ParseWarning ( WARN_MACROINSTRING , " Macro expansion in string " ) ;
if ( len + strlen ( cnst ) > = sizeof ( pr_token ) - 1 )
QCC_Error ( ERR_INVALIDSTRINGIMMEDIATE , " String length exceeds %i " , sizeof ( pr_token ) - 1 ) ;
strcpy ( pr_token + len , cnst ) ;
len + = strlen ( cnst ) ;
pr_file_p = end ;
continue ;
}
}
2005-02-18 02:33:01 +00:00
else if ( c = = 0x7C & & flag_acc ) //reacc support... reacc is strange.
2005-02-09 19:32:30 +00:00
c = ' \n ' ;
2005-04-22 23:55:57 +00:00
else
c | = texttype ;
2004-08-23 01:38:21 +00:00
2005-04-22 23:55:57 +00:00
pr_token [ len ] = c ;
2004-08-23 01:38:21 +00:00
len + + ;
if ( len > = sizeof ( pr_token ) - 1 )
QCC_Error ( ERR_INVALIDSTRINGIMMEDIATE , " String length exceeds %i " , sizeof ( pr_token ) - 1 ) ;
} while ( 1 ) ;
}
# endif
/*
= = = = = = = = = = = = = =
PR_LexNumber
= = = = = = = = = = = = = =
*/
int QCC_PR_LexInteger ( void )
{
int c ;
int len ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
len = 0 ;
c = * pr_file_p ;
if ( pr_file_p [ 0 ] = = ' 0 ' & & pr_file_p [ 1 ] = = ' x ' )
{
pr_token [ 0 ] = ' 0 ' ;
pr_token [ 1 ] = ' x ' ;
len = 2 ;
c = * ( pr_file_p + = 2 ) ;
}
do
{
pr_token [ len ] = c ;
len + + ;
pr_file_p + + ;
c = * pr_file_p ;
} while ( ( c > = ' 0 ' & & c < = ' 9 ' ) | | c = = ' . ' | | ( c > = ' a ' & & c < = ' f ' ) ) ;
pr_token [ len ] = 0 ;
return atoi ( pr_token ) ;
}
void QCC_PR_LexNumber ( void )
{
2009-08-29 16:53:22 +00:00
int tokenlen = 0 ;
2004-08-23 01:38:21 +00:00
int num = 0 ;
2009-08-29 17:24:20 +00:00
int base = 0 ;
2004-08-23 01:38:21 +00:00
int c ;
int sign = 1 ;
if ( * pr_file_p = = ' - ' )
{
sign = - 1 ;
pr_file_p + + ;
2009-08-29 16:53:22 +00:00
pr_token [ tokenlen + + ] = ' - ' ;
2004-08-23 01:38:21 +00:00
}
2009-08-29 16:53:22 +00:00
if ( pr_file_p [ 0 ] = = ' 0 ' & & pr_file_p [ 1 ] = = ' x ' )
2004-08-23 01:38:21 +00:00
{
pr_file_p + = 2 ;
base = 16 ;
2009-08-29 16:53:22 +00:00
pr_token [ tokenlen + + ] = ' 0 ' ;
pr_token [ tokenlen + + ] = ' x ' ;
2004-08-23 01:38:21 +00:00
}
2009-08-29 17:24:20 +00:00
pr_immediate_type = NULL ;
//assume base 10 if not stated
if ( ! base )
base = 10 ;
2004-08-23 01:38:21 +00:00
while ( ( c = * pr_file_p ) )
2010-12-08 14:42:05 +00:00
{
2004-08-23 01:38:21 +00:00
if ( c > = ' 0 ' & & c < = ' 9 ' )
{
2009-08-29 16:53:22 +00:00
pr_token [ tokenlen + + ] = c ;
2004-08-23 01:38:21 +00:00
num * = base ;
num + = c - ' 0 ' ;
}
2009-08-29 17:24:20 +00:00
else if ( c > = ' a ' & & c < = ' f ' & & base > 10 )
2004-08-23 01:38:21 +00:00
{
2009-08-29 16:53:22 +00:00
pr_token [ tokenlen + + ] = c ;
2004-08-23 01:38:21 +00:00
num * = base ;
num + = c - ' a ' + 10 ;
}
2009-08-29 17:24:20 +00:00
else if ( c > = ' A ' & & c < = ' F ' & & base > 10 )
2004-08-23 01:38:21 +00:00
{
2009-08-29 16:53:22 +00:00
pr_token [ tokenlen + + ] = c ;
2004-08-23 01:38:21 +00:00
num * = base ;
num + = c - ' A ' + 10 ;
}
else if ( c = = ' . ' )
{
2009-08-29 16:53:22 +00:00
pr_token [ tokenlen + + ] = c ;
2004-08-23 01:38:21 +00:00
pr_file_p + + ;
pr_immediate_type = type_float ;
while ( 1 )
{
c = * pr_file_p ;
if ( c > = ' 0 ' & & c < = ' 9 ' )
{
2009-08-29 17:24:20 +00:00
pr_token [ tokenlen + + ] = c ;
2004-08-23 01:38:21 +00:00
}
2009-08-29 17:24:20 +00:00
else if ( c = = ' f ' )
{
pr_file_p + + ;
break ;
}
2004-08-23 01:38:21 +00:00
else
2010-12-08 14:42:05 +00:00
{
2004-08-23 01:38:21 +00:00
break ;
}
pr_file_p + + ;
}
2009-08-29 17:24:20 +00:00
pr_token [ tokenlen + + ] = 0 ;
2009-11-04 21:16:50 +00:00
pr_immediate . _float = ( float ) atof ( pr_token ) ;
2004-08-23 01:38:21 +00:00
return ;
}
else if ( c = = ' i ' )
{
2009-08-29 17:24:20 +00:00
pr_token [ tokenlen + + ] = c ;
pr_token [ tokenlen + + ] = 0 ;
2004-08-23 01:38:21 +00:00
pr_file_p + + ;
pr_immediate_type = type_integer ;
pr_immediate . _int = num * sign ;
return ;
}
2009-08-29 17:24:20 +00:00
else
break ;
2004-08-23 01:38:21 +00:00
pr_file_p + + ;
}
2009-08-29 16:53:22 +00:00
pr_token [ tokenlen + + ] = 0 ;
2004-08-23 01:38:21 +00:00
2009-08-29 17:24:20 +00:00
if ( ! pr_immediate_type )
{
if ( flag_assume_integer )
pr_immediate_type = type_integer ;
else
pr_immediate_type = type_float ;
}
if ( pr_immediate_type = = type_integer )
2009-08-29 14:56:42 +00:00
{
pr_immediate_type = type_integer ;
pr_immediate . _int = num * sign ;
}
else
{
pr_immediate_type = type_float ;
2009-09-04 10:35:41 +00:00
// at this point, we know there's no . in it, so the NaN bug shouldn't happen
// and we cannot use atof on tokens like 0xabc, so use num*sign, it SHOULD be safe
//pr_immediate._float = atof(pr_token);
pr_immediate . _float = ( float ) ( num * sign ) ;
2009-08-29 14:56:42 +00:00
}
2004-08-23 01:38:21 +00:00
}
float QCC_PR_LexFloat ( void )
{
int c ;
int len ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
len = 0 ;
c = * pr_file_p ;
do
{
pr_token [ len ] = c ;
len + + ;
pr_file_p + + ;
c = * pr_file_p ;
2004-09-20 23:25:38 +00:00
} while ( ( c > = ' 0 ' & & c < = ' 9 ' ) | | ( c = = ' . ' & & pr_file_p [ 1 ] ! = ' . ' ) ) ; //only allow a . if the next isn't too...
2004-08-23 01:38:21 +00:00
pr_token [ len ] = 0 ;
return ( float ) atof ( pr_token ) ;
}
/*
= = = = = = = = = = = = = =
PR_LexVector
Parses a single quoted vector
= = = = = = = = = = = = = =
*/
void QCC_PR_LexVector ( void )
{
int i ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
pr_file_p + + ;
if ( * pr_file_p = = ' \\ ' )
2008-01-28 13:27:30 +00:00
{ //extended character constant
2004-08-23 01:38:21 +00:00
pr_token_type = tt_immediate ;
pr_immediate_type = type_float ;
pr_file_p + + ;
switch ( * pr_file_p )
{
case ' n ' :
pr_immediate . _float = ' \n ' ;
break ;
case ' r ' :
pr_immediate . _float = ' \r ' ;
break ;
case ' t ' :
pr_immediate . _float = ' \t ' ;
break ;
case ' \' ' :
pr_immediate . _float = ' \' ' ;
break ;
case ' \" ' :
pr_immediate . _float = ' \" ' ;
break ;
case ' \\ ' :
pr_immediate . _float = ' \\ ' ;
break ;
default :
2008-01-28 13:27:30 +00:00
QCC_PR_ParseError ( ERR_INVALIDVECTORIMMEDIATE , " Bad character constant " ) ;
2004-08-23 01:38:21 +00:00
}
if ( * pr_file_p ! = ' \' ' )
2008-01-28 13:27:30 +00:00
QCC_PR_ParseError ( ERR_INVALIDVECTORIMMEDIATE , " Bad character constant " ) ;
2004-08-23 01:38:21 +00:00
pr_file_p + + ;
return ;
}
if ( pr_file_p [ 1 ] = = ' \' ' )
{ //character constant
pr_token_type = tt_immediate ;
pr_immediate_type = type_float ;
pr_immediate . _float = pr_file_p [ 0 ] ;
pr_file_p + = 2 ;
return ;
}
pr_token_type = tt_immediate ;
pr_immediate_type = type_vector ;
QCC_PR_LexWhitespace ( ) ;
for ( i = 0 ; i < 3 ; i + + )
{
pr_immediate . vector [ i ] = QCC_PR_LexFloat ( ) ;
QCC_PR_LexWhitespace ( ) ;
2006-09-17 00:59:22 +00:00
if ( * pr_file_p = = ' \' ' & & i = = 1 )
{
if ( i < 2 )
QCC_PR_ParseWarning ( WARN_FTE_SPECIFIC , " Bad vector " ) ;
for ( i + + ; i < 3 ; i + + )
pr_immediate . vector [ i ] = 0 ;
break ;
}
2004-08-23 01:38:21 +00:00
}
if ( * pr_file_p ! = ' \' ' )
QCC_PR_ParseError ( ERR_INVALIDVECTORIMMEDIATE , " Bad vector " ) ;
pr_file_p + + ;
}
/*
= = = = = = = = = = = = = =
PR_LexName
Parses an identifier
= = = = = = = = = = = = = =
*/
void QCC_PR_LexName ( void )
{
int c ;
int len ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
len = 0 ;
c = * pr_file_p ;
do
{
pr_token [ len ] = c ;
len + + ;
pr_file_p + + ;
c = * pr_file_p ;
2010-12-08 14:42:05 +00:00
} while ( ( c > = ' a ' & & c < = ' z ' ) | | ( c > = ' A ' & & c < = ' Z ' ) | | c = = ' _ '
| | ( c > = ' 0 ' & & c < = ' 9 ' ) ) ;
2004-08-23 01:38:21 +00:00
pr_token [ len ] = 0 ;
2010-12-08 14:42:05 +00:00
pr_token_type = tt_name ;
2004-08-23 01:38:21 +00:00
}
/*
= = = = = = = = = = = = = =
PR_LexPunctuation
= = = = = = = = = = = = = =
*/
void QCC_PR_LexPunctuation ( void )
{
int i ;
int len ;
char * p ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
pr_token_type = tt_punct ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
for ( i = 0 ; ( p = pr_punctuation [ i ] ) ! = NULL ; i + + )
{
len = strlen ( p ) ;
if ( ! strncmp ( p , pr_file_p , len ) )
{
2004-11-18 17:55:04 +00:00
strcpy ( pr_token , pr_punctuationremap [ i ] ) ;
2004-08-23 01:38:21 +00:00
if ( p [ 0 ] = = ' { ' )
pr_bracelevel + + ;
else if ( p [ 0 ] = = ' } ' )
pr_bracelevel - - ;
pr_file_p + = len ;
return ;
}
}
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
QCC_PR_ParseError ( ERR_UNKNOWNPUCTUATION , " Unknown punctuation " ) ;
}
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
/*
= = = = = = = = = = = = = =
PR_LexWhitespace
= = = = = = = = = = = = = =
*/
void QCC_PR_LexWhitespace ( void )
{
int c ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
while ( 1 )
{
// skip whitespace
while ( ( c = * pr_file_p ) < = ' ' )
{
if ( c = = ' \n ' )
{
2008-11-09 22:29:28 +00:00
pr_file_p + + ;
2004-08-23 01:38:21 +00:00
QCC_PR_NewLine ( false ) ;
if ( ! pr_file_p )
return ;
}
2008-11-09 22:29:28 +00:00
else
{
if ( c = = 0 )
return ; // end of file
pr_file_p + + ;
}
2004-08-23 01:38:21 +00:00
}
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
// skip // comments
if ( c = = ' / ' & & pr_file_p [ 1 ] = = ' / ' )
{
while ( * pr_file_p & & * pr_file_p ! = ' \n ' )
pr_file_p + + ;
2008-11-09 22:29:28 +00:00
if ( * pr_file_p = = ' \n ' )
pr_file_p + + ; //don't break on eof.
2004-08-23 01:38:21 +00:00
QCC_PR_NewLine ( false ) ;
continue ;
}
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
// skip /* */ comments
if ( c = = ' / ' & & pr_file_p [ 1 ] = = ' * ' )
{
2009-07-03 19:02:42 +00:00
pr_file_p + = 2 ;
2004-08-23 01:38:21 +00:00
do
{
if ( pr_file_p [ 0 ] = = ' \n ' )
2008-11-09 22:29:28 +00:00
{
2004-08-23 01:38:21 +00:00
QCC_PR_NewLine ( true ) ;
2008-11-09 22:29:28 +00:00
}
2004-08-23 01:38:21 +00:00
if ( pr_file_p [ 1 ] = = 0 )
{
2011-10-03 02:45:44 +00:00
QCC_PR_ParseError ( 0 , " EOF inside comment \n " ) ;
2004-08-23 01:38:21 +00:00
pr_file_p + + ;
return ;
}
2009-07-03 19:02:42 +00:00
pr_file_p + + ;
} while ( pr_file_p [ 0 ] ! = ' * ' | | pr_file_p [ 1 ] ! = ' / ' ) ;
pr_file_p + = 2 ;
2004-08-23 01:38:21 +00:00
continue ;
}
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
break ; // a real character has been found
}
}
//============================================================================
# define MAX_FRAMES 8192
2005-02-28 07:16:19 +00:00
char pr_framemodelname [ 64 ] ;
2008-01-16 03:43:53 +00:00
char pr_framemacros [ MAX_FRAMES ] [ 64 ] ;
2004-08-23 01:38:21 +00:00
int pr_framemacrovalue [ MAX_FRAMES ] ;
2004-11-15 13:03:32 +00:00
int pr_nummacros , pr_oldmacros ;
2004-08-23 01:38:21 +00:00
int pr_macrovalue ;
int pr_savedmacro ;
void QCC_PR_ClearGrabMacros ( void )
{
2004-11-15 13:03:32 +00:00
pr_oldmacros = pr_nummacros ;
// pr_nummacros = 0;
2004-08-23 01:38:21 +00:00
pr_macrovalue = 0 ;
pr_savedmacro = - 1 ;
}
2005-02-28 07:16:19 +00:00
int QCC_PR_FindMacro ( char * name )
2004-08-23 01:38:21 +00:00
{
int i ;
2004-11-15 13:03:32 +00:00
for ( i = pr_nummacros - 1 ; i > = 0 ; i - - )
2004-08-23 01:38:21 +00:00
{
2005-02-28 07:16:19 +00:00
if ( ! STRCMP ( name , pr_framemacros [ i ] ) )
2004-08-23 01:38:21 +00:00
{
2005-02-28 07:16:19 +00:00
return pr_framemacrovalue [ i ] ;
2004-08-23 01:38:21 +00:00
}
}
2004-11-15 13:03:32 +00:00
for ( i = pr_nummacros - 1 ; i > = 0 ; i - - )
2004-08-23 01:38:21 +00:00
{
2005-02-28 07:16:19 +00:00
if ( ! stricmp ( name , pr_framemacros [ i ] ) )
2004-08-23 01:38:21 +00:00
{
QCC_PR_ParseWarning ( WARN_CASEINSENSATIVEFRAMEMACRO , " Case insensative frame macro " ) ;
2005-02-28 07:16:19 +00:00
return pr_framemacrovalue [ i ] ;
2004-08-23 01:38:21 +00:00
}
}
2005-02-28 07:16:19 +00:00
return - 1 ;
}
void QCC_PR_ExpandMacro ( void )
{
int i = QCC_PR_FindMacro ( pr_token ) ;
if ( i < 0 )
QCC_PR_ParseError ( ERR_BADFRAMEMACRO , " Unknown frame macro $%s " , pr_token ) ;
sprintf ( pr_token , " %d " , i ) ;
pr_token_type = tt_immediate ;
pr_immediate_type = type_float ;
pr_immediate . _float = ( float ) i ;
2004-08-23 01:38:21 +00:00
}
// just parses text, returning false if an eol is reached
pbool QCC_PR_SimpleGetToken ( void )
{
int c ;
int i ;
2004-11-15 13:03:32 +00:00
2008-10-16 23:04:36 +00:00
pr_token [ 0 ] = 0 ;
2004-08-23 01:38:21 +00:00
// skip whitespace
while ( ( c = * pr_file_p ) < = ' ' )
{
if ( c = = ' \n ' | | c = = 0 )
return false ;
pr_file_p + + ;
}
2005-01-04 08:22:03 +00:00
if ( pr_file_p [ 0 ] = = ' / ' )
{
if ( pr_file_p [ 1 ] = = ' / ' )
{ //comment alert
while ( * pr_file_p & & * pr_file_p ! = ' \n ' )
pr_file_p + + ;
return false ;
}
2005-02-28 07:16:19 +00:00
if ( pr_file_p [ 1 ] = = ' * ' )
return false ;
2005-01-04 08:22:03 +00:00
}
2004-11-15 13:03:32 +00:00
2004-08-23 01:38:21 +00:00
i = 0 ;
2005-05-08 17:05:07 +00:00
while ( ( c = * pr_file_p ) > ' ' & & c ! = ' , ' & & c ! = ' ; ' & & c ! = ' ) ' & & c ! = ' ( ' & & c ! = ' ] ' )
2004-08-23 01:38:21 +00:00
{
pr_token [ i ] = c ;
i + + ;
pr_file_p + + ;
}
pr_token [ i ] = 0 ;
2005-02-28 07:16:19 +00:00
return i ! = 0 ;
2004-08-23 01:38:21 +00:00
}
2008-10-30 11:10:58 +00:00
pbool QCC_PR_LexMacroName ( void )
{
int c ;
int i ;
pr_token [ 0 ] = 0 ;
// skip whitespace
while ( ( c = * pr_file_p ) < = ' ' )
{
if ( c = = ' \n ' | | c = = 0 )
return false ;
pr_file_p + + ;
}
if ( pr_file_p [ 0 ] = = ' / ' )
{
if ( pr_file_p [ 1 ] = = ' / ' )
{ //comment alert
while ( * pr_file_p & & * pr_file_p ! = ' \n ' )
pr_file_p + + ;
return false ;
}
if ( pr_file_p [ 1 ] = = ' * ' )
return false ;
}
i = 0 ;
2008-11-09 22:29:28 +00:00
while ( ( c = * pr_file_p ) > ' ' & & c ! = ' \n ' & & c ! = ' , ' & & c ! = ' ; ' & & c ! = ' ) ' & & c ! = ' ( ' & & c ! = ' ] ' & & ! ( pr_file_p [ 0 ] = = ' . ' & & pr_file_p [ 1 ] = = ' . ' ) )
2008-10-30 11:10:58 +00:00
{
pr_token [ i ] = c ;
i + + ;
pr_file_p + + ;
}
pr_token [ i ] = 0 ;
return i ! = 0 ;
}
2005-02-28 07:16:19 +00:00
void QCC_PR_MacroFrame ( char * name , int value )
2004-08-23 01:38:21 +00:00
{
2004-11-15 13:03:32 +00:00
int i ;
2005-02-28 07:16:19 +00:00
for ( i = pr_nummacros - 1 ; i > = 0 ; i - - )
2004-08-23 01:38:21 +00:00
{
2005-02-28 07:16:19 +00:00
if ( ! STRCMP ( name , pr_framemacros [ i ] ) )
2004-11-15 13:03:32 +00:00
{
2005-02-28 07:16:19 +00:00
pr_framemacrovalue [ i ] = value ;
if ( i > = pr_oldmacros )
QCC_PR_ParseWarning ( WARN_DUPLICATEMACRO , " Duplicate macro defined (%s) " , pr_token ) ;
//else it's from an old file, and shouldn't be mentioned.
return ;
2004-11-15 13:03:32 +00:00
}
2005-02-28 07:16:19 +00:00
}
2004-11-15 13:03:32 +00:00
2008-01-16 03:43:53 +00:00
if ( strlen ( name ) + 1 > sizeof ( pr_framemacros [ 0 ] ) )
QCC_PR_ParseWarning ( ERR_TOOMANYFRAMEMACROS , " Name for frame macro %s is too long " , name ) ;
else
{
strcpy ( pr_framemacros [ pr_nummacros ] , name ) ;
pr_framemacrovalue [ pr_nummacros ] = value ;
pr_nummacros + + ;
if ( pr_nummacros > = MAX_FRAMES )
QCC_PR_ParseError ( ERR_TOOMANYFRAMEMACROS , " Too many frame macros defined " ) ;
}
2005-02-28 07:16:19 +00:00
}
2004-11-15 13:03:32 +00:00
2005-02-28 07:16:19 +00:00
void QCC_PR_ParseFrame ( void )
{
2008-10-30 11:10:58 +00:00
while ( QCC_PR_LexMacroName ( ) )
2005-02-28 07:16:19 +00:00
{
QCC_PR_MacroFrame ( pr_token , pr_macrovalue + + ) ;
2004-08-23 01:38:21 +00:00
}
}
/*
= = = = = = = = = = = = = =
PR_LexGrab
Deals with counting sequence numbers and replacing frame macros
= = = = = = = = = = = = = =
*/
void QCC_PR_LexGrab ( void )
2010-12-08 14:42:05 +00:00
{
2004-08-23 01:38:21 +00:00
pr_file_p + + ; // skip the $
// if (!QCC_PR_SimpleGetToken ())
// QCC_PR_ParseError ("hanging $");
if ( * pr_file_p < = ' ' )
QCC_PR_ParseError ( ERR_BADFRAMEMACRO , " hanging $ " ) ;
2008-10-30 11:10:58 +00:00
QCC_PR_LexMacroName ( ) ;
2004-08-23 01:38:21 +00:00
if ( ! * pr_token )
QCC_PR_ParseError ( ERR_BADFRAMEMACRO , " hanging $ " ) ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
// check for $frame
if ( ! STRCMP ( pr_token , " frame " ) | | ! STRCMP ( pr_token , " framesave " ) )
{
QCC_PR_ParseFrame ( ) ;
QCC_PR_Lex ( ) ;
}
// ignore other known $commands - just for model/spritegen
else if ( ! STRCMP ( pr_token , " cd " )
| | ! STRCMP ( pr_token , " origin " )
| | ! STRCMP ( pr_token , " base " )
| | ! STRCMP ( pr_token , " flags " )
| | ! STRCMP ( pr_token , " scale " )
| | ! STRCMP ( pr_token , " skin " ) )
{ // skip to end of line
2008-10-30 11:10:58 +00:00
while ( QCC_PR_LexMacroName ( ) )
2004-08-23 01:38:21 +00:00
;
QCC_PR_Lex ( ) ;
}
else if ( ! STRCMP ( pr_token , " flush " ) )
{
QCC_PR_ClearGrabMacros ( ) ;
2008-10-30 11:10:58 +00:00
while ( QCC_PR_LexMacroName ( ) )
2004-08-23 01:38:21 +00:00
;
QCC_PR_Lex ( ) ;
}
else if ( ! STRCMP ( pr_token , " framevalue " ) )
{
2008-10-30 11:10:58 +00:00
QCC_PR_LexMacroName ( ) ;
2004-08-23 01:38:21 +00:00
pr_macrovalue = atoi ( pr_token ) ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
QCC_PR_Lex ( ) ;
}
else if ( ! STRCMP ( pr_token , " framerestore " ) )
{
2008-10-30 11:10:58 +00:00
QCC_PR_LexMacroName ( ) ;
2005-02-28 07:16:19 +00:00
QCC_PR_ExpandMacro ( ) ;
2004-08-23 01:38:21 +00:00
pr_macrovalue = ( int ) pr_immediate . _float ;
2010-12-08 14:42:05 +00:00
2005-02-28 07:16:19 +00:00
QCC_PR_Lex ( ) ;
}
else if ( ! STRCMP ( pr_token , " modelname " ) )
{
int i ;
2008-10-30 11:10:58 +00:00
QCC_PR_LexMacroName ( ) ;
2005-02-28 07:16:19 +00:00
if ( * pr_framemodelname )
QCC_PR_MacroFrame ( pr_framemodelname , pr_macrovalue ) ;
strncpy ( pr_framemodelname , pr_token , sizeof ( pr_framemodelname ) - 1 ) ;
pr_framemodelname [ sizeof ( pr_framemodelname ) - 1 ] = ' \0 ' ;
i = QCC_PR_FindMacro ( pr_framemodelname ) ;
if ( i )
pr_macrovalue = i ;
else
i = 0 ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
QCC_PR_Lex ( ) ;
}
// look for a frame name macro
else
2005-02-28 07:16:19 +00:00
QCC_PR_ExpandMacro ( ) ;
2004-08-23 01:38:21 +00:00
}
//===========================
//compiler constants - dmw
pbool QCC_PR_UndefineName ( char * name )
{
// int a;
CompilerConstant_t * c ;
2005-02-09 19:32:30 +00:00
c = pHash_Get ( & compconstantstable , name ) ;
2004-08-23 01:38:21 +00:00
if ( ! c )
2004-09-07 18:27:08 +00:00
{
2005-09-28 16:57:10 +00:00
QCC_PR_ParseWarning ( WARN_UNDEFNOTDEFINED , " Precompiler constant %s was not defined " , name ) ;
2004-08-23 01:38:21 +00:00
return false ;
2004-09-07 18:27:08 +00:00
}
2004-08-23 01:38:21 +00:00
Hash_Remove ( & compconstantstable , name ) ;
return true ;
}
CompilerConstant_t * QCC_PR_DefineName ( char * name )
{
int i ;
CompilerConstant_t * cnst ;
// if (numCompilerConstants >= MAX_CONSTANTS)
// QCC_PR_ParseError("Too many compiler constants - %i >= %i", numCompilerConstants, MAX_CONSTANTS);
2011-11-08 06:00:35 +00:00
if ( strlen ( name ) > = MAXCONSTANTNAMELENGTH | | ! * name )
2010-07-03 21:49:48 +00:00
QCC_PR_ParseError ( ERR_NAMETOOLONG , " Compiler constant name length is too long or short " ) ;
2010-12-08 14:42:05 +00:00
2005-02-09 19:32:30 +00:00
cnst = pHash_Get ( & compconstantstable , name ) ;
2010-07-03 21:49:48 +00:00
if ( cnst )
2004-09-07 18:27:08 +00:00
{
QCC_PR_ParseWarning ( WARN_DUPLICATEDEFINITION , " Duplicate definition for Precompiler constant %s " , name ) ;
Hash_Remove ( & compconstantstable , name ) ;
}
2004-08-23 01:38:21 +00:00
cnst = qccHunkAlloc ( sizeof ( CompilerConstant_t ) ) ;
cnst - > used = false ;
cnst - > numparams = 0 ;
strcpy ( cnst - > name , name ) ;
cnst - > namelen = strlen ( name ) ;
2010-07-03 21:49:48 +00:00
cnst - > value = cnst - > name + strlen ( cnst - > name ) ;
2004-08-23 01:38:21 +00:00
for ( i = 0 ; i < MAXCONSTANTPARAMS ; i + + )
cnst - > params [ i ] [ 0 ] = ' \0 ' ;
2005-02-09 19:32:30 +00:00
pHash_Add ( & compconstantstable , cnst - > name , cnst , qccHunkAlloc ( sizeof ( bucket_t ) ) ) ;
2004-08-23 01:38:21 +00:00
return cnst ;
}
void QCC_PR_Undefine ( void )
{
QCC_PR_SimpleGetToken ( ) ;
QCC_PR_UndefineName ( pr_token ) ;
// QCC_PR_ParseError("%s was not defined.", pr_token);
}
void QCC_PR_ConditionCompilation ( void )
2005-09-28 16:57:10 +00:00
{
char * oldval ;
2004-08-23 01:38:21 +00:00
char * d ;
2010-07-03 21:49:48 +00:00
char * dbuf ;
int dbuflen ;
2004-08-23 01:38:21 +00:00
char * s ;
int quote = false ;
CompilerConstant_t * cnst ;
QCC_PR_SimpleGetToken ( ) ;
2010-12-08 14:42:05 +00:00
if ( ! QCC_PR_SimpleGetToken ( ) )
2004-08-23 01:38:21 +00:00
QCC_PR_ParseError ( ERR_NONAME , " No name defined for compiler constant " ) ;
2005-02-09 19:32:30 +00:00
cnst = pHash_Get ( & compconstantstable , pr_token ) ;
2004-09-13 03:14:42 +00:00
if ( cnst )
{
2005-09-28 16:57:10 +00:00
oldval = cnst - > value ;
2004-09-13 03:14:42 +00:00
Hash_Remove ( & compconstantstable , pr_token ) ;
}
2005-09-28 16:57:10 +00:00
else
oldval = NULL ;
2004-08-23 01:38:21 +00:00
cnst = QCC_PR_DefineName ( pr_token ) ;
if ( * pr_file_p = = ' ( ' )
{
s = pr_file_p + 1 ;
while ( * pr_file_p + + )
{
if ( * pr_file_p = = ' , ' )
{
2008-11-09 22:29:28 +00:00
if ( cnst - > numparams > = MAXCONSTANTPARAMS )
QCC_PR_ParseError ( ERR_MACROTOOMANYPARMS , " May not have more than %i parameters to a macro " , MAXCONSTANTPARAMS ) ;
2004-08-23 01:38:21 +00:00
strncpy ( cnst - > params [ cnst - > numparams ] , s , pr_file_p - s ) ;
cnst - > params [ cnst - > numparams ] [ pr_file_p - s ] = ' \0 ' ;
cnst - > numparams + + ;
pr_file_p + + ;
s = pr_file_p ;
}
if ( * pr_file_p = = ' ) ' )
{
2008-11-09 22:29:28 +00:00
if ( cnst - > numparams > = MAXCONSTANTPARAMS )
QCC_PR_ParseError ( ERR_MACROTOOMANYPARMS , " May not have more than %i parameters to a macro " , MAXCONSTANTPARAMS ) ;
2004-08-23 01:38:21 +00:00
strncpy ( cnst - > params [ cnst - > numparams ] , s , pr_file_p - s ) ;
cnst - > params [ cnst - > numparams ] [ pr_file_p - s ] = ' \0 ' ;
cnst - > numparams + + ;
pr_file_p + + ;
break ;
}
}
}
else cnst - > numparams = - 1 ;
s = pr_file_p ;
2010-07-03 21:49:48 +00:00
d = dbuf = NULL ;
dbuflen = 0 ;
2004-08-23 01:38:21 +00:00
while ( * s = = ' ' | | * s = = ' \t ' )
s + + ;
while ( 1 )
{
2010-07-03 21:49:48 +00:00
if ( ( d - dbuf ) + 2 > = dbuflen )
{
int len = d - dbuf ;
dbuflen = ( len + 128 ) * 2 ;
dbuf = qccHunkAlloc ( dbuflen ) ;
memcpy ( dbuf , d - len , len ) ;
d = dbuf + len ;
}
2008-01-26 18:32:41 +00:00
if ( * s = = ' \\ ' )
2004-10-16 13:18:58 +00:00
{
2008-01-26 18:32:41 +00:00
// read over a newline if necessary
if ( s [ 1 ] = = ' \n ' | | s [ 1 ] = = ' \r ' )
2004-10-16 13:18:58 +00:00
{
2008-01-26 18:32:41 +00:00
s + + ;
2009-03-20 01:12:01 +00:00
QCC_PR_NewLine ( false ) ;
2008-01-26 18:32:41 +00:00
* d + + = * s + + ;
if ( s [ - 1 ] = = ' \r ' & & s [ 0 ] = = ' \n ' )
{
* d + + = * s + + ;
}
2004-10-16 13:18:58 +00:00
}
2010-12-08 14:42:05 +00:00
}
2008-01-26 18:32:41 +00:00
else if ( * s = = ' \r ' | | * s = = ' \n ' | | * s = = ' \0 ' )
{
break ;
2004-10-16 13:18:58 +00:00
}
2004-08-23 01:38:21 +00:00
if ( ! quote & & s [ 0 ] = = ' / ' & & ( s [ 1 ] = = ' / ' | | s [ 1 ] = = ' * ' ) )
break ;
if ( * s = = ' \" ' )
quote = ! quote ;
* d = * s ;
d + + ;
s + + ;
}
* d = ' \0 ' ;
2010-07-03 21:49:48 +00:00
cnst - > value = dbuf ;
2005-09-28 16:57:10 +00:00
2005-10-17 17:17:20 +00:00
if ( oldval )
{ //we always warn if it was already defined
//we use different warning codes so that -Wno-mundane can be used to ignore identical redefinitions.
if ( strcmp ( oldval , cnst - > value ) )
QCC_PR_ParseWarning ( WARN_DUPLICATEPRECOMPILER , " Alternate precompiler definition of %s " , pr_token ) ;
else
QCC_PR_ParseWarning ( WARN_IDENTICALPRECOMPILER , " Identical precompiler definition of %s " , pr_token ) ;
}
2008-01-26 18:32:41 +00:00
pr_file_p = s ;
2004-08-23 01:38:21 +00:00
}
2011-11-08 06:00:35 +00:00
/* *buffer, *bufferlen and *buffermax should be NULL/0 at the start */
static void QCC_PR_ExpandStrCat ( char * * buffer , int * bufferlen , int * buffermax , char * newdata , int newlen )
{
int newmax = * bufferlen + newlen ;
if ( newmax < * bufferlen )
{
QCC_PR_ParseWarning ( ERR_INTERNAL , " out of memory " ) ;
return ;
}
if ( newmax > * buffermax )
{
char * newbuf ;
if ( newmax < 64 )
newmax = 64 ;
if ( newmax < * bufferlen * 2 )
{
newmax = * bufferlen * 2 ;
if ( newmax < * bufferlen ) /*overflowed?*/
{
QCC_PR_ParseWarning ( ERR_INTERNAL , " out of memory " ) ;
return ;
}
}
newbuf = realloc ( * buffer , newmax ) ;
if ( ! newbuf )
{
QCC_PR_ParseWarning ( ERR_INTERNAL , " out of memory " ) ;
return ; /*OOM*/
}
* buffer = newbuf ;
* buffermax = newmax ;
}
memcpy ( * buffer + * bufferlen , newdata , newlen ) ;
* bufferlen + = newlen ;
/*no null terminator, remember to cat one if required*/
}
2004-08-23 01:38:21 +00:00
int QCC_PR_CheakCompConst ( void )
{
char * oldpr_file_p = pr_file_p ;
2004-10-27 23:51:52 +00:00
int whitestart ;
2004-08-23 01:38:21 +00:00
CompilerConstant_t * c ;
char * end ;
for ( end = pr_file_p ; ; end + + )
{
if ( * end < = ' ' )
break ;
if ( * end = = ' ) '
| | * end = = ' ( '
| | * end = = ' + '
| | * end = = ' - '
| | * end = = ' * '
| | * end = = ' / '
| | * end = = ' | '
| | * end = = ' & '
| | * end = = ' = '
| | * end = = ' ^ '
| | * end = = ' ~ '
| | * end = = ' [ '
| | * end = = ' ] '
| | * end = = ' \" '
| | * end = = ' { '
| | * end = = ' } '
| | * end = = ' ; '
| | * end = = ' : '
| | * end = = ' , '
| | * end = = ' . '
| | * end = = ' # ' )
break ;
}
strncpy ( pr_token , pr_file_p , end - pr_file_p ) ;
pr_token [ end - pr_file_p ] = ' \0 ' ;
2005-02-28 07:16:19 +00:00
2004-08-23 01:38:21 +00:00
// printf("%s\n", pr_token);
2005-02-09 19:32:30 +00:00
c = pHash_Get ( & compconstantstable , pr_token ) ;
2004-08-23 01:38:21 +00:00
2005-12-21 03:07:33 +00:00
if ( c & & ! c - > inside )
2004-08-23 01:38:21 +00:00
{
pr_file_p = oldpr_file_p + strlen ( c - > name ) ;
2005-02-28 07:16:19 +00:00
while ( * pr_file_p = = ' ' | | * pr_file_p = = ' \t ' )
pr_file_p + + ;
2004-08-23 01:38:21 +00:00
if ( c - > numparams > = 0 )
{
if ( * pr_file_p = = ' ( ' )
{
int p ;
char * start ;
2011-11-08 06:00:35 +00:00
char * starttok ;
char * buffer ;
int buffermax ;
int bufferlen ;
2004-08-23 01:38:21 +00:00
char * paramoffset [ MAXCONSTANTPARAMS + 1 ] ;
int param = 0 ;
2004-12-27 18:47:32 +00:00
int plevel = 0 ;
2004-08-23 01:38:21 +00:00
pr_file_p + + ;
2005-02-28 07:16:19 +00:00
while ( * pr_file_p = = ' ' | | * pr_file_p = = ' \t ' )
pr_file_p + + ;
2004-08-23 01:38:21 +00:00
start = pr_file_p ;
while ( 1 )
{
2008-01-23 00:37:56 +00:00
// handle strings correctly by ignoring them
if ( * pr_file_p = = ' \" ' )
{
do {
pr_file_p + + ;
} while ( ( pr_file_p [ - 1 ] = = ' \\ ' | | pr_file_p [ 0 ] ! = ' \" ' ) & & * pr_file_p & & * pr_file_p ! = ' \n ' ) ;
}
2004-12-27 18:47:32 +00:00
if ( * pr_file_p = = ' ( ' )
plevel + + ;
else if ( ! plevel & & ( * pr_file_p = = ' , ' | | * pr_file_p = = ' ) ' ) )
2004-08-23 01:38:21 +00:00
{
paramoffset [ param + + ] = start ;
start = pr_file_p + 1 ;
if ( * pr_file_p = = ' ) ' )
{
* pr_file_p = ' \0 ' ;
pr_file_p + + ;
break ;
}
* pr_file_p = ' \0 ' ;
pr_file_p + + ;
2005-02-28 07:16:19 +00:00
while ( * pr_file_p = = ' ' | | * pr_file_p = = ' \t ' )
2008-07-27 02:48:59 +00:00
{
2005-02-28 07:16:19 +00:00
pr_file_p + + ;
2008-07-27 02:48:59 +00:00
start + + ;
}
2008-01-23 00:37:56 +00:00
// move back by one char because we move forward by one at the end of the loop
pr_file_p - - ;
2004-08-23 01:38:21 +00:00
if ( param = = MAXCONSTANTPARAMS )
QCC_PR_ParseError ( ERR_TOOMANYPARAMS , " Too many parameters in macro call " ) ;
2004-12-27 18:47:32 +00:00
} else if ( * pr_file_p = = ' ) ' )
plevel - - ;
2009-03-20 01:12:01 +00:00
else if ( * pr_file_p = = ' \n ' )
QCC_PR_NewLine ( false ) ;
2004-12-27 18:47:32 +00:00
2008-07-27 02:48:59 +00:00
// see that *pr_file_p = '\0' up there? Must ++ BEFORE checking for !*pr_file_p
pr_file_p + + ;
2004-08-23 01:38:21 +00:00
if ( ! * pr_file_p )
QCC_PR_ParseError ( ERR_EOF , " EOF on macro call " ) ;
}
if ( param < c - > numparams )
QCC_PR_ParseError ( ERR_TOOFEWPARAMS , " Not enough macro parameters " ) ;
paramoffset [ param ] = start ;
2011-11-08 06:00:35 +00:00
buffer = NULL ;
bufferlen = 0 ;
buffermax = 0 ;
2004-08-23 01:38:21 +00:00
oldpr_file_p = pr_file_p ;
pr_file_p = c - > value ;
2004-10-27 23:51:52 +00:00
for ( ; ; )
2004-08-23 01:38:21 +00:00
{
2011-11-08 06:00:35 +00:00
whitestart = bufferlen ;
starttok = pr_file_p ;
2004-10-19 16:10:14 +00:00
while ( * pr_file_p < = ' ' ) //copy across whitespace
{
if ( ! * pr_file_p )
break ;
2011-11-08 06:00:35 +00:00
pr_file_p + + ;
}
if ( starttok ! = pr_file_p )
{
QCC_PR_ExpandStrCat ( & buffer , & bufferlen , & buffermax , starttok , pr_file_p - starttok ) ;
2004-10-19 16:10:14 +00:00
}
2008-07-27 02:48:59 +00:00
if ( * pr_file_p = = ' \" ' )
{
2011-11-08 06:00:35 +00:00
starttok = pr_file_p ;
2008-07-27 02:48:59 +00:00
do
{
2011-11-08 06:00:35 +00:00
pr_file_p + + ;
2008-07-27 02:48:59 +00:00
} while ( ( pr_file_p [ - 1 ] = = ' \\ ' | | pr_file_p [ 0 ] ! = ' \" ' ) & & * pr_file_p & & * pr_file_p ! = ' \n ' ) ;
2011-11-08 06:00:35 +00:00
if ( * pr_file_p = = ' \" ' )
pr_file_p + + ;
QCC_PR_ExpandStrCat ( & buffer , & bufferlen , & buffermax , starttok , pr_file_p - starttok ) ;
2008-07-27 02:48:59 +00:00
continue ;
}
else if ( * pr_file_p = = ' # ' ) //if you ask for #a##b you will be shot. use #a #b instead, or chain macros.
2004-10-27 23:51:52 +00:00
{
if ( pr_file_p [ 1 ] = = ' # ' )
2011-11-08 06:00:35 +00:00
{ //concatinate (strip out whitespace before the token)
bufferlen = whitestart ;
2004-10-27 23:51:52 +00:00
pr_file_p + = 2 ;
}
else
{ //stringify
pr_file_p + + ;
2004-11-13 17:18:34 +00:00
pr_file_p = QCC_COM_Parse2 ( pr_file_p ) ;
2004-10-27 23:51:52 +00:00
if ( ! pr_file_p )
break ;
for ( p = 0 ; p < param ; p + + )
{
if ( ! STRCMP ( qcc_token , c - > params [ p ] ) )
{
2011-11-08 06:00:35 +00:00
QCC_PR_ExpandStrCat ( & buffer , & bufferlen , & buffermax , " \" " , 1 ) ;
QCC_PR_ExpandStrCat ( & buffer , & bufferlen , & buffermax , paramoffset [ p ] , strlen ( paramoffset [ p ] ) ) ;
QCC_PR_ExpandStrCat ( & buffer , & bufferlen , & buffermax , " \" " , 1 ) ;
2004-10-27 23:51:52 +00:00
break ;
}
}
if ( p = = param )
{
2011-11-08 06:00:35 +00:00
QCC_PR_ExpandStrCat ( & buffer , & bufferlen , & buffermax , " # " , 1 ) ;
QCC_PR_ExpandStrCat ( & buffer , & bufferlen , & buffermax , qcc_token , strlen ( qcc_token ) ) ;
2008-01-27 01:14:44 +00:00
//QCC_PR_ParseWarning(0, "Stringification ignored");
2004-10-27 23:51:52 +00:00
}
continue ; //already did this one
}
}
2004-11-13 17:18:34 +00:00
pr_file_p = QCC_COM_Parse2 ( pr_file_p ) ;
2004-08-23 01:38:21 +00:00
if ( ! pr_file_p )
break ;
for ( p = 0 ; p < param ; p + + )
{
if ( ! STRCMP ( qcc_token , c - > params [ p ] ) )
{
2011-11-08 06:00:35 +00:00
QCC_PR_ExpandStrCat ( & buffer , & bufferlen , & buffermax , paramoffset [ p ] , strlen ( paramoffset [ p ] ) ) ;
2004-08-23 01:38:21 +00:00
break ;
}
}
if ( p = = param )
2011-11-08 06:00:35 +00:00
QCC_PR_ExpandStrCat ( & buffer , & bufferlen , & buffermax , qcc_token , strlen ( qcc_token ) ) ;
2004-10-27 23:51:52 +00:00
}
2004-08-23 01:38:21 +00:00
for ( p = 0 ; p < param - 1 ; p + + )
paramoffset [ p ] [ strlen ( paramoffset [ p ] ) ] = ' , ' ;
paramoffset [ p ] [ strlen ( paramoffset [ p ] ) ] = ' ) ' ;
pr_file_p = oldpr_file_p ;
2011-11-08 06:00:35 +00:00
if ( ! bufferlen )
2008-11-09 22:29:28 +00:00
expandedemptymacro = true ;
2011-11-08 06:00:35 +00:00
else
{
QCC_PR_ExpandStrCat ( & buffer , & bufferlen , & buffermax , " \0 " , 1 ) ;
QCC_PR_IncludeChunkEx ( buffer , true , NULL , c ) ;
}
free ( buffer ) ;
2004-08-23 01:38:21 +00:00
}
else
2011-11-08 06:00:35 +00:00
QCC_PR_ParseError ( ERR_TOOFEWPARAMS , " Macro without argument list " ) ;
2004-08-23 01:38:21 +00:00
}
else
2008-11-09 22:29:28 +00:00
{
if ( ! * c - > value )
expandedemptymacro = true ;
2008-01-27 01:14:44 +00:00
QCC_PR_IncludeChunkEx ( c - > value , false , NULL , c ) ;
2008-11-09 22:29:28 +00:00
}
2004-08-23 01:38:21 +00:00
QCC_PR_Lex ( ) ;
return true ;
}
if ( ! strncmp ( pr_file_p , " __TIME__ " , 8 ) )
{
2005-04-02 18:00:45 +00:00
static char retbuf [ 128 ] ;
time_t long_time ;
time ( & long_time ) ;
strftime ( retbuf , sizeof ( retbuf ) ,
2005-06-04 04:20:20 +00:00
" \" %H:%M \" " , localtime ( & long_time ) ) ;
2005-04-02 18:00:45 +00:00
2004-08-23 01:38:21 +00:00
pr_file_p = retbuf ;
QCC_PR_Lex ( ) ; //translate the macro's value
pr_file_p = oldpr_file_p + 8 ;
return true ;
}
if ( ! strncmp ( pr_file_p , " __DATE__ " , 8 ) )
{
2005-04-02 18:00:45 +00:00
static char retbuf [ 128 ] ;
time_t long_time ;
time ( & long_time ) ;
strftime ( retbuf , sizeof ( retbuf ) ,
2005-04-02 18:39:22 +00:00
" \" %a %d %b %Y \" " , localtime ( & long_time ) ) ;
2005-04-02 18:00:45 +00:00
2004-08-23 01:38:21 +00:00
pr_file_p = retbuf ;
QCC_PR_Lex ( ) ; //translate the macro's value
pr_file_p = oldpr_file_p + 8 ;
return true ;
}
if ( ! strncmp ( pr_file_p , " __FILE__ " , 8 ) )
2010-12-08 14:42:05 +00:00
{
2004-08-23 01:38:21 +00:00
static char retbuf [ 256 ] ;
sprintf ( retbuf , " \" %s \" " , strings + s_file ) ;
pr_file_p = retbuf ;
QCC_PR_Lex ( ) ; //translate the macro's value
pr_file_p = oldpr_file_p + 8 ;
return true ;
}
if ( ! strncmp ( pr_file_p , " __LINE__ " , 8 ) )
{
static char retbuf [ 256 ] ;
sprintf ( retbuf , " \" %i \" " , pr_source_line ) ;
pr_file_p = retbuf ;
QCC_PR_Lex ( ) ; //translate the macro's value
pr_file_p = oldpr_file_p + 8 ;
return true ;
}
if ( ! strncmp ( pr_file_p , " __FUNC__ " , 8 ) )
2010-12-08 14:42:05 +00:00
{
2004-08-23 01:38:21 +00:00
static char retbuf [ 256 ] ;
sprintf ( retbuf , " \" %s \" " , pr_scope - > name ) ;
pr_file_p = retbuf ;
QCC_PR_Lex ( ) ; //translate the macro's value
pr_file_p = oldpr_file_p + 8 ;
return true ;
}
if ( ! strncmp ( pr_file_p , " __NULL__ " , 8 ) )
{
static char retbuf [ 256 ] ;
2009-11-07 04:34:32 +00:00
sprintf ( retbuf , " 0i " ) ;
2004-08-23 01:38:21 +00:00
pr_file_p = retbuf ;
QCC_PR_Lex ( ) ; //translate the macro's value
pr_file_p = oldpr_file_p + 8 ;
return true ;
}
return false ;
}
char * QCC_PR_CheakCompConstString ( char * def )
{
char * s ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
CompilerConstant_t * c ;
2005-02-09 19:32:30 +00:00
c = pHash_Get ( & compconstantstable , def ) ;
2004-08-23 01:38:21 +00:00
2010-12-08 14:42:05 +00:00
if ( c )
2004-08-23 01:38:21 +00:00
{
s = QCC_PR_CheakCompConstString ( c - > value ) ;
return s ;
}
return def ;
}
CompilerConstant_t * QCC_PR_CheckCompConstDefined ( char * def )
{
2005-02-09 19:32:30 +00:00
CompilerConstant_t * c = pHash_Get ( & compconstantstable , def ) ;
2004-08-23 01:38:21 +00:00
return c ;
}
//============================================================================
/*
= = = = = = = = = = = = = =
PR_Lex
Sets pr_token , pr_token_type , and possibly pr_immediate and pr_immediate_type
= = = = = = = = = = = = = =
*/
void QCC_PR_Lex ( void )
{
int c ;
pr_token [ 0 ] = 0 ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
if ( ! pr_file_p )
{
if ( QCC_PR_UnInclude ( ) )
2010-12-08 14:42:05 +00:00
{
2004-08-23 01:38:21 +00:00
QCC_PR_Lex ( ) ;
return ;
}
pr_token_type = tt_eof ;
return ;
}
QCC_PR_LexWhitespace ( ) ;
if ( ! pr_file_p )
{
if ( QCC_PR_UnInclude ( ) )
2010-12-08 14:42:05 +00:00
{
2004-08-23 01:38:21 +00:00
QCC_PR_Lex ( ) ;
return ;
}
pr_token_type = tt_eof ;
return ;
}
c = * pr_file_p ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
if ( ! c )
{
if ( QCC_PR_UnInclude ( ) )
2010-12-08 14:42:05 +00:00
{
2004-08-23 01:38:21 +00:00
QCC_PR_Lex ( ) ;
return ;
}
pr_token_type = tt_eof ;
return ;
}
// handle quoted strings as a unit
if ( c = = ' \" ' )
{
QCC_PR_LexString ( ) ;
return ;
}
// handle quoted vectors as a unit
if ( c = = ' \' ' )
{
QCC_PR_LexVector ( ) ;
return ;
}
// if the first character is a valid identifier, parse until a non-id
// character is reached
2004-11-18 17:55:04 +00:00
if ( c = = ' ~ ' | | c = = ' % ' ) //let's see which one we make into an operator first... possibly both...
2004-08-23 01:38:21 +00:00
{
2009-08-29 17:51:13 +00:00
QCC_PR_ParseWarning ( 0 , " ~ or %% prefixes to denote integers are deprecated. Please use a postfix of 'i' " ) ;
2004-08-23 01:38:21 +00:00
pr_file_p + + ;
pr_token_type = tt_immediate ;
pr_immediate_type = type_integer ;
pr_immediate . _int = QCC_PR_LexInteger ( ) ;
return ;
}
if ( c = = ' 0 ' & & pr_file_p [ 1 ] = = ' x ' )
{
pr_token_type = tt_immediate ;
QCC_PR_LexNumber ( ) ;
return ;
}
if ( ( c = = ' . ' & & pr_file_p [ 1 ] > = ' 0 ' & & pr_file_p [ 1 ] < = ' 9 ' ) | | ( c > = ' 0 ' & & c < = ' 9 ' ) | | ( c = = ' - ' & & pr_file_p [ 1 ] > = ' 0 ' & & pr_file_p [ 1 ] < = ' 9 ' ) )
{
pr_token_type = tt_immediate ;
2009-08-29 14:56:42 +00:00
QCC_PR_LexNumber ( ) ;
2004-08-23 01:38:21 +00:00
return ;
}
if ( c = = ' # ' & & ! ( pr_file_p [ 1 ] = = ' - ' | | ( pr_file_p [ 1 ] > = ' 0 ' & & pr_file_p [ 1 ] < = ' 9 ' ) ) ) //hash and not number
{
pr_file_p + + ;
if ( ! QCC_PR_CheakCompConst ( ) )
{
if ( ! QCC_PR_SimpleGetToken ( ) )
strcpy ( pr_token , " unknown " ) ;
QCC_PR_ParseError ( ERR_CONSTANTNOTDEFINED , " Explicit precompiler usage when not defined %s " , pr_token ) ;
}
else
if ( pr_token_type = = tt_eof )
QCC_PR_Lex ( ) ;
return ;
}
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
if ( ( c > = ' a ' & & c < = ' z ' ) | | ( c > = ' A ' & & c < = ' Z ' ) | | c = = ' _ ' )
{
2005-09-05 23:50:46 +00:00
if ( flag_hashonly | | ! QCC_PR_CheakCompConst ( ) ) //look for a macro.
2004-08-23 01:38:21 +00:00
QCC_PR_LexName ( ) ;
else
if ( pr_token_type = = tt_eof )
{
if ( QCC_PR_UnInclude ( ) )
2010-12-08 14:42:05 +00:00
{
2004-08-23 01:38:21 +00:00
QCC_PR_Lex ( ) ;
return ;
}
pr_token_type = tt_eof ;
}
return ;
}
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
if ( c = = ' $ ' )
{
QCC_PR_LexGrab ( ) ;
return ;
}
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
// parse symbol strings until a non-symbol is found
QCC_PR_LexPunctuation ( ) ;
}
//=============================================================================
void QCC_PR_ParsePrintDef ( int type , QCC_def_t * def )
{
if ( qccwarningdisabled [ type ] )
return ;
if ( def - > s_file )
2009-11-04 21:16:50 +00:00
{
if ( flag_msvcstyle )
printf ( " %s(%i) : %s is defined here \n " , strings + def - > s_file , def - > s_line , def - > name ) ;
else
printf ( " %s:%i: %s is defined here \n " , strings + def - > s_file , def - > s_line , def - > name ) ;
}
2004-08-23 01:38:21 +00:00
}
2006-01-14 03:37:22 +00:00
void * errorscope ;
void QCC_PR_PrintScope ( void )
{
if ( pr_scope )
{
if ( errorscope ! = pr_scope )
2006-05-07 20:57:30 +00:00
printf ( " in function %s (line %i), \n " , pr_scope - > name , pr_scope - > s_line ) ;
2006-01-14 03:37:22 +00:00
errorscope = pr_scope ;
}
else
{
if ( errorscope )
2006-05-07 20:57:30 +00:00
printf ( " at global scope, \n " ) ;
2006-01-14 03:37:22 +00:00
errorscope = NULL ;
}
}
void QCC_PR_ResetErrorScope ( void )
{
errorscope = NULL ;
}
2004-08-23 01:38:21 +00:00
/*
= = = = = = = = = = = =
PR_ParseError
Aborts the current file load
= = = = = = = = = = = =
*/
# ifndef QCC
void editbadfile ( char * file , int line ) ;
# endif
void VARGS QCC_PR_ParseError ( int errortype , char * error , . . . )
{
va_list argptr ;
char string [ 1024 ] ;
va_start ( argptr , error ) ;
QC_vsnprintf ( string , sizeof ( string ) - 1 , error , argptr ) ;
va_end ( argptr ) ;
# ifndef QCC
editbadfile ( strings + s_file , pr_source_line ) ;
# endif
2006-01-14 03:37:22 +00:00
QCC_PR_PrintScope ( ) ;
2009-11-04 21:16:50 +00:00
if ( flag_msvcstyle )
printf ( " %s(%i) : error: %s \n " , strings + s_file , pr_source_line , string ) ;
else
printf ( " %s:%i: error: %s \n " , strings + s_file , pr_source_line , string ) ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
longjmp ( pr_parse_abort , 1 ) ;
}
void VARGS QCC_PR_ParseErrorPrintDef ( int errortype , QCC_def_t * def , char * error , . . . )
{
va_list argptr ;
char string [ 1024 ] ;
va_start ( argptr , error ) ;
QC_vsnprintf ( string , sizeof ( string ) - 1 , error , argptr ) ;
va_end ( argptr ) ;
# ifndef QCC
editbadfile ( strings + s_file , pr_source_line ) ;
# endif
2006-01-14 03:37:22 +00:00
QCC_PR_PrintScope ( ) ;
2009-11-04 21:16:50 +00:00
if ( flag_msvcstyle )
printf ( " %s(%i) : error: %s \n " , strings + s_file , pr_source_line , string ) ;
else
printf ( " %s:%i: error: %s \n " , strings + s_file , pr_source_line , string ) ;
2004-08-23 01:38:21 +00:00
QCC_PR_ParsePrintDef ( WARN_ERROR , def ) ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
longjmp ( pr_parse_abort , 1 ) ;
}
void VARGS QCC_PR_ParseWarning ( int type , char * error , . . . )
{
va_list argptr ;
char string [ 1024 ] ;
2004-09-02 12:58:49 +00:00
if ( type < ERR_PARSEERRORS & & qccwarningdisabled [ type ] )
2004-08-23 01:38:21 +00:00
return ;
va_start ( argptr , error ) ;
QC_vsnprintf ( string , sizeof ( string ) - 1 , error , argptr ) ;
va_end ( argptr ) ;
2006-01-14 03:37:22 +00:00
QCC_PR_PrintScope ( ) ;
2004-09-02 12:58:49 +00:00
if ( type > = ERR_PARSEERRORS )
{
2009-11-04 21:16:50 +00:00
if ( flag_msvcstyle )
printf ( " %s(%i) : error: %s \n " , strings + s_file , pr_source_line , string ) ;
else
printf ( " %s:%i: error: %s \n " , strings + s_file , pr_source_line , string ) ;
2004-09-02 12:58:49 +00:00
pr_error_count + + ;
}
else
2005-12-16 17:15:43 +00:00
{
2009-11-04 21:16:50 +00:00
if ( flag_msvcstyle )
printf ( " %s(%i) : warning: %s \n " , strings + s_file , pr_source_line , string ) ;
else
printf ( " %s:%i: warning: %s \n " , strings + s_file , pr_source_line , string ) ;
2005-12-16 17:15:43 +00:00
pr_warning_count + + ;
}
2004-08-23 01:38:21 +00:00
}
2010-05-01 22:47:47 +00:00
void VARGS QCC_PR_Note ( int type , char * file , int line , char * error , . . . )
{
va_list argptr ;
char string [ 1024 ] ;
if ( qccwarningdisabled [ type ] )
return ;
va_start ( argptr , error ) ;
QC_vsnprintf ( string , sizeof ( string ) - 1 , error , argptr ) ;
va_end ( argptr ) ;
QCC_PR_PrintScope ( ) ;
if ( file )
{
if ( flag_msvcstyle )
printf ( " %s(%i) : note: %s \n " , file , line , string ) ;
else
printf ( " %s:%i: note: %s \n " , file , line , string ) ;
}
else
printf ( " note: %s \n " , string ) ;
}
2011-10-03 02:45:44 +00:00
pbool VARGS QCC_PR_Warning ( int type , char * file , int line , char * error , . . . )
2004-08-23 01:38:21 +00:00
{
va_list argptr ;
char string [ 1024 ] ;
if ( qccwarningdisabled [ type ] )
2011-10-03 02:45:44 +00:00
return false ;
2004-08-23 01:38:21 +00:00
va_start ( argptr , error ) ;
QC_vsnprintf ( string , sizeof ( string ) - 1 , error , argptr ) ;
va_end ( argptr ) ;
2006-01-14 03:37:22 +00:00
QCC_PR_PrintScope ( ) ;
2004-08-23 01:38:21 +00:00
if ( file )
2009-11-04 21:16:50 +00:00
{
if ( flag_msvcstyle )
printf ( " %s(%i) : warning: %s \n " , file , line , string ) ;
else
printf ( " %s:%i: warning: %s \n " , file , line , string ) ;
}
2004-08-23 01:38:21 +00:00
else
printf ( " warning: %s \n " , string ) ;
2005-12-16 17:15:43 +00:00
pr_warning_count + + ;
2011-10-03 02:45:44 +00:00
return true ;
2004-08-23 01:38:21 +00:00
}
/*
= = = = = = = = = = = = =
PR_Expect
Issues an error if the current token isn ' t equal to string
Gets the next token
= = = = = = = = = = = = =
*/
# ifndef COMMONINLINES
void QCC_PR_Expect ( char * string )
{
if ( STRCMP ( string , pr_token ) )
QCC_PR_ParseError ( ERR_EXPECTED , " expected %s, found %s " , string , pr_token ) ;
QCC_PR_Lex ( ) ;
}
# endif
/*
= = = = = = = = = = = = =
PR_Check
Returns true and gets the next token if the current token equals string
Returns false and does nothing otherwise
= = = = = = = = = = = = =
*/
# ifndef COMMONINLINES
2005-03-20 02:57:11 +00:00
pbool QCC_PR_CheckToken ( char * string )
2004-08-23 01:38:21 +00:00
{
2008-10-16 23:04:36 +00:00
if ( pr_token_type ! = tt_punct )
return false ;
if ( STRCMP ( string , pr_token ) )
return false ;
2010-12-08 14:42:05 +00:00
2008-10-16 23:04:36 +00:00
QCC_PR_Lex ( ) ;
return true ;
}
pbool QCC_PR_CheckImmediate ( char * string )
{
if ( pr_token_type ! = tt_immediate )
return false ;
2004-08-23 01:38:21 +00:00
if ( STRCMP ( string , pr_token ) )
return false ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
QCC_PR_Lex ( ) ;
return true ;
}
2005-03-20 02:57:11 +00:00
pbool QCC_PR_CheckName ( char * string )
2005-02-09 19:32:30 +00:00
{
2008-10-16 23:04:36 +00:00
if ( pr_token_type ! = tt_name )
return false ;
2010-12-08 14:42:05 +00:00
if ( flag_caseinsensative )
2005-03-20 02:57:11 +00:00
{
if ( stricmp ( string , pr_token ) )
return false ;
}
else
{
if ( STRCMP ( string , pr_token ) )
return false ;
}
QCC_PR_Lex ( ) ;
return true ;
}
pbool QCC_PR_CheckKeyword ( int keywordenabled , char * string )
{
if ( ! keywordenabled )
2005-02-09 19:32:30 +00:00
return false ;
2010-12-08 14:42:05 +00:00
if ( flag_caseinsensative )
2005-03-20 02:57:11 +00:00
{
if ( stricmp ( string , pr_token ) )
return false ;
}
else
{
if ( STRCMP ( string , pr_token ) )
return false ;
}
2005-02-09 19:32:30 +00:00
QCC_PR_Lex ( ) ;
return true ;
}
2005-03-20 02:57:11 +00:00
# endif
2005-02-09 19:32:30 +00:00
2004-08-23 01:38:21 +00:00
/*
= = = = = = = = = = = =
PR_ParseName
Checks to see if the current token is a valid name
= = = = = = = = = = = =
*/
char * QCC_PR_ParseName ( void )
{
static char ident [ MAX_NAME ] ;
char * ret ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
if ( pr_token_type ! = tt_name )
2011-09-03 03:49:43 +00:00
{
if ( pr_token_type = = tt_eof )
QCC_PR_ParseError ( ERR_EOF , " unexpected EOF " , pr_token ) ;
else
QCC_PR_ParseError ( ERR_NOTANAME , " \" %s \" - not a name " , pr_token ) ;
}
2004-08-23 01:38:21 +00:00
if ( strlen ( pr_token ) > = MAX_NAME - 1 )
QCC_PR_ParseError ( ERR_NAMETOOLONG , " name too long " ) ;
strcpy ( ident , pr_token ) ;
QCC_PR_Lex ( ) ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
ret = qccHunkAlloc ( strlen ( ident ) + 1 ) ;
strcpy ( ret , ident ) ;
return ret ;
// return ident;
}
/*
= = = = = = = = = = = =
PR_FindType
Returns a preexisting complex type that matches the parm , or allocates
a new one and copies it out .
= = = = = = = = = = = =
*/
//0 if same
QCC_type_t * QCC_PR_NewType ( char * name , int basictype ) ;
int typecmp ( QCC_type_t * a , QCC_type_t * b )
{
if ( a = = b )
return 0 ;
if ( ! a | | ! b )
return 1 ; //different (^ and not both null)
if ( a - > type ! = b - > type )
return 1 ;
if ( a - > num_parms ! = b - > num_parms )
2011-11-08 06:00:35 +00:00
{
2004-08-23 01:38:21 +00:00
return 1 ;
2011-11-08 06:00:35 +00:00
}
2004-08-23 01:38:21 +00:00
if ( a - > size ! = b - > size )
return 1 ;
2004-10-26 14:41:05 +00:00
// if (STRCMP(a->name, b->name)) //This isn't 100% clean.
// return 1;
2004-08-23 01:38:21 +00:00
if ( typecmp ( a - > aux_type , b - > aux_type ) )
return 1 ;
if ( a - > param | | b - > param )
{
a = a - > param ;
b = b - > param ;
while ( a | | b )
{
if ( typecmp ( a , b ) )
return 1 ;
a = a - > next ;
b = b - > next ;
}
}
return 0 ;
}
QCC_type_t * QCC_PR_DuplicateType ( QCC_type_t * in )
{
QCC_type_t * out , * op , * ip ;
if ( ! in )
return NULL ;
out = QCC_PR_NewType ( in - > name , in - > type ) ;
out - > aux_type = QCC_PR_DuplicateType ( in - > aux_type ) ;
out - > param = QCC_PR_DuplicateType ( in - > param ) ;
ip = in - > param ;
op = NULL ;
while ( ip )
{
if ( ! op )
out - > param = op = QCC_PR_DuplicateType ( ip ) ;
else
op = ( op - > next = QCC_PR_DuplicateType ( ip ) ) ;
ip = ip - > next ;
}
2011-11-08 06:00:35 +00:00
out - > arraysize = in - > arraysize ;
2004-08-23 01:38:21 +00:00
out - > size = in - > size ;
out - > num_parms = in - > num_parms ;
out - > ofs = in - > ofs ;
out - > name = in - > name ;
out - > parentclass = in - > parentclass ;
return out ;
}
char * TypeName ( QCC_type_t * type )
{
static char buffer [ 2 ] [ 512 ] ;
static int op ;
char * ret ;
op + + ;
ret = buffer [ op & 1 ] ;
if ( type - > type = = ev_field )
{
type = type - > aux_type ;
* ret + + = ' . ' ;
}
* ret = 0 ;
if ( type - > type = = ev_function )
{
2011-11-08 06:00:35 +00:00
pbool varg = type - > num_parms < 0 ;
int args = type - > num_parms ;
if ( args < 0 )
args = - ( args + 1 ) ;
2004-08-23 01:38:21 +00:00
strcat ( ret , type - > aux_type - > name ) ;
strcat ( ret , " ( " ) ;
type = type - > param ;
while ( type )
{
2011-11-08 06:00:35 +00:00
if ( args < = 0 )
strcat ( ret , " optional " ) ;
args - - ;
2004-08-23 01:38:21 +00:00
strcat ( ret , type - > name ) ;
type = type - > next ;
2011-11-08 06:00:35 +00:00
if ( type | | varg )
2004-08-23 01:38:21 +00:00
strcat ( ret , " , " ) ;
}
2011-11-08 06:00:35 +00:00
if ( varg )
{
strcat ( ret , " ... " ) ;
}
2004-08-23 01:38:21 +00:00
strcat ( ret , " ) " ) ;
}
else if ( type - > type = = ev_entity & & type - > parentclass )
{
ret = buffer [ op & 1 ] ;
* ret = 0 ;
strcat ( ret , " class " ) ;
strcat ( ret , type - > name ) ;
/* strcat(ret, " {");
type = type - > param ;
while ( type )
{
strcat ( ret , type - > name ) ;
type = type - > next ;
if ( type )
strcat ( ret , " , " ) ;
}
strcat ( ret , " } " ) ;
*/
}
else
strcpy ( ret , type - > name ) ;
return buffer [ op & 1 ] ;
}
//#define typecmp(a, b) (a && ((a)->type==(b)->type) && !STRCMP((a)->name, (b)->name))
QCC_type_t * QCC_PR_FindType ( QCC_type_t * type )
{
int t ;
for ( t = 0 ; t < numtypeinfos ; t + + )
{
// check = &qcc_typeinfo[t];
if ( typecmp ( & qcc_typeinfo [ t ] , type ) )
continue ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
// c2 = check->next;
// n2 = type->next;
// for (i=0 ; n2&&c2 ; i++)
// {
// if (!typecmp((c2), (n2)))
// break;
// c2=c2->next;
// n2=n2->next;
// }
// if (n2==NULL&&c2==NULL)
{
return & qcc_typeinfo [ t ] ;
}
}
QCC_Error ( ERR_INTERNAL , " Error with type " ) ;
return type ;
}
/*
QCC_type_t * QCC_PR_NextSubType ( QCC_type_t * type , QCC_type_t * prev )
{
int p ;
if ( ! prev )
return type - > next ;
for ( p = prev - > num_parms ; p ; p - - )
prev = QCC_PR_NextSubType ( prev , NULL ) ;
if ( prev - > num_parms )
switch ( prev - > type )
{
case ev_function :
}
return prev - > next ;
}
*/
QCC_type_t * QCC_TypeForName ( char * name )
{
int i ;
for ( i = 0 ; i < numtypeinfos ; i + + )
{
if ( ! STRCMP ( qcc_typeinfo [ i ] . name , name ) )
{
return & qcc_typeinfo [ i ] ;
}
}
return NULL ;
}
/*
= = = = = = = = = = = =
PR_SkipToSemicolon
For error recovery , also pops out of nested braces
= = = = = = = = = = = =
*/
void QCC_PR_SkipToSemicolon ( void )
{
do
{
2005-03-20 02:57:11 +00:00
if ( ! pr_bracelevel & & QCC_PR_CheckToken ( " ; " ) )
2004-08-23 01:38:21 +00:00
return ;
QCC_PR_Lex ( ) ;
} while ( pr_token_type ! = tt_eof ) ;
}
/*
= = = = = = = = = = = =
PR_ParseType
Parses a variable type , including field and functions types
= = = = = = = = = = = =
*/
# ifdef MAX_EXTRA_PARMS
char pr_parm_names [ MAX_PARMS + MAX_EXTRA_PARMS ] [ MAX_NAME ] ;
# else
char pr_parm_names [ MAX_PARMS ] [ MAX_NAME ] ;
# endif
2004-09-02 12:58:49 +00:00
pbool recursivefunctiontype ;
2004-08-23 01:38:21 +00:00
QCC_type_t * QCC_PR_NewType ( char * name , int basictype ) ;
//expects a ( to have already been parsed.
QCC_type_t * QCC_PR_ParseFunctionType ( int newtype , QCC_type_t * returntype )
{
QCC_type_t * ftype , * ptype , * nptype ;
char * name ;
2004-09-02 12:58:49 +00:00
int definenames = ! recursivefunctiontype ;
2011-11-08 06:00:35 +00:00
int optional = 0 ;
int numparms = 0 ;
2004-09-02 12:58:49 +00:00
recursivefunctiontype + + ;
2004-08-23 01:38:21 +00:00
ftype = QCC_PR_NewType ( type_function - > name , ev_function ) ;
ftype - > aux_type = returntype ; // return type
ftype - > num_parms = 0 ;
ptype = NULL ;
2005-03-20 02:57:11 +00:00
if ( ! QCC_PR_CheckToken ( " ) " ) )
2004-08-23 01:38:21 +00:00
{
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckToken ( " ... " ) )
2004-08-23 01:38:21 +00:00
ftype - > num_parms = - 1 ; // variable args
else
do
{
if ( ftype - > num_parms > = MAX_PARMS + MAX_EXTRA_PARMS )
2004-09-21 03:22:55 +00:00
QCC_PR_ParseError ( ERR_TOOMANYTOTALPARAMETERS , " Too many parameters. Sorry. (limit is %i) \n " , MAX_PARMS + MAX_EXTRA_PARMS ) ;
2004-08-23 01:38:21 +00:00
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckToken ( " ... " ) )
2004-08-23 01:38:21 +00:00
{
2011-11-08 06:00:35 +00:00
if ( optional )
numparms = optional - 1 ;
ftype - > num_parms = ( numparms * - 1 ) - 1 ;
2004-08-23 01:38:21 +00:00
break ;
}
2011-11-08 06:00:35 +00:00
if ( QCC_PR_CheckKeyword ( keyword_optional , " optional " ) )
{
if ( ! optional )
optional = numparms + 1 ;
}
else if ( optional )
QCC_PR_ParseWarning ( WARN_MISSINGOPTIONAL , " optional not specified on all optional args \n " ) ;
2011-09-03 03:49:43 +00:00
nptype = QCC_PR_ParseType ( true , false ) ;
2004-08-23 01:38:21 +00:00
if ( nptype - > type = = ev_void )
break ;
if ( ! ptype )
{
ptype = nptype ;
ftype - > param = ptype ;
}
else
{
ptype - > next = nptype ;
ptype = ptype - > next ;
}
// type->name = "FUNC PARAMETER";
if ( STRCMP ( pr_token , " , " ) & & STRCMP ( pr_token , " ) " ) )
{
name = QCC_PR_ParseName ( ) ;
2004-09-02 12:58:49 +00:00
if ( definenames )
2011-11-08 06:00:35 +00:00
strcpy ( pr_parm_names [ numparms ] , name ) ;
2004-08-23 01:38:21 +00:00
}
2004-09-02 12:58:49 +00:00
else if ( definenames )
2011-11-08 06:00:35 +00:00
strcpy ( pr_parm_names [ numparms ] , " " ) ;
numparms + + ;
if ( optional )
ftype - > num_parms = optional - 1 ;
else
ftype - > num_parms = numparms ;
2005-03-20 02:57:11 +00:00
} while ( QCC_PR_CheckToken ( " , " ) ) ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
QCC_PR_Expect ( " ) " ) ;
}
2004-09-02 12:58:49 +00:00
recursivefunctiontype - - ;
2004-08-23 01:38:21 +00:00
if ( newtype )
return ftype ;
return QCC_PR_FindType ( ftype ) ;
}
2005-02-09 19:32:30 +00:00
QCC_type_t * QCC_PR_ParseFunctionTypeReacc ( int newtype , QCC_type_t * returntype )
{
QCC_type_t * ftype , * ptype , * nptype ;
char * name ;
char argname [ 64 ] ;
int definenames = ! recursivefunctiontype ;
recursivefunctiontype + + ;
ftype = QCC_PR_NewType ( type_function - > name , ev_function ) ;
ftype - > aux_type = returntype ; // return type
ftype - > num_parms = 0 ;
ptype = NULL ;
2005-03-20 02:57:11 +00:00
if ( ! QCC_PR_CheckToken ( " ) " ) )
2005-02-09 19:32:30 +00:00
{
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckToken ( " ... " ) )
2005-02-09 19:32:30 +00:00
ftype - > num_parms = - 1 ; // variable args
else
do
{
if ( ftype - > num_parms > = MAX_PARMS + MAX_EXTRA_PARMS )
QCC_PR_ParseError ( ERR_TOOMANYTOTALPARAMETERS , " Too many parameters. Sorry. (limit is %i) \n " , MAX_PARMS + MAX_EXTRA_PARMS ) ;
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckToken ( " ... " ) )
2005-02-09 19:32:30 +00:00
{
ftype - > num_parms = ( ftype - > num_parms * - 1 ) - 1 ;
break ;
}
2008-10-16 23:04:36 +00:00
if ( QCC_PR_CheckName ( " arg " ) )
2005-02-09 19:32:30 +00:00
{
sprintf ( argname , " arg%i " , ftype - > num_parms ) ;
name = argname ;
nptype = QCC_PR_NewType ( " Variant " , ev_variant ) ;
}
2008-10-16 23:04:36 +00:00
else if ( QCC_PR_CheckName ( " vect " ) ) //this can only be of vector sizes, so...
2005-02-09 19:32:30 +00:00
{
sprintf ( argname , " arg%i " , ftype - > num_parms ) ;
name = argname ;
nptype = QCC_PR_NewType ( " Vector " , ev_vector ) ;
}
else
{
name = QCC_PR_ParseName ( ) ;
QCC_PR_Expect ( " : " ) ;
2011-09-03 03:49:43 +00:00
nptype = QCC_PR_ParseType ( true , false ) ;
2005-02-09 19:32:30 +00:00
}
if ( nptype - > type = = ev_void )
break ;
if ( ! ptype )
{
ptype = nptype ;
ftype - > param = ptype ;
}
else
{
ptype - > next = nptype ;
ptype = ptype - > next ;
}
// type->name = "FUNC PARAMETER";
if ( definenames )
strcpy ( pr_parm_names [ ftype - > num_parms ] , name ) ;
ftype - > num_parms + + ;
2005-03-20 02:57:11 +00:00
} while ( QCC_PR_CheckToken ( " ; " ) ) ;
2010-12-08 14:42:05 +00:00
2005-02-09 19:32:30 +00:00
QCC_PR_Expect ( " ) " ) ;
}
recursivefunctiontype - - ;
if ( newtype )
return ftype ;
return QCC_PR_FindType ( ftype ) ;
}
2004-11-04 04:19:10 +00:00
QCC_type_t * QCC_PR_PointerType ( QCC_type_t * pointsto )
{
2011-09-03 03:49:43 +00:00
QCC_type_t * ptype , * e ;
ptype = QCC_PR_NewType ( " ptr " , ev_pointer ) ;
2004-11-04 04:19:10 +00:00
ptype - > aux_type = pointsto ;
2011-09-03 03:49:43 +00:00
e = QCC_PR_FindType ( ptype ) ;
if ( e = = ptype )
{
char name [ 128 ] ;
sprintf ( name , " ptr to %s " , pointsto - > name ) ;
e - > name = strdup ( name ) ;
}
return e ;
2004-11-04 04:19:10 +00:00
}
2005-02-09 19:32:30 +00:00
QCC_type_t * QCC_PR_FieldType ( QCC_type_t * pointsto )
{
QCC_type_t * ptype ;
char name [ 128 ] ;
sprintf ( name , " FIELD TYPE(%s) " , pointsto - > name ) ;
ptype = QCC_PR_NewType ( name , ev_field ) ;
ptype - > aux_type = pointsto ;
ptype - > size = ptype - > aux_type - > size ;
return QCC_PR_FindType ( ptype ) ;
}
2004-11-04 04:19:10 +00:00
2007-04-15 17:35:58 +00:00
pbool type_inlinefunction ;
2011-09-03 03:49:43 +00:00
/*newtype=true: creates a new type always
silentfail = true : function is permitted to return NULL if it was not given a type , otherwise never returns NULL
*/
QCC_type_t * QCC_PR_ParseType ( int newtype , pbool silentfail )
2004-08-23 01:38:21 +00:00
{
QCC_type_t * newparm ;
QCC_type_t * newt ;
QCC_type_t * type ;
char * name ;
int i ;
2007-04-15 17:35:58 +00:00
type_inlinefunction = false ; //doesn't really matter so long as its not from an inline function type
2004-08-23 01:38:21 +00:00
// int ofs;
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckToken ( " .. " ) ) //so we don't end up with the user specifying '. .vector blah' (hexen2 added the .. token for array ranges)
2004-11-29 19:38:06 +00:00
{
newt = QCC_PR_NewType ( " FIELD TYPE " , ev_field ) ;
2011-09-03 03:49:43 +00:00
newt - > aux_type = QCC_PR_ParseType ( false , false ) ;
2004-11-29 19:38:06 +00:00
newt - > size = newt - > aux_type - > size ;
newt = QCC_PR_FindType ( newt ) ;
type = QCC_PR_NewType ( " FIELD TYPE " , ev_field ) ;
type - > aux_type = newt ;
type - > size = type - > aux_type - > size ;
if ( newtype )
return type ;
return QCC_PR_FindType ( type ) ;
}
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckToken ( " . " ) )
2004-08-23 01:38:21 +00:00
{
newt = QCC_PR_NewType ( " FIELD TYPE " , ev_field ) ;
2011-09-03 03:49:43 +00:00
newt - > aux_type = QCC_PR_ParseType ( false , false ) ;
2004-08-23 01:38:21 +00:00
newt - > size = newt - > aux_type - > size ;
if ( newtype )
return newt ;
return QCC_PR_FindType ( newt ) ;
}
name = QCC_PR_CheakCompConstString ( pr_token ) ;
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckKeyword ( keyword_class , " class " ) )
2004-08-23 01:38:21 +00:00
{
// int parms;
QCC_type_t * fieldtype ;
char membername [ 2048 ] ;
char * classname = QCC_PR_ParseName ( ) ;
2006-09-28 02:46:42 +00:00
int forwarddeclaration ;
newt = 0 ;
/* Don't advance the line number yet */
forwarddeclaration = pr_token [ 0 ] = = ' ; ' ;
/* Look to see if this type is already defined */
for ( i = 0 ; i < numtypeinfos ; i + + )
{
if ( STRCMP ( qcc_typeinfo [ i ] . name , classname ) = = 0 )
{
newt = & qcc_typeinfo [ i ] ;
break ;
2010-12-08 14:42:05 +00:00
}
2006-09-28 02:46:42 +00:00
}
if ( newt & & forwarddeclaration )
QCC_PR_ParseError ( ERR_REDECLARATION , " Forward declaration of already defined class %s " , classname ) ;
if ( newt & & newt - > num_parms ! = 0 )
QCC_PR_ParseError ( ERR_REDECLARATION , " Redeclaration of class %s " , classname ) ;
if ( ! newt )
newt = QCC_PR_NewType ( classname , ev_entity ) ;
2004-08-23 01:38:21 +00:00
newt - > size = type_entity - > size ;
type = NULL ;
2006-09-28 02:46:42 +00:00
if ( forwarddeclaration )
{
QCC_PR_CheckToken ( " ; " ) ;
return NULL ;
}
2010-12-08 14:42:05 +00:00
2006-09-28 02:46:42 +00:00
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckToken ( " : " ) )
2004-08-23 01:38:21 +00:00
{
char * parentname = QCC_PR_ParseName ( ) ;
newt - > parentclass = QCC_TypeForName ( parentname ) ;
if ( ! newt - > parentclass )
QCC_PR_ParseError ( ERR_NOTANAME , " Parent class %s was not defined " , parentname ) ;
}
else
newt - > parentclass = type_entity ;
QCC_PR_Expect ( " { " ) ;
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckToken ( " , " ) )
2004-08-23 01:38:21 +00:00
QCC_PR_ParseError ( ERR_NOTANAME , " member missing name " ) ;
2005-03-20 02:57:11 +00:00
while ( ! QCC_PR_CheckToken ( " } " ) )
2004-08-23 01:38:21 +00:00
{
2005-03-20 02:57:11 +00:00
// if (QCC_PR_CheckToken(","))
2004-08-23 01:38:21 +00:00
// type->next = QCC_PR_NewType(type->name, type->type);
// else
2011-09-03 03:49:43 +00:00
newparm = QCC_PR_ParseType ( true , false ) ;
2004-08-23 01:38:21 +00:00
if ( newparm - > type = = ev_struct | | newparm - > type = = ev_union ) //we wouldn't be able to handle it.
QCC_PR_ParseError ( ERR_INTERNAL , " Struct or union in class %s " , classname ) ;
2005-03-20 02:57:11 +00:00
if ( ! QCC_PR_CheckToken ( " ; " ) )
2004-08-23 01:38:21 +00:00
{
newparm - > name = QCC_CopyString ( pr_token ) + strings ;
QCC_PR_Lex ( ) ;
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckToken ( " [ " ) )
2004-08-23 01:38:21 +00:00
{
type - > next - > size * = atoi ( pr_token ) ;
QCC_PR_Lex ( ) ;
QCC_PR_Expect ( " ] " ) ;
}
2005-03-20 02:57:11 +00:00
QCC_PR_CheckToken ( " ; " ) ;
2004-08-23 01:38:21 +00:00
}
else
newparm - > name = QCC_CopyString ( " " ) + strings ;
sprintf ( membername , " %s:: " MEMBERFIELDNAME , classname , newparm - > name ) ;
fieldtype = QCC_PR_NewType ( newparm - > name , ev_field ) ;
fieldtype - > aux_type = newparm ;
2005-09-08 22:52:46 +00:00
fieldtype - > size = newparm - > size ;
2008-10-05 02:55:01 +00:00
QCC_PR_GetDef ( fieldtype , membername , pr_scope , 2 , 1 , false ) ;
2004-08-23 01:38:21 +00:00
2005-09-08 22:52:46 +00:00
newparm - > ofs = 0 ; //newt->size;
2004-08-23 01:38:21 +00:00
newt - > num_parms + + ;
if ( type )
type - > next = newparm ;
else
newt - > param = newparm ;
type = newparm ;
}
QCC_PR_Expect ( " ; " ) ;
return NULL ;
}
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckKeyword ( keyword_struct , " struct " ) )
2004-08-23 01:38:21 +00:00
{
newt = QCC_PR_NewType ( " struct " , ev_struct ) ;
newt - > size = 0 ;
QCC_PR_Expect ( " { " ) ;
type = NULL ;
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckToken ( " , " ) )
2004-08-23 01:38:21 +00:00
QCC_PR_ParseError ( ERR_NOTANAME , " element missing name " ) ;
2004-10-13 07:24:59 +00:00
newparm = NULL ;
2005-03-20 02:57:11 +00:00
while ( ! QCC_PR_CheckToken ( " } " ) )
2004-08-23 01:38:21 +00:00
{
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckToken ( " , " ) )
2004-08-23 01:38:21 +00:00
{
if ( ! newparm )
QCC_PR_ParseError ( ERR_NOTANAME , " element missing type " ) ;
newparm = QCC_PR_NewType ( newparm - > name , newparm - > type ) ;
}
else
2011-09-03 03:49:43 +00:00
newparm = QCC_PR_ParseType ( true , false ) ;
2004-08-23 01:38:21 +00:00
2005-03-20 02:57:11 +00:00
if ( ! QCC_PR_CheckToken ( " ; " ) )
2004-08-23 01:38:21 +00:00
{
newparm - > name = QCC_CopyString ( pr_token ) + strings ;
QCC_PR_Lex ( ) ;
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckToken ( " [ " ) )
2004-08-23 01:38:21 +00:00
{
2011-10-03 02:45:44 +00:00
newparm - > arraysize = QCC_PR_IntConstExpr ( ) ;
2004-08-23 01:38:21 +00:00
QCC_PR_Expect ( " ] " ) ;
}
2005-03-20 02:57:11 +00:00
QCC_PR_CheckToken ( " ; " ) ;
2004-08-23 01:38:21 +00:00
}
else
newparm - > name = QCC_CopyString ( " " ) + strings ;
newparm - > ofs = newt - > size ;
2011-10-03 02:45:44 +00:00
newt - > size + = newparm - > size * newparm - > arraysize ;
2004-08-23 01:38:21 +00:00
newt - > num_parms + + ;
if ( type )
type - > next = newparm ;
else
newt - > param = newparm ;
type = newparm ;
}
return newt ;
}
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckKeyword ( keyword_union , " union " ) )
2004-08-23 01:38:21 +00:00
{
newt = QCC_PR_NewType ( " union " , ev_union ) ;
newt - > size = 0 ;
QCC_PR_Expect ( " { " ) ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
type = NULL ;
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckToken ( " , " ) )
2004-08-23 01:38:21 +00:00
QCC_PR_ParseError ( ERR_NOTANAME , " element missing name " ) ;
2004-10-13 07:24:59 +00:00
newparm = NULL ;
2005-03-20 02:57:11 +00:00
while ( ! QCC_PR_CheckToken ( " } " ) )
2004-08-23 01:38:21 +00:00
{
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckToken ( " , " ) )
2004-08-23 01:38:21 +00:00
{
if ( ! newparm )
QCC_PR_ParseError ( ERR_NOTANAME , " element missing type " ) ;
newparm = QCC_PR_NewType ( newparm - > name , newparm - > type ) ;
}
else
2011-09-03 03:49:43 +00:00
newparm = QCC_PR_ParseType ( true , false ) ;
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckToken ( " ; " ) )
2004-08-23 01:38:21 +00:00
newparm - > name = QCC_CopyString ( " " ) + strings ;
else
{
newparm - > name = QCC_CopyString ( pr_token ) + strings ;
QCC_PR_Lex ( ) ;
2011-10-03 02:45:44 +00:00
if ( QCC_PR_CheckToken ( " [ " ) )
{
newparm - > arraysize = QCC_PR_IntConstExpr ( ) ;
QCC_PR_Expect ( " ] " ) ;
}
2004-08-23 01:38:21 +00:00
QCC_PR_Expect ( " ; " ) ;
}
newparm - > ofs = 0 ;
2011-10-03 02:45:44 +00:00
if ( newparm - > size > newt - > size * newparm - > arraysize )
newt - > size = newparm - > size * newparm - > arraysize ;
2004-08-23 01:38:21 +00:00
newt - > num_parms + + ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
if ( type )
type - > next = newparm ;
else
newt - > param = newparm ;
type = newparm ;
}
return newt ;
}
type = NULL ;
for ( i = 0 ; i < numtypeinfos ; i + + )
{
if ( ! STRCMP ( qcc_typeinfo [ i ] . name , name ) )
{
type = & qcc_typeinfo [ i ] ;
break ;
}
}
if ( i = = numtypeinfos )
{
2005-02-28 07:16:19 +00:00
if ( ! * name )
return NULL ;
2005-02-09 19:32:30 +00:00
if ( ! stricmp ( " Void " , name ) )
type = type_void ;
else if ( ! stricmp ( " Real " , name ) )
type = type_float ;
else if ( ! stricmp ( " Vector " , name ) )
type = type_vector ;
else if ( ! stricmp ( " Object " , name ) )
type = type_entity ;
else if ( ! stricmp ( " String " , name ) )
type = type_string ;
else if ( ! stricmp ( " PFunc " , name ) )
type = type_function ;
else
{
2011-09-03 03:49:43 +00:00
if ( silentfail )
return NULL ;
2005-02-09 19:32:30 +00:00
QCC_PR_ParseError ( ERR_NOTATYPE , " \" %s \" is not a type " , name ) ;
type = type_float ; // shut up compiler warning
}
2004-08-23 01:38:21 +00:00
}
QCC_PR_Lex ( ) ;
2010-12-08 14:42:05 +00:00
2011-09-03 03:49:43 +00:00
while ( QCC_PR_CheckToken ( " * " ) )
type = QCC_PointerTypeTo ( type ) ;
2005-03-20 02:57:11 +00:00
if ( QCC_PR_CheckToken ( " ( " ) ) //this is followed by parameters. Must be a function.
2007-04-15 17:35:58 +00:00
{
type_inlinefunction = true ;
2011-09-03 03:49:43 +00:00
type = QCC_PR_ParseFunctionType ( newtype , type ) ;
2007-04-15 17:35:58 +00:00
}
2004-08-23 01:38:21 +00:00
else
{
if ( newtype )
{
2010-12-08 14:42:05 +00:00
type = QCC_PR_DuplicateType ( type ) ;
2004-08-23 01:38:21 +00:00
}
}
2011-09-03 03:49:43 +00:00
return type ;
2004-08-23 01:38:21 +00:00
}
2004-09-07 18:27:08 +00:00
# endif
2008-07-27 02:48:59 +00:00