1.1 --- a/compiler-init/scstate.c Sat Jul 15 01:36:48 2006 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,375 +0,0 @@
1.4 -/* Pawn compiler
1.5 - *
1.6 - * Machine and state maintenance.
1.7 - *
1.8 - * Three lists are maintained here:
1.9 - * - A list of automatons (state machines): these hold a name, a unique id
1.10 - * (in the "index" field) and the memory address of a cell that holds the
1.11 - * current state of the automaton (in the "value" field).
1.12 - * - A list of states for each automaton: a name, an automaton id (in the
1.13 - * "index" field) and a unique id for the state (unique in the automaton;
1.14 - * states belonging to different automatons may have the same id).
1.15 - * - A list of state combinations. Each function may belong to a set of states.
1.16 - * This list assigns a unique id to the combination of the automaton and all
1.17 - * states.
1.18 - *
1.19 - * For a function/variable that has states, there is a fourth list, which is
1.20 - * attached to the "symbol" structure. This list contains the code label (in
1.21 - * the "name" field, only for functions), the id of the state combinations (the
1.22 - * state list id; it is stored in the "index" field) and the code address at
1.23 - * which the function starts. The latter is currently unused.
1.24 - *
1.25 - * At the start of the compiled code, a set of stub functions is generated.
1.26 - * Each stub function looks up the value of the "state selector" value for the
1.27 - * automaton, and goes with a "switch" instruction to the start address of the
1.28 - * function. This happens in SC4.C.
1.29 - *
1.30 - *
1.31 - * Copyright (c) ITB CompuPhase, 2005-2006
1.32 - *
1.33 - * This software is provided "as-is", without any express or implied warranty.
1.34 - * In no event will the authors be held liable for any damages arising from
1.35 - * the use of this software.
1.36 - *
1.37 - * Permission is granted to anyone to use this software for any purpose,
1.38 - * including commercial applications, and to alter it and redistribute it
1.39 - * freely, subject to the following restrictions:
1.40 - *
1.41 - * 1. The origin of this software must not be misrepresented; you must not
1.42 - * claim that you wrote the original software. If you use this software in
1.43 - * a product, an acknowledgment in the product documentation would be
1.44 - * appreciated but is not required.
1.45 - * 2. Altered source versions must be plainly marked as such, and must not be
1.46 - * misrepresented as being the original software.
1.47 - * 3. This notice may not be removed or altered from any source distribution.
1.48 - *
1.49 - * Version: $Id: scstate.c 3579 2006-06-06 13:35:29Z thiadmer $
1.50 - */
1.51 -#include <assert.h>
1.52 -#include <limits.h>
1.53 -#include <stdio.h>
1.54 -#include <stdlib.h>
1.55 -#include <string.h>
1.56 -#include "sc.h"
1.57 -#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
1.58 - #include <sclinux.h>
1.59 -#endif
1.60 -
1.61 -#if defined FORTIFY
1.62 - #include <alloc/fortify.h>
1.63 -#endif
1.64 -
1.65 -typedef struct s_statelist {
1.66 - struct s_statelist *next;
1.67 - int *states; /* list of states in this combination */
1.68 - int numstates; /* number of items in the above list */
1.69 - int fsa; /* automaton id */
1.70 - int listid; /* unique id for this combination list */
1.71 -} statelist;
1.72 -
1.73 -static statelist statelist_tab = { NULL, NULL, 0, 0, 0}; /* state combinations table */
1.74 -
1.75 -
1.76 -static constvalue *find_automaton(const char *name,int *last)
1.77 -{
1.78 - constvalue *ptr;
1.79 -
1.80 - assert(last!=NULL);
1.81 - *last=0;
1.82 - ptr=sc_automaton_tab.next;
1.83 - while (ptr!=NULL) {
1.84 - if (strcmp(name,ptr->name)==0)
1.85 - return ptr;
1.86 - if (ptr->index>*last)
1.87 - *last=ptr->index;
1.88 - ptr=ptr->next;
1.89 - } /* while */
1.90 - return NULL;
1.91 -}
1.92 -
1.93 -SC_FUNC constvalue *automaton_add(const char *name)
1.94 -{
1.95 - constvalue *ptr;
1.96 - int last;
1.97 -
1.98 - assert(strlen(name)<sizeof(ptr->name));
1.99 - ptr=find_automaton(name,&last);
1.100 - if (ptr==NULL) {
1.101 - assert(last+1 <= SHRT_MAX);
1.102 - ptr=append_constval(&sc_automaton_tab,name,(cell)0,(short)(last+1));
1.103 - } /* if */
1.104 - return ptr;
1.105 -}
1.106 -
1.107 -SC_FUNC constvalue *automaton_find(const char *name)
1.108 -{
1.109 - int last;
1.110 - return find_automaton(name,&last);
1.111 -}
1.112 -
1.113 -SC_FUNC constvalue *automaton_findid(int id)
1.114 -{
1.115 - constvalue *ptr;
1.116 - for (ptr=sc_automaton_tab.next; ptr!=NULL && ptr->index!=id; ptr=ptr->next)
1.117 - /* nothing */;
1.118 - return ptr;
1.119 -}
1.120 -
1.121 -
1.122 -static constvalue *find_state(const char *name,int fsa,int *last)
1.123 -{
1.124 - constvalue *ptr;
1.125 -
1.126 - assert(last!=NULL);
1.127 - *last=0;
1.128 - ptr=sc_state_tab.next;
1.129 - while (ptr!=NULL) {
1.130 - if (ptr->index==fsa) {
1.131 - if (strcmp(name,ptr->name)==0)
1.132 - return ptr;
1.133 - if ((int)ptr->value>*last)
1.134 - *last=(int)ptr->value;
1.135 - } /* if */
1.136 - ptr=ptr->next;
1.137 - } /* while */
1.138 - return NULL;
1.139 -}
1.140 -
1.141 -SC_FUNC constvalue *state_add(const char *name,int fsa)
1.142 -{
1.143 - constvalue *ptr;
1.144 - int last;
1.145 -
1.146 - assert(strlen(name)<sizeof(ptr->name));
1.147 - ptr=find_state(name,fsa,&last);
1.148 - if (ptr==NULL) {
1.149 - assert(fsa <= SHRT_MAX);
1.150 - ptr=append_constval(&sc_state_tab,name,(cell)(last+1),(short)fsa);
1.151 - } /* if */
1.152 - return ptr;
1.153 -}
1.154 -
1.155 -SC_FUNC constvalue *state_find(const char *name,int fsa_id)
1.156 -{
1.157 - int last; /* dummy */
1.158 - return find_state(name,fsa_id,&last);
1.159 -}
1.160 -
1.161 -SC_FUNC constvalue *state_findid(int id)
1.162 -{
1.163 - constvalue *ptr;
1.164 - for (ptr=sc_state_tab.next; ptr!=NULL && ptr->value!=id; ptr=ptr->next)
1.165 - /* nothing */;
1.166 - return ptr;
1.167 -}
1.168 -
1.169 -SC_FUNC void state_buildlist(int **list,int *listsize,int *count,int stateid)
1.170 -{
1.171 - int idx;
1.172 -
1.173 - assert(list!=NULL);
1.174 - assert(listsize!=NULL);
1.175 - assert(*listsize>=0);
1.176 - assert(count!=NULL);
1.177 - assert(*count>=0);
1.178 - assert(*count<=*listsize);
1.179 -
1.180 - if (*count==*listsize) {
1.181 - /* To avoid constantly calling malloc(), the list is grown by 4 states at
1.182 - * a time.
1.183 - */
1.184 - *listsize+=4;
1.185 - *list=(int*)realloc(*list,*listsize*sizeof(int));
1.186 - if (*list==NULL)
1.187 - error(103); /* insufficient memory */
1.188 - } /* if */
1.189 -
1.190 - /* find the insertion point (the list has to stay sorted) */
1.191 - for (idx=0; idx<*count && *list[idx]<stateid; idx++)
1.192 - /* nothing */;
1.193 - if (idx<*count)
1.194 - memmove(&(*list)[idx+1],&(*list)[idx],(int)((*count-idx+1)*sizeof(int)));
1.195 - (*list)[idx]=stateid;
1.196 - *count+=1;
1.197 -}
1.198 -
1.199 -static statelist *state_findlist(int *list,int count,int fsa,int *last)
1.200 -{
1.201 - statelist *ptr;
1.202 - int i;
1.203 -
1.204 - assert(count>0);
1.205 - assert(last!=NULL);
1.206 - *last=0;
1.207 - ptr=statelist_tab.next;
1.208 - while (ptr!=NULL) {
1.209 - if (ptr->listid>*last)
1.210 - *last=ptr->listid;
1.211 - if (ptr->fsa==fsa && ptr->numstates==count) {
1.212 - /* compare all states */
1.213 - for (i=0; i<count && ptr->states[i]==list[i]; i++)
1.214 - /* nothing */;
1.215 - if (i==count)
1.216 - return ptr;
1.217 - } /* if */
1.218 - ptr=ptr->next;
1.219 - } /* while */
1.220 - return NULL;
1.221 -}
1.222 -
1.223 -static statelist *state_getlist_ptr(int listid)
1.224 -{
1.225 - statelist *ptr;
1.226 -
1.227 - assert(listid>0);
1.228 - for (ptr=statelist_tab.next; ptr!=NULL && ptr->listid!=listid; ptr=ptr->next)
1.229 - /* nothing */;
1.230 - return ptr;
1.231 -}
1.232 -
1.233 -SC_FUNC int state_addlist(int *list,int count,int fsa)
1.234 -{
1.235 - statelist *ptr;
1.236 - int last;
1.237 -
1.238 - assert(list!=NULL);
1.239 - assert(count>0);
1.240 - ptr=state_findlist(list,count,fsa,&last);
1.241 - if (ptr==NULL) {
1.242 - if ((ptr=(statelist*)malloc(sizeof(statelist)))==NULL)
1.243 - error(103); /* insufficient memory */
1.244 - if ((ptr->states=(int*)malloc(count*sizeof(int)))==NULL) {
1.245 - free(ptr);
1.246 - error(103); /* insufficient memory */
1.247 - } /* if */
1.248 - memcpy(ptr->states,list,count*sizeof(int));
1.249 - ptr->numstates=count;
1.250 - ptr->fsa=fsa;
1.251 - ptr->listid=last+1;
1.252 - ptr->next=statelist_tab.next;
1.253 - statelist_tab.next=ptr;
1.254 - } /* if */
1.255 - assert(ptr!=NULL);
1.256 - return ptr->listid;
1.257 -}
1.258 -
1.259 -SC_FUNC void state_deletetable(void)
1.260 -{
1.261 - statelist *ptr;
1.262 -
1.263 - while (statelist_tab.next!=NULL) {
1.264 - ptr=statelist_tab.next;
1.265 - /* unlink first */
1.266 - statelist_tab.next=ptr->next;
1.267 - /* then delete */
1.268 - assert(ptr->states!=NULL);
1.269 - free(ptr->states);
1.270 - free(ptr);
1.271 - } /* while */
1.272 -}
1.273 -
1.274 -SC_FUNC int state_getfsa(int listid)
1.275 -{
1.276 - statelist *ptr;
1.277 -
1.278 - assert(listid>=0);
1.279 - if (listid==0)
1.280 - return -1;
1.281 -
1.282 - ptr=state_getlist_ptr(listid);
1.283 - return (ptr!=NULL) ? ptr->fsa : -1; /* fsa 0 exists */
1.284 -}
1.285 -
1.286 -SC_FUNC int state_count(int listid)
1.287 -{
1.288 - statelist *ptr=state_getlist_ptr(listid);
1.289 - if (ptr==NULL)
1.290 - return 0; /* unknown list, no states in it */
1.291 - return ptr->numstates;
1.292 -}
1.293 -
1.294 -SC_FUNC int state_inlist(int listid,int state)
1.295 -{
1.296 - statelist *ptr;
1.297 - int i;
1.298 -
1.299 - ptr=state_getlist_ptr(listid);
1.300 - if (ptr==NULL)
1.301 - return FALSE; /* unknown list, state not in it */
1.302 - for (i=0; i<ptr->numstates; i++)
1.303 - if (ptr->states[i]==state)
1.304 - return TRUE;
1.305 - return FALSE;
1.306 -}
1.307 -
1.308 -SC_FUNC int state_listitem(int listid,int index)
1.309 -{
1.310 - statelist *ptr;
1.311 -
1.312 - ptr=state_getlist_ptr(listid);
1.313 - assert(ptr!=NULL);
1.314 - assert(index>=0 && index<ptr->numstates);
1.315 - return ptr->states[index];
1.316 -}
1.317 -
1.318 -static int checkconflict(statelist *psrc,statelist *ptgt)
1.319 -{
1.320 - int s,t;
1.321 -
1.322 - assert(psrc!=NULL);
1.323 - assert(ptgt!=NULL);
1.324 - for (s=0; s<psrc->numstates; s++)
1.325 - for (t=0; t<ptgt->numstates; t++)
1.326 - if (psrc->states[s]==ptgt->states[t])
1.327 - return 1; /* state conflict */
1.328 - return 0;
1.329 -}
1.330 -
1.331 -/* This function searches whether one of the states in the list of statelist id's
1.332 - * of a symbol exists in any other statelist id's of the same function; it also
1.333 - * verifies that all definitions of the symbol are in the same automaton.
1.334 - */
1.335 -SC_FUNC void state_conflict(symbol *root)
1.336 -{
1.337 - statelist *psrc,*ptgt;
1.338 - constvalue *srcptr,*tgtptr;
1.339 - symbol *sym;
1.340 -
1.341 - assert(root!=NULL);
1.342 - for (sym=root->next; sym!=NULL; sym=sym->next) {
1.343 - if (sym->parent!=NULL || sym->ident!=iFUNCTN)
1.344 - continue; /* hierarchical data type or no function */
1.345 - if (sym->states==NULL)
1.346 - continue; /* this function has no states */
1.347 - for (srcptr=sym->states->next; srcptr!=NULL; srcptr=srcptr->next) {
1.348 - if (srcptr->index==-1)
1.349 - continue; /* state list id -1 is a special case */
1.350 - psrc=state_getlist_ptr(srcptr->index);
1.351 - assert(psrc!=NULL);
1.352 - for (tgtptr=srcptr->next; tgtptr!=NULL; tgtptr=tgtptr->next) {
1.353 - if (tgtptr->index==-1)
1.354 - continue; /* state list id -1 is a special case */
1.355 - ptgt=state_getlist_ptr(tgtptr->index);
1.356 - assert(ptgt!=NULL);
1.357 - if (psrc->fsa!=ptgt->fsa && strcmp(sym->name,uENTRYFUNC)!=0)
1.358 - error(83,sym->name); /* this function is part of another machine */
1.359 - if (checkconflict(psrc,ptgt))
1.360 - error(84,sym->name); /* state conflict */
1.361 - } /* for (tgtptr) */
1.362 - } /* for (srcptr) */
1.363 - } /* for (sym) */
1.364 -}
1.365 -
1.366 -/* check whether the two state lists (whose ids are passed in) share any
1.367 - * states
1.368 - */
1.369 -SC_FUNC int state_conflict_id(int listid1,int listid2)
1.370 -{
1.371 - statelist *psrc,*ptgt;
1.372 -
1.373 - psrc=state_getlist_ptr(listid1);
1.374 - assert(psrc!=NULL);
1.375 - ptgt=state_getlist_ptr(listid2);
1.376 - assert(ptgt!=NULL);
1.377 - return checkconflict(psrc,ptgt);
1.378 -}