# set to 1 to trace object creation/destruction CREATE $(TRACE) = 0 GOTO main FUNCTION return_ifnot conds,result IF $(conds) ~ & P if (!($(conds:# && =))) return $(INIT|$(result)); ENDIF RETURN FUNCTION index_or_return index,return IF $(index) !~ # P int index = aisc_talking_get_index(0, $(index)); /* index_or_return $(return) */ SET $(return) return $(return); P if (aisc_server_error) $(return: ;=;) ENDIF RETURN FUNCTION define_callback a,type,func CONST $(a) # releative key CONST $(type) # function type (get, set etc.) CONST $(func) # function name CREATE $(num) = $(+ $(a)+$(KEYC)) CREATE $(cb) $(type)_list[$(num)] # $(cb) contains name of callback variable IF $($(cb)) IF $($(cb)) ~ 0 ELSE ERROR Number $(KEYC) for '$(func)' already in use by '$($(cb))' ENDIF ELSE ERROR Invalid number $(KEYC) for '$(func)'. Increase MAX_KEY to $(num) in $(argv[2]) ENDIF SET $($(cb)) = $(func) RETURN FUNCTION accessors struct,a,c # struct = struct/member name # a = relative key (int) # c = conditions CONST $(struct) CONST $(a) CONST $(c) CREATE $(su) $(setup) CREATE $(ac) $(access) CREATE $(in) $(index) CONST $(su) CONST $(ac) CONST $(in) CREATE $(type) CREATE $(member) CREATE $(conds) CREATE $(fun) CREATE $(funtype) CREATE $(null) FOR $({/KEY) SET $(member) $(struct)$(KEY) SET $(conds) $(c) SET $(setup) $(su) IF $(TYPE) = dllh SET $(fun) get_$(member)PRED CALL define_callback $(a),get,$(fun) IF $(extern_$(fun)) ELSE P static $(maintype) *$(fun)(const $(maintype) *THIS) { INDENT +1 CALL return_ifnot $(conds),NULp #P return ($(maintype) *)$(ac)previous; P return $(ac)previous; INDENT -1 P } ENDIF SET $(fun) get_$(member)NEXT CALL define_callback $(+ $(a)+1),get,$(fun) IF $(extern_$(fun)) ELSE P static $(maintype) *$(fun)(const $(maintype) *THIS) { INDENT +1 CALL return_ifnot $(conds),NULp #P return ($(maintype) *)$(ac)next; P return $(ac)next; INDENT -1 P } ENDIF PUSH CREATE $(subadd) $(+ 2+$(+ $(a)+$(KEYC))) SET $(access) $(ac)$(IDENT). MOVETO $(/AISC/DATA/STRUCT.dll_header) GOSUB accessors $(member),$(subadd),$(conds) POP CONTINUE ENDIF SET $(index) $(in) SET $(access) $(ac)$(IDENT) IF $(REF) ~ * SET $(conds) $(conds) && $(access) SET $(index) $(SIZE:THIS->=$(ac)) IF $(REF) ~ o,d,l,r SET $(type) $(TYPE) * ELSE SET $(type) $(TYPE) ENDIF SET $(setup) $(setup)if (!$(access)) $(access) = ($(type)*)calloc(sizeof($(type)),$(index));$n SET $(access) $(access)[index] ELSEIF $(REF) ~ v SET $(index) $(SIZE:THIS->=$(ac)) SET $(access) $(access)[index] ENDIF IF $(REF) ~ s IF $(REF) ~ o,l,r SET $(conds) $(conds) && $(access) SET $(setup) $(setup)if (!$(access)) $(access) = create_$(TYPE)();$n SET $(access) $(access)-> ELSEIF $(REF) ~ i SET $(access) $(access). ENDIF PUSH CREATE $(subadd) = $(+ $(a)+$(KEYC)) MOVETO $(/AISC/DATA/STRUCT.$(TYPE)) CALL accessors $(member),$(subadd),$(conds) POP CONTINUE ENDIF IF $(REF) ~ o,d IF $(ACC) !~ c ELSE # CREATE FUNCTIONS SET $(fun) create_$(member) CALL define_callback $(a),create,$(fun) IF $(extern_$(fun)) ELSE P static $(TYPE) *$(fun)($(maintype) *THIS) { INDENT +1 CALL return_ifnot $(conds),NULp CALL index_or_return $(index),NULp P $(TYPE) *obj = create_$(TYPE)(); P if (obj) { INDENT +1 P aisc_make_sets((long *)obj); P if (aisc_server_error) { INDENT +1 P destroy_$(TYPE)(obj); P obj = NULp; INDENT -1 P } P else { INDENT +1 IF $(REF) ~ d P aisc_server_error = aisc_link((dllpublic_ext*)&($(ac)p$(IDENT)), (dllheader_ext*)obj); ELSE P if ($(access)) destroy_$(TYPE)($(access)); P $(access) = obj; ENDIF INDENT -1 P } INDENT -1 P } P return obj; INDENT -1 P } ENDIF # COPY FUNCTIONS SET $(fun) copy_$(member) CALL define_callback $(a),copy,$(fun) IF $(extern_$(fun)) ELSE P static $(TYPE) *$(fun)($(maintype) *THIS) { INDENT +1 CALL return_ifnot $(conds),NULp CALL index_or_return $(index),NULp P trf_begin(); P $(TYPE) *obj = copy_$(TYPE)($(access)); P trf_commit(0); P if (obj) { INDENT +1 P aisc_make_sets((long *)obj); P if (aisc_server_error) { INDENT +1 P destroy_$(TYPE)(obj); P obj = NULp; INDENT -1 P } P else { INDENT +1 IF $(REF) ~ d P aisc_server_error = aisc_link((dllpublic_ext*)&($(ac)p$(IDENT)), (dllheader_ext*)obj); ELSE P if ($(access)) destroy_$(TYPE)($(access)); P $(access) = obj; ENDIF INDENT -1 P } INDENT -1 P } P return obj; INDENT -1 P } ENDIF ENDIF # FIND FUNCTIONS IF $(ACC) !~ f ELSEIF $(REF) ~ d SET $(fun) find_$(member) CALL define_callback $(a),find,$(fun) IF $(extern_$(fun)) ELSE P static $(TYPE) *$(fun)(const $(maintype) *THIS, const char *key) { INDENT +1 CALL return_ifnot $(conds),NULp P $(TYPE) *obj = ($(TYPE)*)aisc_read_hash((aisc_hash_node**)$(ac)p$(IDENT).hash, key); P return obj; INDENT -1 P } ENDIF ENDIF # CNT FUNCTION IF $(REF) ~ d SET $(fun) get_$(member)_CNT CALL define_callback $(+ $(a)+1),get,$(fun) IF $(extern_$(fun)) ELSE P static int $(fun)(const $(maintype) *THIS) { INDENT +1 CALL return_ifnot $(conds),0 P return $(ac)p$(IDENT).cnt; INDENT -1 P } ENDIF ENDIF ELSE # not $(REF) ~ o,d # SET FUNCTIONS IF $(ACC) !~ w ELSEIF $(REF) ~ $(v) CALL define_callback $(a),set,$(IDENT) IF $(extern_$(IDENT)) ELSE OUT import # Generate Prototypes for import P extern int $1$(IDENT)($(maintype)*, $(TYPE:bytestring=bytestring *)); OUT save ENDIF ELSE SET $(fun) set_$(member) CALL define_callback $(a),set,$(fun) IF $(extern_$(fun)) ELSE IF $(REF) ~ o,l,r P static void $(fun)($(maintype) *THIS, const $(TYPE) *x) { ELSEIF $(REF) ~ t,e P static void $(fun)($(maintype) *THIS, $(TYPE:bytestring=const bytestring *) x) { ELSE ERROR UNKNOWN REF '$(REF|)' in $(STRUCT).$(TYPE) ENDIF INDENT +1 CALL index_or_return $(index), P $(setup)$\ IF $(TYPE) = aisc_string P freeset($(access), x); ELSEIF $(TYPE) = bytestring P if (x) { P $1freeset($(access).data, x->data); P $1$(access).size = x->size; P } P else { P $1freenull($(access).data); P $1$(access).size = 0; P } ELSE IF $(REF) ~ o P if ($(access)) destroy_$(TYPE)($(access)); ENDIF P $(access) = x; ENDIF INDENT -1 P } ENDIF ENDIF ENDIF # GET FUNCTIONS IF $(ACC) !~ r ELSEIF $(REF) ~ $(v) IF $(extern_$(IDENT)) CALL define_callback $(a),get,$(IDENT) ELSE IF $(IDENT) = aisc_get_keystring # special cast for aisc_get_keystring CALL define_callback $(a),get,(const char*(*)(int*))$(IDENT) ELSE # explicit cast to overloaded function type before casting to void CALL define_callback $(a),get,($(TYPE:bytestring=bytestring *)(*)(const $(maintype)*))$(IDENT) ENDIF OUT import # Generate Prototypes for import P extern $(TYPE:bytestring=bytestring *) $(IDENT)(const $(maintype)*); OUT save ENDIF ELSE CALL define_callback $(a),get,get_$(member) IF $(extern_get_$(member)) ELSE P static $\ IF $(REF) ~ o,l,r,d SET $(funtype) = const $(TYPE) * ELSEIF $(REF) ~ e,t SET $(funtype) = $(TYPE:bytestring=const bytestring *:aisc_string=aisc_cstring) ELSE ERROR UNKNOWN REF '$(REF|)' in $(STRUCT).$(TYPE) ENDIF # detect return type for return_ifnot and index_or_return below IF $(funtype) ~ * SET $(null) = NULp ELSE # note the trailing space on next line! SET $(funtype) = $(funtype) SET $(null) = 0 ENDIF P $(funtype)get_$(member)(const $(maintype) *THIS) { INDENT +1 CALL return_ifnot $(conds),$(null) CALL index_or_return $(index),$(null) IF $(TYPE) = bytestring P return &($(access)); ELSE P return $(access); ENDIF INDENT -1 P } ENDIF ENDIF ENDFOR RETURN FUNCTION accessor_table fun P void *aisc_talking_functions_$(fun)_$(STRUCT)[] = { INDENT +1 CREATE $(i) CREATE $(cb) CREATE $(zeros) FOR $(i) = 0 TO $(MAX_KEY) SET $(cb) = $($(fun)_list[$(i)]) IF $(cb) = 0 # collect multiple '0' to print them in one line SET $(zeros) = $(zeros) NULp, ELSE IF $(zeros)!= P $(zeros) SET $(zeros) ENDIF IF $(cb) ~ /* SET $(cb) = $(cb:/*=,/*: ,/*=,/*:,/*=, /*) ELSEIF $(cb) ~ // SET $(cb) = $(cb://=,//: ,//=,//:,//=, //) ELSE SET $(cb) = $(cb), ENDIF P (void *)$(cb) ENDIF ENDFOR IF $(zeros) != P $(zeros) NULp ELSE P NULp ENDIF INDENT -1 P }; RETURN FUNCTION accessor_tables CALL accessor_table get CALL accessor_table set CALL accessor_table create CALL accessor_table find CALL accessor_table copy -- RETURN FUNCTION build_accessors # init callback tables CREATE $(i) = 0 FOR $(i) = 0 TO $(MAX_KEY) CREATE $(set_list[$(i)]) 0 CREATE $(get_list[$(i)]) 0 CREATE $(create_list[$(i)]) 0 CREATE $(find_list[$(i)]) 0 CREATE $(copy_list[$(i)]) 0 ENDFOR #CREATE $(conds) CREATE $(access) CREATE $(maintype) CREATE $(setup) CREATE $(index) # CREATE $(joined) FOR $(STRUCT) IF $(SKEY) P // $(STRUCT) accessors -- IF $(JOINED) ELSE FOR $(i) = 0 TO $(MAX_KEY) SET $(set_list[$(i)]) 0 SET $(get_list[$(i)]) 0 SET $(create_list[$(i)]) 0 SET $(find_list[$(i)]) 0 SET $(copy_list[$(i)]) 0 ENDFOR ENDIF #SET $(conds) = # SET $(access) THIS-> SET $(maintype) $(STRUCT) # 'setup' can not be transformed to parameter, cause it is # assigned sth containing ,; etc. so we need to use a global here :-( SET $(setup) SET $(index) # GOSUB accessors $(SKEY)_,0,# -- IF $(JOIN_NEXT) SET $(joined) = $(joined) $(STRUCT) ELSE P // $(joined) $(STRUCT) callback tables SET $(joined) = GOSUB accessor_tables ENDIF ENDIF ENDFOR RETURN # -------------------------------------------------------------------------------- FUNCTION init_structure,self,deref CREATE $(member) CREATE $(isloop) FOR $({/TYPE) SET $(member) $(self)$(deref)$(IDENT) SET $(isloop) 0 IF $(REF) ~ $(v) ELSE IF $(REF) ~ v SET $(isloop) 1 PMSTART PM for (int index = 0; index < $(SIZE:THIS->=$(self)$(deref)); index++) { INDENT +1 SET $(member) $(member)[index] ENDIF IF $(TYPE) = dllh P $(member).key $|= KEY_$(OBJECT_KEY)_$(SKEY|COMMON); PUSH MOVETO $(/AISC/DATA/STRUCT.dll_header) GOSUB init_structure,$(member),. POP ELSEIF $(REF) ~ o # just a NULp pointer - no init necessary ELSEIF $(REF) ~ d PUSH SET $(member) = $(self)$(deref)p$(IDENT) MOVETO $(/AISC/DATA/STRUCT.$(TYPE)) P $(member).parent $|= (dllheader_ext *)$(self); P $(member).key $|= KEY_$(OBJECT_KEY)_$(SKEY|SKEY_missing); POP ELSEIF $(REF) ~ s IF $(REF) ~ i PUSH MOVETO $(/AISC/DATA/STRUCT.$(TYPE)) GOSUB init_structure,$(member),. POP ENDIF ELSEIF $(REF) ~ t,e,l IF $(IDENT) = key IF $(SKEY) !~ COMMON P $(member) $|= KEY_$(OBJECT_KEY)_$(SKEY|COMMON); ENDIF ELSEIF $(INIT) IF $(TYPE) = aisc_string P $(member) $|= strdup($(INIT:THIS=$(self))); ELSE P $(member) $|= $(INIT:THIS=$(self)); ENDIF ENDIF ELSE ERROR UNKNOWN REF '$(REF|)' in $(STRUCT).$(TYPE) ENDIF IF $(isloop) = 1 INDENT -1 PM } PMEND ENDIF ENDIF ENDFOR RETURN FUNCTION build_init P // ------------ P // constructors -- P inline void alloc_err(const char *objectname) { P $1aisc_server_errorf("Could not allocate '%s'", objectname); P } -- FOR $(STRUCT) IF $(extern_create_$(STRUCT)) ELSE P $(STRUCT) *create_$(STRUCT)()$\ P { INDENT +1 P $(STRUCT) *o = ($(STRUCT)*)calloc(sizeof(*o), 1); P if (!o) alloc_err("$(STRUCT)"); PMSTART PM else { INDENT +1 GOSUB init_structure o,-> INDENT -1 PM } PMEND GOSUB trace "created $(STRUCT)" P return o; INDENT -1 P } ENDIF -- ENDFOR RETURN FUNCTION delete_structure,self,deref CREATE $(member) CREATE $(isloop) CREATE $(isinif) CREATE $(start) FOR $({/TYPE) SET $(member) $(self)$(deref)$(IDENT) SET $(isloop) 0 SET $(isinif) 0 IF $(DESTROY) P $(DESTROY:THIS=obj); ELSEIF $(REF) ~ $(v) # virtual function ELSE IF $(REF) ~ *,v PMSTART IF $(REF) ~ * SET $(isinif) 1 PM if ($(member)) { INDENT +1 ENDIF SET $(isloop) 1 PM for (int index = 0; index < $(SIZE:THIS->=$(self)$(deref)); index++) { INDENT +1 SET $(member) $(member)[index] ENDIF IF $(TYPE) = dllh PUSH MOVETO $(/AISC/DATA/STRUCT.dll_header) GOSUB delete_structure,$(member),. POP ELSEIF $(REF) ~ s IF $(REF) ~ o,d,i PUSH IF $(REF) ~ i CREATE $(subderef) . ELSE P if ($(member)) { INDENT +1 CREATE $(subderef) -> ENDIF MOVETO $(/AISC/DATA/STRUCT.$(TYPE)) GOSUB delete_structure,$(member),$(subderef) POP IF $(REF) !~ i P free($(member)); INDENT -1 P } ENDIF ENDIF ELSEIF $(REF) ~ d,o IF $(REF) ~ d P while $\ ELSE P if $\ ENDIF P ($(member)) { INDENT +1 P destroy_$(TYPE)($(member)); P if (aisc_server_error) return; INDENT -1 P } ELSEIF $(REF) ~ t,e IF $(TYPE) = aisc_string P free($(member)); ELSEIF $(TYPE) = bytestring P free($(member).data); ENDIF ELSEIF $(REF) ~ l ELSE ERROR UNKNOWN REF '$(REF|)' in $(STRUCT).$(TYPE) ENDIF IF $(isloop) = 1 INDENT -1 PM } IF $(isinif) = 1 INDENT -1 PM } ENDIF PMEND ENDIF ENDIF ENDFOR RETURN FUNCTION build_delete P // ----------- P // destructors -- FOR $(STRUCT) IF $(extern_destroy_$(STRUCT)) ELSE PUSH CREATE $(islinked) = 0 CREATE $(ident) PUSH MOVETO $({/.) IF $(TYPE) = dllh SET $(islinked) = 1 SET $(ident) = $(IDENT) ENDIF POP # pass pointers to not-linked objects by reference and set them to NULp below # linked object-pointers are set to NULp by aisc_unlink P void destroy_$(STRUCT)($(STRUCT)$\ IF $(islinked) = 1 P *obj$\ ELSE P *& obj$\ ENDIF P ) { INDENT +1 IF $(islinked) = 1 P if (obj->$(ident).parent) { INDENT +1 P aisc_unlink((dllheader_ext*)obj); P if (aisc_server_error) return; INDENT -1 P } ENDIF GOSUB delete_structure,obj,-> IF $(islinked) = 1 P free(obj); ELSE P freenull(obj); ENDIF GOSUB trace "destroyed $(STRUCT)" INDENT -1 P } -- POP ENDIF ENDFOR RETURN FUNCTION move_structure CREATE $(isloop) CREATE $(my_key) CREATE $(index) CREATE $(access) FOR $({/TYPE) SET $(index) SET $(access) $(IDENT) SET $(isloop) 0 IF $(REF) ~ $(v) ELSEIF $(IDENT) = key ELSE IF $(REF) ~ *,v IF $(SIZE) SET $(index) $(SIZE:THIS->=sobj->) ELSE ERROR Missing SIZE in STRUCT $(STRUCT) ident $(IDENT) ENDIF IF $(REF) ~ * P if (dobj->$(access))$\ ENDIF SET $(isloop) 1 PMSTART PM for (int index = 0; index < $(index); index++) { INDENT +1 SET $(access) $(access)[index] ENDIF IF $(TYPE) = dllh P move_dll_header(&(sobj->$(access)), &(dobj->$(access))); ELSEIF $(REF) ~ l,r P dobj->$(access) $|= sobj->$(access); $\ P $|trf_link((long)sobj->$(access), (long*)&dobj->$(access)); ELSEIF $(REF) ~ o P dobj->$(access) $|= copy_$(TYPE)(sobj->$(access)); ELSEIF $(REF) ~ d P for ($(TYPE) *cobj = sobj->$(access); cobj; cobj = cobj->next) { INDENT +1 P $(TYPE) *d2obj = copy_$(TYPE)(cobj); P if (!d2obj) return 1; P aisc_server_error = aisc_link((dllpublic_ext*)&(dobj->p$(access)), (dllheader_ext*)d2obj); P if (aisc_server_error) return 1; INDENT -1 P } ELSEIF $(REF) ~ s IF $(REF) ~ i P if (move_$(TYPE)(&(sobj->$(access)), &(dobj->$(access)))) return 1; ENDIF ELSEIF $(REF) ~ t,e IF $(TYPE) = aisc_string P dobj->$(access) $|= nulldup(sobj->$(access)); ELSEIF $(TYPE) = bytestring P if (sobj->$(access).data) { INDENT +1 P dobj->$(access).data = (char *)malloc(sobj->$(access).size); P memcpy(dobj->$(access).data, sobj->$(access).data, sobj->$(access).size); P dobj->$(access).size = sobj->$(access).size; INDENT -1 P } ELSE P dobj->$(access) $|= sobj->$(access); ENDIF ELSE PP UNKNOWN REF '$(REF|)' in $(STRUCT).$(TYPE) ENDIF IF $(isloop) = 1 INDENT -1 PM } PMEND ENDIF ENDIF ENDFOR RETURN FUNCTION build_move P // ------------ P // move objects -- FOR $(STRUCT) IF $(extern_move_$(STRUCT)) ELSE P static int move_$(STRUCT)(const $(STRUCT) *sobj, $(STRUCT) *dobj) { INDENT +1 GOSUB move_structure P return 0; INDENT -1 P } -- ENDIF ENDFOR RETURN FUNCTION build_copy P // ------------ P // copy objects -- FOR $(STRUCT) IF $(extern_copy_$(STRUCT)) ELSE P $(STRUCT) *copy_$(STRUCT)(const $(STRUCT) *sobj) { INDENT +1 P $(STRUCT) *dobj = NULp; P if (sobj) { INDENT +1 P dobj = create_$(STRUCT)(); P if (!dobj) alloc_err("$(STRUCT)"); P else { INDENT +1 P trf_create((long)sobj, (long)dobj); P if (move_$(STRUCT)(sobj, dobj)) { INDENT +1 P destroy_$(STRUCT)(dobj); P dobj = NULp; INDENT -1 P } INDENT -1 P } INDENT -1 P } GOSUB trace "copied $(STRUCT)" P return dobj; INDENT -1 P } -- ENDIF ENDFOR RETURN FUNCTION save_structure self,deref,prekey,fp CREATE $(member) CREATE $(isloop) CREATE $(isinif) CREATE $(saved_elems) = 0 FOR $({/TYPE) SET $(member) $(self)$(deref)$(IDENT) SET $(isloop) 0 SET $(isinif) 0 IF $(REF) ~ $(v) # virtual function ELSEIF $(SAVE) SET $(saved_elems) = $(+ $(saved_elems)+1) IF $(REF) ~ *,v PMSTART IF $(REF) ~ * SET $(isinif) 1 PM if ($(access)) { INDENT +1 ENDIF SET $(isloop) 1 PM for (int index = 0; index < $(SIZE:THIS->=$(self)$(deref); index++) { INDENT +1 SET $(member) $(member)[index] ENDIF IF $(TYPE) = dllh PUSH CREATE $(pk) $(prekey)$(KEY) MOVETO $(/AISC/DATA/STRUCT.dll_header) GOSUB save_structure,$(member),.,$(pk),$(fp) POP ELSEIF $(REF) ~ s IF $(REF) ~ o,d,i ERROR previously unused - check generated code! PUSH IF $(REF) ~ i CREATE $(subderef) . ELSE PMSTART PM if ($(member)) { INDENT +1 CREATE $(subderef) -> ENDIF CREATE $(pk) $(prekey)$(KEY|NOKEYDEFINED) MOVETO $(/AISC/DATA/STRUCT.$(TYPE)) GOSUB save_structure,$(member),$(subderef),$(pk),$(fp) POP IF $(REF) !~ i INDENT -1 PM } PMEND ENDIF ENDIF ELSEIF $(REF) ~ d IF $(saveable_$(TYPE)) = 0 ERROR Can't save $(TYPE) (has no saveable members) ENDIF P for ($(TYPE) *s = $(member); s; s = s->next) { INDENT +1 P fputs("$(prekey)$(KEY|NOKEYDEFINED){ ", $(fp)); P save_$(TYPE)(s, $(fp)); P fputs("}\n", $(fp)); INDENT -1 P } ELSEIF $(REF) ~ o ERROR previously unused - check generated code! IF $(saveable_$(TYPE)) = 0 ERROR Can't save $(TYPE) (has no saveable members) ENDIF P fputs("$(prekey)$(KEY) {\n", $(fp)); P save_$TYPE($(member), $(fp)); P fputs("}\n", $(fp)); ELSEIF $(REF) ~ t,e IF $(TYPE) = aisc_string P if ($(member)) $|save_string("$(prekey)$(KEY|NOKEYDEFINED)", $(member), $(fp)); ELSEIF $(TYPE) = int,long,char P fprintf($(fp), "$(prekey)$(KEY|NOKEYDEFINED) %i\n", $(member)); ELSEIF $(TYPE) = float,double P fprintf($(fp), "$(prekey)$(KEY|NOKEYDEFINED) %f\n", $(member)); ELSE ERROR CANNOT SAVE TYPE '$(TYPE)' ENDIF ELSEIF $(REF) ~ l P fprintf($(fp), "$(prekey)$(KEY|NOKEYDEFINED) %i", $(member)); ELSE ERROR UNKNOWN REF '$(REF|)' in $(STRUCT).$(TYPE) ENDIF IF $(isloop) = 1 INDENT -1 PM } IF $(isinif) = 1 INDENT -1 PM } ENDIF PMEND ENDIF ENDIF ENDFOR IF $(saved_elems) = 0 ERROR It makes no sense to save $(STRUCT), since it has no saveable data elements ENDIF RETURN FUNCTION load_structure self,deref,prekey,fp CREATE $(member) CREATE $(isloop) CREATE $(isinif) FOR $({/TYPE) SET $(member) $(self)$(deref)$(IDENT) SET $(isloop) 0 SET $(isinif) 0 IF $(REF) ~ $(v) # virtual function ELSEIF $(SAVE) IF $(REF) ~ *,v PMSTART IF $(REF) ~ * SET $(isinif) 1 PM if ($(member)) { INDENT +1 ENDIF SET $(isloop) 1 PM for (int index = 0; index < $(SIZE:THIS->=$(self)$(deref); index++) { INDENT +1 SET $(member) $(member)[index] ENDIF IF $(TYPE) = dllh PUSH CREATE $(pk) $(prekey)$(KEY) MOVETO $(/AISC/DATA/STRUCT.dll_header) GOSUB load_structure,$(member),.,$(pk),$(fp) POP ELSEIF $(REF) ~ s IF $(REF) ~ o,d,i ERROR previously unused - check generated code! PUSH IF $(REF) ~ i CREATE $(subderef) . ELSE PMSTART PM if ($(member)) { INDENT +1 CREATE $(subderef) -> ENDIF CREATE $(pk) $(prekey)$(KEY|NOKEYDEFINED) MOVETO $(/AISC/DATA/STRUCT.$(TYPE)) GOSUB load_structure,$(member),$(subderef),$(pk),$(fp) POP IF $(REF) !~ i INDENT -1 PM } PMEND ENDIF ENDIF ELSEIF $(REF) ~ d P if (strcmp("$(prekey)$(KEY|NOKEYDEFINED){", token)==0) { INDENT +1 P $(TYPE) *cobj = create_$(TYPE)(); P if (cobj) { INDENT +1 P if (load_$(TYPE)(cobj, $(fp))==0) { INDENT +1 P aisc_link((dllpublic_ext*)&($(self)$(deref)p$(IDENT)), (dllheader_ext*)cobj); P continue; INDENT -1 P } P destroy_$(TYPE)(cobj); INDENT -1 P } P return 1; INDENT -1 P } ELSEIF $(REF) ~ o ERROR code generated here is broken (does save instead of load) P fprintf($(fp),"$(prekey)$(KEY) {\n"); P { int error = save_$TYPE($(member),$(fp)); P if (error) return error; } P fprintf($(fp),"}\n"); ELSEIF $(REF) ~ t,e P if (strcmp("$(prekey)$(KEY|NOKEYDEFINED)", token)==0) { INDENT +1 P if (aisc_server_load_token($(fp), token, $(TOKENSIZE))) return 1; IF $(TYPE) = aisc_string P $(member) = strdup(token); ELSEIF $(TYPE) = int,long,char P $(member) = atoi(token); ELSEIF $(TYPE) = float,double P $(member) = atof(token); ELSE ERROR Loading type '$(TYPE)' not implemented (yet) ENDIF P continue; INDENT -1 P } ELSEIF $(REF) ~ l ERROR loading links not implemented (yet) ELSE ERROR UNKNOWN REF '$(REF|)' in $(STRUCT).$(TYPE) ENDIF IF $(isloop) = 1 INDENT -1 PM } IF $(isinif) = 1 INDENT -1 PM } ENDIF PMEND ENDIF ENDIF ENDFOR RETURN FUNCTION build_saveload CREATE $(TOKENSIZE) 1024 P // ------------- P // save and load -- P inline void warn_unknown_token(const char *token, const char *objectname) { P $1fprintf(stderr, "Unknown token '%s' while loading '%s' (ignored)\n", token, objectname); P } -- P inline void save_string(const char *key, const char *value, FILE *out) { INDENT +1 P fputs(key, out); P fputc(' ', out); P aisc_server_save_token(out, value, $(TOKENSIZE)); INDENT -1 P } -- FOR $(STRUCT) CREATE $(saveable_$(STRUCT)) = 0 FOR $({/TYPE) IF $(SAVE) SET $(saveable_$(STRUCT)) = 1 ENDIF ENDFOR #WARNING saveable_$(STRUCT) = $(saveable_$(STRUCT)) ENDFOR FOR $(STRUCT) IF $(saveable_$(STRUCT)) = 1 IF $(extern_save_$(STRUCT)) ELSE P void save_$(STRUCT)(const $(STRUCT) *o, FILE *out) { INDENT +1 GOSUB save_structure,o,->,,out INDENT -1 P } -- ENDIF ENDIF ENDFOR FOR $(STRUCT) IF $(saveable_$(STRUCT)) = 1 IF $(extern_load_$(STRUCT)) ELSE P int load_$(STRUCT)($(STRUCT) *o, FILE *in) { INDENT +1 P char token[$(TOKENSIZE)+1]; P while (aisc_server_load_token(in, token, $(TOKENSIZE))==0) { INDENT +1 P if (*token == '}') break; GOSUB load_structure,o,->,,in P warn_unknown_token(token, "$(STRUCT)"); INDENT -1 P } P return 0; INDENT -1 P } -- ENDIF ENDIF ENDFOR RETURN FUNCTION trace msg IF $(TRACE) = 1 P fputs("AISC_SERVER_TRACE " $(msg) "\n", stderr); fflush(stderr); ENDIF RETURN FUNCTION file_header P // ----------------------------------------------------------------- P // Created automagically from ../$(argv[2]) P // and ../$(argv[4]) P // using aisc-script '../AISC/aisc_server.pa' P // DO NOT EDIT THIS FILE!!! P // ----------------------------------------------------------------- -- RETURN # -------------------------------------------------------------------------------- LABEL main IF $(argc) < 7 ERROR Wrong number of parameters[$(argc)]. Usage: aisc aisc_server.pa xxx.aisc outfile externfile.aisc import_proto globals.aisc ENDIF DATA AISC { $(#FILE $(argv[2])) }, EXTERN { $(#FILE $(argv[4])) }, GLOBALS { $(#FILE $(argv[6])) }; DUMPDATA DUMP/aisc_server.pa__$(argv[2]).dump OPEN save $(argv[3]) OPEN import $(argv[5]) # set extern functions MOVETO $(EXTERN/.) FOR $(FUNCTION) CREATE $(extern_$(FUNCTION)) NEXT ERROR no extern Functions found ENDFOR # set globals passed from Makefile MOVETO $(/GLOBALS/.) CREATE $(create_save_code) = $(AISC_SAVE) OUT import CALL file_header OUT save CALL file_header P $(#FILE C/aisc_server.h) MOVETO $(/AISC/DATA/.) CREATE $(v) = % CALL build_init CALL build_delete CALL build_move CALL build_copy CALL build_accessors IF $(create_save_code) = YES CALL build_saveload ENDIF CLOSE save CLOSE import EXIT