added very, very primitive, mostly unusable structs. the most these can do so far is expose themselves publically
authorDavid Anderson <dvander@alliedmods.net>
Thu Nov 09 22:53:27 2006 +0000 (2006-11-09)
changeset 1674db3481b6db7
parent 166 3f7a9bbc8da6
child 168 13839096b00d
added very, very primitive, mostly unusable structs. the most these can do so far is expose themselves publically
sourcepawn/compiler/msvc8/spcomp.vcproj
sourcepawn/compiler/sc.h
sourcepawn/compiler/sc1.c
sourcepawn/compiler/sc2.c
sourcepawn/compiler/sc5.scp
sourcepawn/compiler/sctracker.c
sourcepawn/compiler/sctracker.h
     1.1 --- a/sourcepawn/compiler/msvc8/spcomp.vcproj	Wed Nov 08 09:37:16 2006 +0000
     1.2 +++ b/sourcepawn/compiler/msvc8/spcomp.vcproj	Thu Nov 09 22:53:27 2006 +0000
     1.3 @@ -144,6 +144,7 @@
     1.4  				SubSystem="1"
     1.5  				OptimizeReferences="2"
     1.6  				EnableCOMDATFolding="2"
     1.7 +				LinkTimeCodeGeneration="0"
     1.8  				TargetMachine="1"
     1.9  			/>
    1.10  			<Tool
     2.1 --- a/sourcepawn/compiler/sc.h	Wed Nov 08 09:37:16 2006 +0000
     2.2 +++ b/sourcepawn/compiler/sc.h	Thu Nov 09 22:53:27 2006 +0000
     2.3 @@ -285,7 +285,7 @@
     2.4   */
     2.5  #define tFIRST   256    /* value of first multi-character operator */
     2.6  #define tMIDDLE  280    /* value of last multi-character operator */
     2.7 -#define tLAST    330    /* value of last multi-character match-able token */
     2.8 +#define tLAST    331    /* value of last multi-character match-able token */
     2.9  /* multi-character operators */
    2.10  #define taMULT   256    /* *= */
    2.11  #define taDIV    257    /* /= */
    2.12 @@ -343,38 +343,39 @@
    2.13  #define tSTATE   308
    2.14  #define tSTATIC  309
    2.15  #define tSTOCK   310
    2.16 -#define tSWITCH  311
    2.17 -#define tTAGOF   312
    2.18 -#define tTHEN    313
    2.19 -#define tWHILE   314
    2.20 +#define tSTRUCT  311
    2.21 +#define tSWITCH  312
    2.22 +#define tTAGOF   313
    2.23 +#define tTHEN    314
    2.24 +#define tWHILE   315
    2.25  /* compiler directives */
    2.26 -#define tpASSERT 315    /* #assert */
    2.27 -#define tpDEFINE 316
    2.28 -#define tpELSE   317    /* #else */
    2.29 -#define tpELSEIF 318    /* #elseif */
    2.30 -#define tpEMIT   319
    2.31 -#define tpENDIF  320
    2.32 -#define tpENDINPUT 321
    2.33 -#define tpENDSCRPT 322
    2.34 -#define tpERROR  323
    2.35 -#define tpFILE   324
    2.36 -#define tpIF     325    /* #if */
    2.37 -#define tINCLUDE 326
    2.38 -#define tpLINE   327
    2.39 -#define tpPRAGMA 328
    2.40 -#define tpTRYINCLUDE 329
    2.41 -#define tpUNDEF  330
    2.42 +#define tpASSERT 316    /* #assert */
    2.43 +#define tpDEFINE 317
    2.44 +#define tpELSE   318    /* #else */
    2.45 +#define tpELSEIF 319    /* #elseif */
    2.46 +#define tpEMIT   320
    2.47 +#define tpENDIF  321
    2.48 +#define tpENDINPUT 322
    2.49 +#define tpENDSCRPT 323
    2.50 +#define tpERROR  324
    2.51 +#define tpFILE   325
    2.52 +#define tpIF     326    /* #if */
    2.53 +#define tINCLUDE 327
    2.54 +#define tpLINE   328
    2.55 +#define tpPRAGMA 329
    2.56 +#define tpTRYINCLUDE 330
    2.57 +#define tpUNDEF  331
    2.58  /* semicolon is a special case, because it can be optional */
    2.59 -#define tTERM    331    /* semicolon or newline */
    2.60 -#define tENDEXPR 332    /* forced end of expression */
    2.61 +#define tTERM    332    /* semicolon or newline */
    2.62 +#define tENDEXPR 333    /* forced end of expression */
    2.63  /* other recognized tokens */
    2.64 -#define tNUMBER  333    /* integer number */
    2.65 -#define tRATIONAL 334   /* rational number */
    2.66 -#define tSYMBOL  335
    2.67 -#define tLABEL   336
    2.68 -#define tSTRING  337
    2.69 -#define tEXPR    338 /* for assigment to "lastst" only (see SC1.C) */
    2.70 -#define tENDLESS 339 /* endless loop, for assigment to "lastst" only */
    2.71 +#define tNUMBER  334    /* integer number */
    2.72 +#define tRATIONAL 335   /* rational number */
    2.73 +#define tSYMBOL  336
    2.74 +#define tLABEL   337
    2.75 +#define tSTRING  338
    2.76 +#define tEXPR    339 /* for assigment to "lastst" only (see SC1.C) */
    2.77 +#define tENDLESS 340 /* endless loop, for assigment to "lastst" only */
    2.78  
    2.79  /* (reversed) evaluation of staging buffer */
    2.80  #define sSTARTREORDER 0x01
     3.1 --- a/sourcepawn/compiler/sc1.c	Wed Nov 08 09:37:16 2006 +0000
     3.2 +++ b/sourcepawn/compiler/sc1.c	Thu Nov 09 22:53:27 2006 +0000
     3.3 @@ -88,8 +88,10 @@
     3.4  static void declfuncvar(int fpublic,int fstatic,int fstock,int fconst);
     3.5  static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,
     3.6                      int stock,int fconst);
     3.7 +static void declstructvar(char *firstname,int fpublic, pstruct_t *pstruct);
     3.8  static int declloc(int fstatic);
     3.9  static void decl_const(int table);
    3.10 +static void declstruct();
    3.11  static void decl_enum(int table);
    3.12  static cell needsub(int *tag,constvalue **enumroot);
    3.13  static void initials(int ident,int tag,cell *size,int dim[],int numdim,
    3.14 @@ -326,6 +328,7 @@
    3.15        inst_datetime_defines();
    3.16      #endif
    3.17      resetglobals();
    3.18 +    pstructs_free();
    3.19  	funcenums_free();
    3.20      sc_ctrlchar=sc_ctrlchar_org;
    3.21      sc_packstr=lcl_packstr;
    3.22 @@ -388,6 +391,7 @@
    3.23    reduce_referrers(&glbtab);
    3.24    delete_symbols(&glbtab,0,TRUE,FALSE);
    3.25    funcenums_free();
    3.26 +  pstructs_free();
    3.27    #if !defined NO_DEFINE
    3.28      delete_substtable();
    3.29      inst_datetime_defines();
    3.30 @@ -1414,6 +1418,9 @@
    3.31      case tFUNCENUM:
    3.32        dofuncenum();
    3.33        break;
    3.34 +    case tSTRUCT:
    3.35 +      declstruct();
    3.36 +      break;
    3.37      case tPUBLIC:
    3.38        /* This can be a public function or a public variable; see the comment
    3.39         * above (for static functions/variables) for details.
    3.40 @@ -1627,12 +1634,19 @@
    3.41  static void declfuncvar(int fpublic,int fstatic,int fstock,int fconst)
    3.42  {
    3.43    char name[sNAMEMAX+11];
    3.44 -  int tok,tag;
    3.45 +  int tok,tag=0;
    3.46    char *str;
    3.47    cell val;
    3.48    int invalidfunc;
    3.49 -
    3.50 -  tag=pc_addtag(NULL);
    3.51 +  pstruct_t *pstruct = NULL;
    3.52 +
    3.53 +  tok=lex(&val,&str);
    3.54 +  if (tok == tLABEL) {
    3.55 +    pstruct=pstructs_find(str);
    3.56 +    tag=pc_addtag(str);
    3.57 +  } else {
    3.58 +    lexpush();
    3.59 +  }
    3.60    tok=lex(&val,&str);
    3.61    /* if we arrived here, this may not be a declaration of a native function
    3.62     * or variable
    3.63 @@ -1664,11 +1678,209 @@
    3.64      invalidfunc= fconst || (fpublic && fstock);
    3.65      if (invalidfunc || !newfunc(name,tag,fpublic,fstatic,fstock)) {
    3.66        /* if not a function, try a global variable */
    3.67 -      declglb(name,tag,fpublic,fstatic,fstock,fconst);
    3.68 +      if (pstruct) {
    3.69 +        declstructvar(name,fpublic,pstruct);
    3.70 +      } else {
    3.71 +        declglb(name,tag,fpublic,fstatic,fstock,fconst);
    3.72 +      }
    3.73      } /* if */
    3.74    } /* if */
    3.75  }
    3.76  
    3.77 +/* declstruct	- declare global struct symbols
    3.78 + * 
    3.79 + * global references: glb_declared		(altered)
    3.80 + */
    3.81 +static void declstructvar(char *firstname,int fpublic, pstruct_t *pstruct)
    3.82 +{
    3.83 +	char name[sNAMEMAX+1];
    3.84 +	int tok,i;
    3.85 +	cell val;
    3.86 +	char *str;
    3.87 +	int cur_litidx = 0;
    3.88 +	cell *values, *found;
    3.89 +	int usage;
    3.90 +	symbol *mysym;
    3.91 +
    3.92 +	strcpy(name, firstname);
    3.93 +
    3.94 +	values = (cell *)malloc(pstruct->argcount * sizeof(cell));
    3.95 +	found = (cell *)malloc(pstruct->argcount * sizeof(cell));
    3.96 +	
    3.97 +	memset(found, 0, sizeof(cell) * pstruct->argcount);
    3.98 +
    3.99 +
   3.100 +	/**
   3.101 +	 * Lastly, very lastly, we will insert a copy of this variable.
   3.102 +	 * This is soley to expose the pubvar.
   3.103 +	 */
   3.104 +	usage = uDEFINE|uREAD|uCONST;
   3.105 +	if (fpublic)
   3.106 +	{
   3.107 +		usage |= uPUBLIC;
   3.108 +	}
   3.109 +	mysym=addsym(name, 0, iVARIABLE, sGLOBAL, pc_addtag(pstruct->name), usage);
   3.110 +
   3.111 +	/* Maybe error with "public struct requires initialization?" */
   3.112 +	if (!needtoken('='))
   3.113 +	{
   3.114 +		matchtoken(';');
   3.115 +		return;
   3.116 +	}
   3.117 +	needtoken('{');
   3.118 +	do
   3.119 +	{
   3.120 +		structarg_t *arg;
   3.121 +		/* Detect early exit */
   3.122 +		if (matchtoken('}'))
   3.123 +		{
   3.124 +			lexpush();
   3.125 +			break;
   3.126 +		}
   3.127 +		tok=lex(&val,&str);
   3.128 +		if (tok != tSYMBOL)
   3.129 +		{
   3.130 +			error(1, "-identifier-", str);
   3.131 +			continue;
   3.132 +		}
   3.133 +		arg=pstructs_getarg(pstruct,str);
   3.134 +		if (arg == NULL)
   3.135 +		{
   3.136 +			/* :TODO: change to "Could not find member %s in struct %s" */
   3.137 +			error(31);
   3.138 +		}
   3.139 +		needtoken('=');
   3.140 +		cur_litidx = litidx;
   3.141 +		tok=lex(&val,&str);
   3.142 +		if (!arg)
   3.143 +		{
   3.144 +			continue;
   3.145 +		}
   3.146 +		if (tok == tSTRING)
   3.147 +		{
   3.148 +			assert(litidx != 0);
   3.149 +			if (arg->dimcount != 1)
   3.150 +			{
   3.151 +				error(48);
   3.152 +			} else if (arg->tag != pc_tag_string) {
   3.153 +				error(213);
   3.154 +			}
   3.155 +			values[arg->index] = glb_declared * sizeof(cell);
   3.156 +			glb_declared += (litidx-cur_litidx);
   3.157 +			found[arg->index] = 1;
   3.158 +		} else if (tok == tNUMBER || tok == tRATIONAL) {
   3.159 +			/* eat optional 'f' */
   3.160 +			matchtoken('f');
   3.161 +			if (arg->ident != iVARIABLE && arg->ident != iREFERENCE)
   3.162 +			{
   3.163 +				error(23);
   3.164 +			} else {
   3.165 +				if (arg->tag == pc_addtag("Float") && tok == tNUMBER ||
   3.166 +					arg->tag == 0 && tok == tRATIONAL)
   3.167 +				{
   3.168 +					error(213);
   3.169 +				}
   3.170 +				if (arg->ident == iVARIABLE)
   3.171 +				{
   3.172 +					values[arg->index] = val;
   3.173 +				} else if (arg->ident == iREFERENCE) {
   3.174 +					values[arg->index] = glb_declared * sizeof(cell);
   3.175 +					glb_declared += 1;
   3.176 +					litadd(val);
   3.177 +					cur_litidx = litidx;
   3.178 +				}
   3.179 +				found[arg->index] = 1;
   3.180 +			}
   3.181 +		} else if (tok == tSYMBOL) {
   3.182 +			symbol *sym = NULL;
   3.183 +			for (sym=glbtab.next; sym!=NULL; sym=sym->next)
   3.184 +			{
   3.185 +				if (sym->vclass != sGLOBAL)
   3.186 +				{
   3.187 +					continue;
   3.188 +				}
   3.189 +				if (strcmp(sym->name, str) == 0)
   3.190 +				{
   3.191 +					if (arg->ident == iREFERENCE && sym->ident != iVARIABLE)
   3.192 +					{
   3.193 +						/* :TODO: Change to "symbol \"%s\" does not have a matching type */
   3.194 +						error(20, str);
   3.195 +					} else if (arg->ident == iARRAY) {
   3.196 +						if (sym->ident != iARRAY)
   3.197 +						{
   3.198 +							/* :TODO: Change to "symbol \"%s\" does not have a matching type */
   3.199 +							error(20, str);
   3.200 +						} else {
   3.201 +							/* :TODO: We should check dimension sizes here... */
   3.202 +						}
   3.203 +					} else if (arg->ident == iREFARRAY) {
   3.204 +						if (sym->ident != iARRAY)
   3.205 +						{
   3.206 +							/* :TODO: Change to "symbol \"%s\" does not have a matching type */
   3.207 +							error(20, str);
   3.208 +						}
   3.209 +						/* :TODO: Check dimension sizes! */
   3.210 +					} else {
   3.211 +						/* :TODO: Change to "symbol \"%s\" does not have a matching type */
   3.212 +						error(20, str);
   3.213 +					}
   3.214 +					if (sym->tag != arg->tag)
   3.215 +					{
   3.216 +						error(213);
   3.217 +					}
   3.218 +					sym->usage |= uREAD;
   3.219 +					values[arg->index] = sym->addr;
   3.220 +					found[arg->index] = 1;
   3.221 +					refer_symbol(sym, mysym);
   3.222 +					break;
   3.223 +				}
   3.224 +			}
   3.225 +			if (!sym)
   3.226 +			{
   3.227 +				error(17, str);
   3.228 +			}
   3.229 +		} else {
   3.230 +			error(1, "-identifier-", str);
   3.231 +		}
   3.232 +	} while (matchtoken(','));
   3.233 +	needtoken('}');
   3.234 +	matchtoken(';');	/* eat up optional semicolon */
   3.235 +
   3.236 +	for (i=0; i<pstruct->argcount; i++)
   3.237 +	{
   3.238 +		if (!found[i])
   3.239 +		{
   3.240 +			structarg_t *arg = pstruct->args[i];
   3.241 +			if (arg->ident == iREFARRAY)
   3.242 +			{
   3.243 +				values[arg->index] = glb_declared * sizeof(cell);
   3.244 +				glb_declared += 1;
   3.245 +				litadd(0);
   3.246 +				cur_litidx = litidx;
   3.247 +			} else if (arg->ident == iVARIABLE) {
   3.248 +				values[arg->index] = 0;
   3.249 +			} else {
   3.250 +				/* :TODO: broken for iARRAY! (unused tho) */
   3.251 +			}
   3.252 +		}
   3.253 +	}
   3.254 +
   3.255 +	mysym->addr = glb_declared * sizeof(cell);
   3.256 +	glb_declared += pstruct->argcount;
   3.257 +
   3.258 +	for (i=0; i<pstruct->argcount; i++)
   3.259 +	{
   3.260 +		litadd(values[i]);
   3.261 +	}
   3.262 +
   3.263 +	begdseg();
   3.264 +	dumplits();
   3.265 +	litidx=0;
   3.266 +
   3.267 +	free(found);
   3.268 +	free(values);
   3.269 +}
   3.270 +
   3.271  /*  declglb     - declare global symbols
   3.272   *
   3.273   *  Declare a static (global) variable. Global variables are stored in
   3.274 @@ -2612,8 +2824,110 @@
   3.275    needtoken(tTERM);
   3.276  }
   3.277  
   3.278 -/* dofuncenum - declare function enumerations
   3.279 - * 
   3.280 +/*
   3.281 + * declstruct - declare a struct type
   3.282 + */
   3.283 +static void declstruct(void)
   3.284 +{
   3.285 +	cell val;
   3.286 +	char *str;
   3.287 +	int tok;
   3.288 +	pstruct_t *pstruct;
   3.289 +	int size;
   3.290 +
   3.291 +	/* get the explicit tag (required!) */
   3.292 +	tok = lex(&val,&str);
   3.293 +	if (tok != tSYMBOL)
   3.294 +	{
   3.295 +		error(93);
   3.296 +	}
   3.297 +
   3.298 +	if (pstructs_find(str) != NULL)
   3.299 +	{
   3.300 +		/* :TODO: change to "struct requires unique struct name" */
   3.301 +		error(58);
   3.302 +	}
   3.303 +
   3.304 +	pstruct = pstructs_add(str);
   3.305 +
   3.306 +	needtoken('{');
   3.307 +	do
   3.308 +	{
   3.309 +		structarg_t arg;
   3.310 +		if (matchtoken('}'))
   3.311 +		{
   3.312 +			/* Quick exit */
   3.313 +			lexpush();
   3.314 +			break;
   3.315 +		}
   3.316 +		memset(&arg, 0, sizeof(structarg_t));
   3.317 +		tok = lex(&val,&str);
   3.318 +		if (tok == tCONST)
   3.319 +		{
   3.320 +			arg.fconst = 1;
   3.321 +			tok = lex(&val,&str);
   3.322 +		}
   3.323 +		arg.ident = 0;
   3.324 +		if (tok == '&')
   3.325 +		{
   3.326 +			arg.ident = iREFERENCE;
   3.327 +			tok = lex(&val,&str);
   3.328 +		}
   3.329 +		if (tok == tLABEL)
   3.330 +		{
   3.331 +			arg.tag = pc_addtag(str);
   3.332 +			tok = lex(&val,&str);
   3.333 +		}
   3.334 +		if (tok != tSYMBOL)
   3.335 +		{
   3.336 +			error(1, "-identifier-", str);
   3.337 +			continue;
   3.338 +		}
   3.339 +		strcpy(arg.name, str);
   3.340 +		if (matchtoken('['))
   3.341 +		{
   3.342 +			if (arg.ident == iREFERENCE)
   3.343 +			{
   3.344 +				error(67, arg.name);
   3.345 +			}
   3.346 +			arg.ident = iARRAY;
   3.347 +			do 
   3.348 +			{
   3.349 +				constvalue *enumroot;
   3.350 +				int ignore_tag;
   3.351 +				if (arg.dimcount == sDIMEN_MAX)
   3.352 +				{
   3.353 +					error(53);
   3.354 +					break;
   3.355 +				}
   3.356 +				size = needsub(&ignore_tag, &enumroot);
   3.357 +				arg.dims[arg.dimcount++] = size;
   3.358 +			} while (matchtoken('['));
   3.359 +			/* Handle strings */
   3.360 +			if (arg.tag == pc_tag_string && arg.dims[arg.dimcount-1])
   3.361 +			{
   3.362 +				arg.dims[arg.dimcount-1] = (size + sizeof(cell)-1) / sizeof(cell);
   3.363 +			}
   3.364 +			if (arg.dimcount == 1 && !arg.dims[arg.dimcount-1])
   3.365 +			{
   3.366 +				arg.ident = iREFARRAY;
   3.367 +			}
   3.368 +		} else if (!arg.ident) {
   3.369 +			arg.ident = iVARIABLE;
   3.370 +		}
   3.371 +		if (pstructs_addarg(pstruct, &arg) == NULL)
   3.372 +		{
   3.373 +			/* :TODO: change to "struct member name appears more than once" */
   3.374 +			error(58);
   3.375 +		}
   3.376 +	} while (matchtoken(','));
   3.377 +	needtoken('}');
   3.378 +	matchtoken(';');	/* eat up optional semicolon */
   3.379 +}
   3.380 +
   3.381 +
   3.382 +/**
   3.383 + * dofuncenum - declare function enumerations
   3.384   */
   3.385  static void dofuncenum(void)
   3.386  {
   3.387 @@ -2750,7 +3064,8 @@
   3.388  						arg->dimcount += 1;
   3.389  					} while (matchtoken('['));
   3.390  					/* Handle strings */
   3.391 -					if (arg->tagcount == 1 && arg->tags[0] == pc_tag_string)
   3.392 +					if ((arg->tagcount == 1 && arg->tags[0] == pc_tag_string)
   3.393 +						&& arg->dims[arg->dimcount-1])
   3.394  					{
   3.395  						arg->dims[arg->dimcount-1] = (size + sizeof(cell)-1) / sizeof(cell);
   3.396  					}
     4.1 --- a/sourcepawn/compiler/sc2.c	Wed Nov 08 09:37:16 2006 +0000
     4.2 +++ b/sourcepawn/compiler/sc2.c	Thu Nov 09 22:53:27 2006 +0000
     4.3 @@ -1880,7 +1880,7 @@
     4.4           "assert", "*begin", "break", "case", "chars", "const", "continue", "default",
     4.5           "defined", "do", "else", "*end", "enum", "exit", "for", "forward", "funcenum", "goto",
     4.6           "if", "native", "new", "decl", "operator", "public", "return", "sizeof",
     4.7 -         "sleep", "state", "static", "stock", "switch", "tagof", "*then", "while",
     4.8 +         "sleep", "state", "static", "stock", "struct", "switch", "tagof", "*then", "while",
     4.9           "#assert", "#define", "#else", "#elseif", "#emit", "#endif", "#endinput",
    4.10           "#endscript", "#error", "#file", "#if", "#include", "#line", "#pragma",
    4.11           "#tryinclude", "#undef",
     5.1 --- a/sourcepawn/compiler/sc5.scp	Wed Nov 08 09:37:16 2006 +0000
     5.2 +++ b/sourcepawn/compiler/sc5.scp	Thu Nov 09 22:53:27 2006 +0000
     5.3 @@ -86,7 +86,7 @@
     5.4  /*045*/  "too many function arguments\n",
     5.5  /*046*/  "unknown array size (variable \"%s\")\n",
     5.6  /*047*/  "array sizes do not match, or destination array is too small\n",
     5.7 -/*048*/  "array dimensions do not match\n",
     5.8 +/*048*/  "array (s do not match\n",
     5.9  /*049*/  "invalid line continuation\n",
    5.10  /*050*/  "invalid range\n",
    5.11  /*051*/  "invalid subscript, use \"[ ]\" operators on major dimensions\n",
     6.1 --- a/sourcepawn/compiler/sctracker.c	Wed Nov 08 09:37:16 2006 +0000
     6.2 +++ b/sourcepawn/compiler/sctracker.c	Thu Nov 09 22:53:27 2006 +0000
     6.3 @@ -8,6 +8,112 @@
     6.4  memuse_list_t *stackusage = NULL;
     6.5  funcenum_t *firstenum = NULL;
     6.6  funcenum_t *lastenum = NULL;
     6.7 +pstruct_t *firststruct = NULL;
     6.8 +pstruct_t *laststruct = NULL;
     6.9 +
    6.10 +structarg_t *pstructs_getarg(pstruct_t *pstruct, const char *member)
    6.11 +{
    6.12 +	int i;
    6.13 +
    6.14 +	for (i=0; i<pstruct->argcount; i++)
    6.15 +	{
    6.16 +		if (strcmp(pstruct->args[i]->name, member) == 0)
    6.17 +		{
    6.18 +			return pstruct->args[i];
    6.19 +		}
    6.20 +	}
    6.21 +
    6.22 +	return NULL;
    6.23 +}
    6.24 +
    6.25 +pstruct_t *pstructs_add(const char *name)
    6.26 +{
    6.27 +	pstruct_t *p = (pstruct_t *)malloc(sizeof(pstruct_t));
    6.28 +	
    6.29 +	memset(p, 0, sizeof(pstruct_t));
    6.30 +	strcpy(p->name, name);
    6.31 +	
    6.32 +	if (!firststruct)
    6.33 +	{
    6.34 +		firststruct = p;
    6.35 +		laststruct = p;
    6.36 +	} else {
    6.37 +		laststruct->next = p;
    6.38 +		laststruct = p;
    6.39 +	}
    6.40 +
    6.41 +	return p;
    6.42 +}
    6.43 +
    6.44 +void pstructs_free()
    6.45 +{
    6.46 +	pstruct_t *p, *next;
    6.47 +
    6.48 +	p = firststruct;
    6.49 +	while (p)
    6.50 +	{
    6.51 +		while (p->argcount--)
    6.52 +		{
    6.53 +			free(p->args[p->argcount]);
    6.54 +		}
    6.55 +		free(p->args);
    6.56 +		next = p->next;
    6.57 +		free(p);
    6.58 +		p = next;
    6.59 +	}
    6.60 +	firststruct = NULL;
    6.61 +	laststruct = NULL;
    6.62 +}
    6.63 +
    6.64 +pstruct_t *pstructs_find(const char *name)
    6.65 +{
    6.66 +	pstruct_t *p = firststruct;
    6.67 +
    6.68 +	while (p)
    6.69 +	{
    6.70 +		if (strcmp(p->name, name) == 0)
    6.71 +		{
    6.72 +			return p;
    6.73 +		}
    6.74 +		p = p->next;
    6.75 +	}
    6.76 +
    6.77 +	return NULL;
    6.78 +}
    6.79 +
    6.80 +structarg_t *pstructs_addarg(pstruct_t *pstruct, const structarg_t *arg)
    6.81 +{
    6.82 +	structarg_t *newarg;
    6.83 +	int i;
    6.84 +
    6.85 +	for (i=0; i<pstruct->argcount; i++)
    6.86 +	{
    6.87 +		if (strcmp(pstruct->args[i]->name, arg->name) == 0)
    6.88 +		{
    6.89 +			/* Don't allow dup names */
    6.90 +			return NULL;
    6.91 +		}
    6.92 +	}
    6.93 +	
    6.94 +	newarg = (structarg_t *)malloc(sizeof(structarg_t));
    6.95 +
    6.96 +	memcpy(newarg, arg, sizeof(structarg_t));
    6.97 +
    6.98 +	if (pstruct->argcount == 0)
    6.99 +	{
   6.100 +		pstruct->args = (structarg_t **)malloc(sizeof(structarg_t *) * 1);
   6.101 +	} else {
   6.102 +		pstruct->args = (structarg_t **)realloc(
   6.103 +							pstruct->args,
   6.104 +							sizeof(structarg_t *) * (pstruct->argcount + 1));
   6.105 +	}
   6.106 +
   6.107 +	newarg->offs = pstruct->argcount * sizeof(cell);
   6.108 +	newarg->index = pstruct->argcount;
   6.109 +	pstruct->args[pstruct->argcount++] = newarg;
   6.110 +
   6.111 +	return newarg;
   6.112 +}
   6.113  
   6.114  void funcenums_free()
   6.115  {
     7.1 --- a/sourcepawn/compiler/sctracker.h	Wed Nov 08 09:37:16 2006 +0000
     7.2 +++ b/sourcepawn/compiler/sctracker.h	Thu Nov 09 22:53:27 2006 +0000
     7.3 @@ -46,6 +46,35 @@
     7.4    struct funcenum_s *next;
     7.5  } funcenum_t;
     7.6  
     7.7 +typedef struct structarg_s
     7.8 +{
     7.9 +  int tag;
    7.10 +  int dimcount;
    7.11 +  cell dims[sDIMEN_MAX];
    7.12 +  char name[sNAMEMAX+1];
    7.13 +  int fconst;
    7.14 +  int ident;
    7.15 +  unsigned int offs;
    7.16 +  int index;
    7.17 +} structarg_t;
    7.18 +
    7.19 +typedef struct pstruct_s
    7.20 +{
    7.21 +  int argcount;
    7.22 +  char name[sNAMEMAX+1];
    7.23 +  structarg_t **args;
    7.24 +  struct pstruct_s *next;
    7.25 +} pstruct_t;
    7.26 +
    7.27 +/**
    7.28 + * Pawn Structs
    7.29 + */
    7.30 +pstruct_t *pstructs_add(const char *name);
    7.31 +void pstructs_free();
    7.32 +pstruct_t *pstructs_find(const char *name);
    7.33 +structarg_t *pstructs_addarg(pstruct_t *pstruct, const structarg_t *arg);
    7.34 +structarg_t *pstructs_getarg(pstruct_t *pstruct, const char *member);
    7.35 +
    7.36  /**
    7.37   * Function enumeration tags
    7.38   */