00001
00047 #include "class.h"
00048 #include "output.h"
00049 #include "convert.h"
00050 #include "module.h"
00051 #include "exception.h"
00052 #include "timestamp.h"
00053 #include "loadshape.h"
00054 #include "enduse.h"
00055 #include "stream.h"
00056
00057 static unsigned int class_count = 0;
00058
00059 int convert_from_real(char *a, int b, void *c, PROPERTY *d){return 0;}
00060 int convert_to_real(char *a, void *b, PROPERTY *c){return 0;}
00061 int convert_from_float(char *a, int b, void *c, PROPERTY *d){return 0;}
00062 int convert_to_float(char *a, void *b, PROPERTY *c){return 0;}
00063
00064
00065 static struct s_property_specs {
00069 char *name;
00070 unsigned int size;
00071 int (*data_to_string)(char *,int,void*,PROPERTY*);
00072 int (*string_to_data)(char *,void*,PROPERTY*);
00073 int (*create)(void*);
00074 int (*stream_in)(FILE*,void*,PROPERTY*);
00075 int (*stream_out)(FILE*,void*,PROPERTY*);
00076 } property_type[] = {
00077 {"void", 0, convert_from_void,convert_to_void},
00078 {"double", sizeof(double), convert_from_double,convert_to_double,NULL,stream_in_double,stream_out_double},
00079 {"complex", sizeof(complex), convert_from_complex,convert_to_complex},
00080 {"enumeration",sizeof(long), convert_from_enumeration,convert_to_enumeration},
00081 {"set",sizeof(int64), convert_from_set,convert_to_set},
00082 {"int16", sizeof(int16), convert_from_int16,convert_to_int16},
00083 {"int32", sizeof(int32), convert_from_int32,convert_to_int32},
00084 {"int64", sizeof(int64), convert_from_int64,convert_to_int64},
00085 {"char8", sizeof(char8), convert_from_char8,convert_to_char8},
00086 {"char32", sizeof(char32), convert_from_char32,convert_to_char32},
00087 {"char256", sizeof(char256), convert_from_char256,convert_to_char256},
00088 {"char1024", sizeof(char1024), convert_from_char1024,convert_to_char1024},
00089 {"object", sizeof(OBJECT*), convert_from_object,convert_to_object},
00090 {"delegated", (size_t)-1, convert_from_delegated, convert_to_delegated},
00091 {"bool", sizeof(unsigned int), convert_from_boolean, convert_to_boolean},
00092 {"timestamp", sizeof(int64), convert_from_timestamp_stub, convert_to_timestamp_stub},
00093 {"double_array", sizeof(double), convert_from_double_array, convert_to_double_array},
00094 {"complex_array", sizeof(complex), convert_from_complex_array, convert_to_complex_array},
00095 {"real", sizeof(real), convert_from_real, convert_to_real},
00096 {"float", sizeof(float), convert_from_float, convert_to_float},
00097 {"loadshape", sizeof(loadshape), convert_from_loadshape, convert_to_loadshape, loadshape_create},
00098 {"enduse",sizeof(enduse), convert_from_enduse, convert_to_enduse, enduse_create},
00099 };
00100
00101
00102 static CLASS *first_class = NULL;
00103 static CLASS *last_class = NULL;
00124 PROPERTY *class_get_first_property(CLASS *oclass)
00125 {
00126 if (oclass==NULL)
00127 throw_exception("class_get_first_property(CLASS *oclass=NULL): oclass is NULL");
00128
00129
00130
00131
00132 return oclass->pmap;
00133 }
00134
00138 PROPERTY *class_get_next_property(PROPERTY *prop)
00139 {
00140 if (prop->next && prop->oclass==prop->next->oclass)
00141 return prop->next;
00142 else
00143 return NULL;
00144 }
00145
00149 PROPERTY *class_prop_in_class(CLASS *oclass, PROPERTY *prop)
00150 {
00151 if(oclass == prop->oclass)
00152 {
00153 return prop;
00154 }
00155 else
00156 {
00157 if(oclass->parent != NULL)
00158 {
00159 return class_prop_in_class(oclass->parent, prop);
00160 }
00161 else
00162 {
00163 return NULL;
00164 }
00165 }
00166 }
00167
00171 unsigned long property_size(PROPERTY *prop)
00172 {
00173 if (prop && prop->ptype>_PT_FIRST && prop->ptype<_PT_LAST)
00174 return property_type[prop->ptype].size;
00175 else
00176 return 0;
00177 }
00178
00179 unsigned long property_size_by_type(PROPERTYTYPE type)
00180 {
00181 return property_type[type].size;
00182 }
00183
00184 int property_create(PROPERTY *prop, void *addr)
00185 {
00186 if (prop && prop->ptype>_PT_FIRST && prop->ptype<_PT_LAST)
00187 {
00188 if (property_type[prop->ptype].create)
00189 return property_type[prop->ptype].create(addr);
00190
00191 memset(addr,0,property_type[prop->ptype].size);
00192 return 1;
00193 }
00194 else
00195 return 0;
00196 }
00197
00198
00199
00200
00201 PROPERTY *class_find_property_rec(CLASS *oclass, PROPERTYNAME name, CLASS *pclass)
00202 {
00203 PROPERTY *prop;
00204 for (prop=oclass->pmap; prop!=NULL && prop->oclass==oclass; prop=prop->next)
00205 {
00206 if (strcmp(name,prop->name)==0)
00207 return prop;
00208 }
00209 if (oclass->parent==pclass)
00210 {
00211 output_error("class_find_property_rec(CLASS *oclass='%s', PROPERTYNAME name='%s', CLASS *pclass='%s') causes an infinite class inheritance loop", oclass->name, name, pclass->name);
00212
00213
00214
00215
00216 return NULL;
00217 }
00218 else if (oclass->parent!=NULL)
00219 return class_find_property_rec(oclass->parent,name, pclass);
00220 else
00221 return NULL;
00222
00223 }
00224
00229 PROPERTY *class_find_property(CLASS *oclass,
00230 PROPERTYNAME name)
00231 {
00232 PROPERTY *prop;
00233
00234 if(oclass == NULL)
00235 return NULL;
00236
00237 for (prop=oclass->pmap; prop!=NULL && prop->oclass==oclass; prop=prop->next)
00238 {
00239 if (strcmp(name,prop->name)==0)
00240 {
00241 if (prop->flags&PF_DEPRECATED && !(prop->flags&PF_DEPRECATED_NONOTICE) && !global_suppress_deprecated_messages)
00242 {
00243 output_warning("class_find_property(CLASS *oclass='%s', PROPERTYNAME name='%s': property is deprecated", oclass->name, name);
00244
00245
00246
00247
00248 if (global_suppress_repeat_messages)
00249 prop->flags |= ~PF_DEPRECATED_NONOTICE;
00250 }
00251 return prop;
00252 }
00253 }
00254 if (oclass->parent==oclass)
00255 {
00256 output_error("class_find_property(oclass='%s', name='%s') causes an infinite class inheritance loop", oclass->name, name);
00257
00258
00259
00260
00261 return NULL;
00262 }
00263 else if (oclass->parent!=NULL)
00264 return class_find_property_rec(oclass->parent,name, oclass);
00265 else
00266 return NULL;
00267 }
00268
00269 void class_add_property(CLASS *oclass, PROPERTY *prop)
00270 {
00271 PROPERTY *last = oclass->pmap;
00272 while (last!=NULL && last->next!=NULL)
00273 last = last->next;
00274 if (last==NULL)
00275 oclass->pmap = prop;
00276 else
00277 last->next = prop;
00278 }
00279
00280 PROPERTY *class_add_extended_property(CLASS *oclass, char *name, PROPERTYTYPE ptype, char *unit)
00281 {
00282 PROPERTY *prop = malloc(sizeof(PROPERTY));
00283 UNIT *pUnit = NULL;
00284
00285 TRY {
00286 if (unit)
00287 pUnit = unit_find(unit);
00288 } CATCH (char *msg) {
00289
00290 } ENDCATCH;
00291
00292 if (prop==NULL)
00293 throw_exception("class_add_extended_property(oclass='%s', name='%s', ...): memory allocation failed", oclass->name, name);
00294
00295
00296
00297 if (ptype<=_PT_FIRST || ptype>=_PT_LAST)
00298 throw_exception("class_add_extended_property(oclass='%s', name='%s', ...): property type is invalid", oclass->name, name);
00299
00300
00301
00302 if (unit!=NULL && pUnit==NULL)
00303 throw_exception("class_add_extended_property(oclass='%s', name='%s', ...): unit '%s' is not found", oclass->name, name, unit);
00304
00305
00306
00307
00308 prop->access = PA_PUBLIC;
00309 prop->addr = (void*)(int64)oclass->size;
00310 prop->size = 0;
00311 prop->delegation = NULL;
00312 prop->flags = PT_EXTENDED;
00313 prop->keywords = NULL;
00314 prop->description = NULL;
00315 prop->unit = pUnit;
00316 strncpy(prop->name,name,sizeof(prop->name));
00317 prop->next = NULL;
00318 prop->oclass = oclass;
00319 prop->ptype = ptype;
00320
00321 oclass->size += property_type[ptype].size;
00322
00323 class_add_property(oclass,prop);
00324 return prop;
00325 }
00326
00330 CLASS *class_get_last_class(void)
00331 {
00332 return last_class;
00333 }
00334
00338 unsigned int class_get_count(void)
00339 {
00340 return class_count;
00341 }
00342
00346 char *class_get_property_typename(PROPERTYTYPE type)
00347 {
00348 if (type<=_PT_FIRST || type>=_PT_LAST)
00349 return "##UNDEF##";
00350 else
00351 return property_type[type].name;
00352 }
00353
00357 PROPERTYTYPE class_get_propertytype_from_typename(char *name)
00358 {
00359 int i;
00360 for (i=0; i<sizeof(property_type)/sizeof(property_type[0]); i++)
00361 {
00362 if (strcmp(property_type[i].name,name)==0)
00363 return i;
00364 }
00365 return PT_void;
00366 }
00367
00368 int class_string_to_propertytype(PROPERTYTYPE type, void *addr, char *value)
00369 {
00370 if (type > _PT_FIRST && type < _PT_LAST)
00371 return (*property_type[type].string_to_data)(value,addr,NULL);
00372 else
00373 return 0;
00374 }
00379 int class_string_to_property(PROPERTY *prop,
00380 void *addr,
00381 char *value)
00382 {
00383 if (prop->ptype > _PT_FIRST && prop->ptype < _PT_LAST)
00384 return (*property_type[prop->ptype].string_to_data)(value,addr,prop);
00385 else
00386 return 0;
00387 }
00388
00393 int class_property_to_string(PROPERTY *prop,
00394 void *addr,
00395 char *value,
00396 int size)
00397 {
00398 if (prop->ptype==PT_delegated)
00399 {
00400 output_error("unable to convert from delegated property value");
00401
00402
00403
00404
00405 return 0;
00406 }
00407 else if (prop->ptype>_PT_FIRST && prop->ptype<_PT_LAST)
00408 return (*property_type[prop->ptype].data_to_string)(value,size,addr,prop);
00409 else
00410 return 0;
00411 }
00412
00413
00420 CLASS *class_register(MODULE *module,
00421 CLASSNAME name,
00422 unsigned int size,
00423 PASSCONFIG passconfig)
00424 {
00425 CLASS *oclass = class_get_class_from_classname(name);
00426
00427
00428 int a = sizeof(property_type);
00429 int b = sizeof(property_type[0]);
00430 int c = _PT_LAST - _PT_FIRST - 1;
00431
00432 if (_PT_LAST-_PT_FIRST-1!=sizeof(property_type)/sizeof(property_type[0]))
00433 {
00434 output_fatal("property_type[] in class.c has an incorrect number of members (%i vs %i)", a/b, c);
00435
00436
00437
00438
00439
00440 exit(1);
00441 }
00442 if (oclass!=NULL)
00443 {
00444 if(strcmp(oclass->module->name, module->name) == 0){
00445 output_error("module %s cannot register class %s, it is already registered by module %s", module->name,name,oclass->module->name);
00446
00447
00448
00449
00450
00451 return NULL;
00452 } else {
00453 output_verbose("module %s is registering a 2nd class %s, previous one in module %s", module->name, name, oclass->module->name);
00454 }
00455 }
00456 if (strlen(name)>=sizeof(oclass->name) )
00457 {
00458 errno = E2BIG;
00459 return 0;
00460 }
00461 oclass = (CLASS*)malloc(sizeof(CLASS));
00462 if (oclass==NULL)
00463 {
00464 errno = ENOMEM;
00465 return 0;
00466 }
00467 memset(oclass,0,sizeof(CLASS));
00468 oclass->magic = CLASSVALID;
00469 oclass->module = module;
00470 strncpy(oclass->name,name,sizeof(oclass->name));
00471 oclass->size = size;
00472 oclass->passconfig = passconfig;
00473 oclass->profiler.numobjs=0;
00474 oclass->profiler.count=0;
00475 oclass->profiler.clocks=0;
00476 if (first_class==NULL)
00477 first_class = oclass;
00478 else
00479 last_class->next = oclass;
00480 last_class = oclass;
00481 output_verbose("class %s registered ok", name);
00482 class_count++;
00483 return oclass;
00484 }
00485
00490 CLASS *class_get_first_class(void)
00491 {
00492 return first_class;
00493 }
00494
00499 CLASS *class_get_class_from_classname_in_module(char *name, MODULE *mod){
00500 CLASS *oclass = NULL;
00501 if(name == NULL) return NULL;
00502 if(mod == NULL) return NULL;
00503 for (oclass=first_class; oclass!=NULL; oclass=oclass->next)
00504 {
00505 if(oclass->module == (MODULE *)mod)
00506 if(strcmp(oclass->name,name)==0)
00507 return oclass;
00508 }
00509 return NULL;
00510 }
00511
00512 PROPERTY *property_malloc(PROPERTYTYPE proptype, CLASS *oclass, char *name, void *addr, DELEGATEDTYPE *delegation)
00513 {
00514 char unitspec[1024];
00515 PROPERTY *prop = (PROPERTY*)malloc(sizeof(PROPERTY));
00516
00517 if (prop==NULL)
00518 {
00519 output_error("property_malloc(oclass='%s',...): memory allocation failed", oclass->name, name);
00520
00521
00522
00523
00524 errno = ENOMEM;
00525 goto Error;
00526 }
00527 prop->ptype = proptype;
00528 prop->size = 0;
00529 prop->access = PA_PUBLIC;
00530 prop->oclass = oclass;
00531 prop->flags = 0;
00532 prop->keywords = NULL;
00533 prop->description = NULL;
00534 prop->unit = NULL;
00535 if (sscanf(name,"%[^[][%[A-Za-z0-9*/^]]",prop->name,unitspec)==2)
00536 {
00537
00538 if (prop->ptype!=PT_double && prop->ptype!=PT_complex)
00539 output_error("property_malloc(oclass='%s',...): property %s cannot have unit '%s' because it is not a double or complex value",oclass->name, prop->name,unitspec);
00540
00541
00542
00543
00544
00545
00546 else
00547 {
00548 TRY {
00549 if ((prop->unit = unit_find(unitspec))==NULL)
00550 output_error("property_malloc(oclass='%s',...): property %s unit '%s' is not recognized",oclass->name, prop->name,unitspec);
00551
00552
00553
00554
00555
00556 } CATCH (char *msg) {
00557 output_error("property_malloc(oclass='%s',...): property %s unit '%s' is not recognized",oclass->name, prop->name,unitspec);
00558
00559
00560
00561
00562
00563 } ENDCATCH;
00564 }
00565 }
00566 prop->addr = addr;
00567 prop->delegation = delegation;
00568 prop->next = NULL;
00569
00570
00571 if (oclass!=NULL && class_find_property(oclass,prop->name))
00572 output_warning("property_malloc(oclass='%s',...): property name '%s' is defined more than once", oclass->name, prop->name);
00573
00574
00575
00576
00577 return prop;
00578 Error:
00579 free(prop);
00580 return NULL;
00581 }
00586 CLASS *class_get_class_from_classname(char *name)
00587 {
00588 CLASS *oclass = NULL;
00589 MODULE *mod = NULL;
00590 char *ptr = NULL;
00591 char temp[1024];
00592 strcpy(temp, name);
00593 ptr = strchr(temp, '.');
00594 if(ptr != NULL){
00595 ptr[0] = 0;
00596 ++ptr;
00597 mod = module_find(temp);
00598 if(mod == NULL){
00599 output_verbose("could not search for '%s.%s', module not loaded", name, ptr);
00600 return NULL;
00601 }
00602 for (oclass=first_class; oclass!=NULL; oclass=oclass->next)
00603 {
00604 if(oclass->module == mod)
00605 if(strcmp(oclass->name,ptr)==0)
00606 return oclass;
00607 }
00608 return NULL;
00609 }
00610 for (oclass=first_class; oclass!=NULL; oclass=oclass->next)
00611 {
00612 if (strcmp(oclass->name,name)==0)
00613 return oclass;
00614 }
00615 return NULL;
00616 }
00617
00653 int class_define_map(CLASS *oclass,
00654 ...)
00655 {
00656 va_list arg;
00657 PROPERTYTYPE proptype;
00658 int count=0;
00659 PROPERTY *prop=NULL;
00660 va_start(arg,oclass);
00661 errno = 0;
00662 while ((proptype=va_arg(arg,PROPERTYTYPE))!=0)
00663 {
00664 if (proptype>_PT_LAST)
00665 {
00666 if (proptype==PT_INHERIT)
00667 {
00668 if (oclass->parent!=NULL)
00669 {
00670 errno = EINVAL;
00671 output_error("class_define_map(oclass='%s',...): PT_INHERIT unexpected; class already inherits properties from class %s", oclass->name, oclass->parent);
00672
00673
00674
00675
00676
00677 goto Error;
00678 }
00679 else
00680 {
00681 char *classname = va_arg(arg,char*);
00682 PASSCONFIG no_override;
00683 oclass->parent = class_get_class_from_classname_in_module(classname,oclass->module);
00684 if (oclass->parent==NULL)
00685 {
00686 errno = EINVAL;
00687 output_error("class_define_map(oclass='%s',...): parent property class name '%s' is not defined", oclass->name, classname);
00688
00689
00690
00691
00692
00693
00694
00695
00696 goto Error;
00697 }
00698 if (oclass->parent == oclass){
00699 errno = EINVAL;
00700 output_error("class_define_map(oclass='%s',...): parent property class name '%s' attempting to inherit from self!", oclass->name, classname);
00701
00702
00703
00704
00705 goto Error;
00706 }
00707 no_override = ~(~oclass->parent->passconfig|oclass->passconfig);
00708 if (oclass->parent->passconfig&PC_UNSAFE_OVERRIDE_OMIT
00709 && !(oclass->passconfig&PC_PARENT_OVERRIDE_OMIT)
00710 && no_override&PC_PRETOPDOWN)
00711 output_warning("class_define_map(oclass='%s',...): class '%s' suppresses parent class '%s' PRETOPDOWN sync behavior by omitting override", oclass->name, oclass->name, oclass->parent->name);
00712
00713
00714
00715
00716
00717 if (oclass->parent->passconfig&PC_UNSAFE_OVERRIDE_OMIT
00718 && !(oclass->passconfig&PC_PARENT_OVERRIDE_OMIT)
00719 && no_override&PC_BOTTOMUP)
00720 output_warning("class_define_map(oclass='%s',...): class '%s' suppresses parent class '%s' BOTTOMUP sync behavior by omitting override", oclass->name, oclass->name, oclass->parent->name);
00721
00722
00723
00724
00725
00726 if (oclass->parent->passconfig&PC_UNSAFE_OVERRIDE_OMIT
00727 && !(oclass->passconfig&PC_PARENT_OVERRIDE_OMIT)
00728 && no_override&PC_POSTTOPDOWN)
00729 output_warning("class_define_map(oclass='%s',...): class '%s' suppresses parent class '%s' POSTTOPDOWN sync behavior by omitting override", oclass->name, oclass->name, oclass->parent->name);
00730
00731
00732
00733
00734
00735 if (oclass->parent->passconfig&PC_UNSAFE_OVERRIDE_OMIT
00736 && !(oclass->passconfig&PC_PARENT_OVERRIDE_OMIT)
00737 && no_override&PC_UNSAFE_OVERRIDE_OMIT)
00738 output_warning("class_define_map(oclass='%s',...): class '%s' does not assert UNSAFE_OVERRIDE_OMIT when parent class '%s' does", oclass->name, oclass->name, oclass->parent->name);
00739
00740
00741
00742
00743
00744
00745 count++;
00746 }
00747 }
00748
00749
00750 else if (prop==NULL)
00751 {
00752 errno = EINVAL;
00753 output_error("class_define_map(oclass='%s',...): expected keyword missing after '%s'", oclass->name, class_get_property_typename(proptype));
00754
00755
00756
00757
00758 goto Error;
00759 }
00760 else if (proptype==PT_KEYWORD && prop->ptype==PT_enumeration)
00761 {
00762 char *keyword = va_arg(arg,char*);
00763 long keyvalue = va_arg(arg,long);
00764 if (!class_define_enumeration_member(oclass,prop->name,keyword,keyvalue))
00765 {
00766 errno = EINVAL;
00767 output_error("class_define_map(oclass='%s',...): property keyword '%s' could not be defined as value %d", oclass->name, keyword,keyvalue);
00768
00769
00770
00771
00772
00773 goto Error;
00774 }
00775 }
00776 else if (proptype==PT_KEYWORD && prop->ptype==PT_set)
00777 {
00778 char *keyword = va_arg(arg,char*);
00779 unsigned int64 keyvalue = va_arg(arg, int64);
00780 if (!class_define_set_member(oclass,prop->name,keyword,keyvalue))
00781 {
00782 errno = EINVAL;
00783 output_error("class_define_map(oclass='%s',...): property keyword '%s' could not be defined as value %d", oclass->name, keyword,keyvalue);
00784
00785
00786
00787
00788
00789 goto Error;
00790 }
00791 }
00792 else if (proptype==PT_ACCESS)
00793 {
00794 PROPERTYACCESS pa = va_arg(arg,PROPERTYACCESS);
00795 switch (pa) {
00796 case PA_PUBLIC:
00797 case PA_PROTECTED:
00798 case PA_PRIVATE:
00799 case PA_REFERENCE:
00800 prop->access = pa;
00801 break;
00802 default:
00803 errno = EINVAL;
00804 output_error("class_define_map(oclass='%s',...): unrecognized property access code (value=%d is not valid)", oclass->name, pa);
00805
00806
00807
00808
00809 goto Error;
00810 break;
00811 }
00812 }
00813 else if (proptype==PT_SIZE)
00814 {
00815 prop->size = va_arg(arg,unsigned long);
00816 if (prop->size<1)
00817 {
00818 errno = EINVAL;
00819 output_error("class_define_map(oclass='%s',...): property size must be greater than 0", oclass->name, proptype);
00820
00821
00822
00823
00824 goto Error;
00825 }
00826 }
00827 else if (proptype==PT_EXTEND)
00828 {
00829 oclass->size += property_type[prop->ptype].size;
00830 }
00831 else if (proptype==PT_EXTENDBY)
00832 {
00833 oclass->size += va_arg(arg,unsigned int);
00834 }
00835 else if (proptype==PT_FLAGS)
00836 {
00837 prop->flags |= va_arg(arg,unsigned int);
00838 }
00839 else if (proptype==PT_DEPRECATED)
00840 {
00841 prop->flags |= PF_DEPRECATED;
00842 }
00843 else if (proptype==PT_UNITS)
00844 {
00845 char *unitspec = va_arg(arg,char*);
00846 TRY {
00847 if ((prop->unit = unit_find(unitspec))==NULL)
00848 output_error("class_define_map(oclass='%s',...): property %s unit '%s' is not recognized",oclass->name, prop->name,unitspec);
00849
00850
00851
00852
00853
00854 } CATCH (char *msg) {
00855 output_error("class_define_map(oclass='%s',...): property %s unit '%s' is not recognized",oclass->name, prop->name,unitspec);
00856
00857
00858
00859
00860
00861
00862 } ENDCATCH;
00863 }
00864 else if (proptype==PT_DESCRIPTION)
00865 {
00866 prop->description = va_arg(arg,char*);
00867 }
00868 else
00869 {
00870 char tcode[32];
00871 char *ptypestr=class_get_property_typename(proptype);
00872 sprintf(tcode,"%d",proptype);
00873 if (strcmp(ptypestr,"##UNDEF##")==0)
00874 ptypestr = tcode;
00875 errno = EINVAL;
00876 output_error("class_define_map(oclass='%s',...): unrecognized extended property (PROPERTYTYPE=%s)", oclass->name, ptypestr?ptypestr:tcode);
00877
00878
00879
00880
00881 goto Error;
00882 }
00883 }
00884 else if (proptype==PT_enduse)
00885 {
00886 char *name = va_arg(arg,char*);
00887 PROPERTYADDR addr = va_arg(arg,PROPERTYADDR);
00888 if (enduse_publish(oclass,addr,name)<=0)
00889 {
00890 output_error("class_define_map(oclass='%s',...): substructure of property '%s' substructure could not be published", oclass->name, prop->name);
00891
00892
00893
00894
00895 errno = E2BIG;
00896 goto Error;
00897 }
00898 }
00899 else
00900 {
00901 DELEGATEDTYPE *delegation=(proptype==PT_delegated?va_arg(arg,DELEGATEDTYPE*):NULL);
00902 char *name = va_arg(arg,char*);
00903 PROPERTYADDR addr = va_arg(arg,PROPERTYADDR);
00904 if (prop!=NULL && strlen(name)>=sizeof(prop->name))
00905 {
00906 output_error("class_define_map(oclass='%s',...): property name '%s' is too big", oclass->name, name);
00907
00908
00909
00910
00911
00912 errno = E2BIG;
00913 goto Error;
00914 }
00915 if (strcmp(name,"parent")==0){
00916 output_error("class_define_map(oclass='%s',...): property name '%s' conflicts with built-in property", oclass->name, name);
00917
00918
00919
00920
00921
00922
00923 goto Error;
00924 } else if (strcmp(name,"rank")==0) {
00925 output_error("class_define_map(oclass='%s',...): property name '%s' conflicts with built-in property", oclass->name, name);
00926
00927 goto Error;
00928 } else if (strcmp(name,"clock")==0) {
00929 output_error("class_define_map(oclass='%s',...): property name '%s' conflicts with built-in property", oclass->name, name);
00930
00931 goto Error;
00932 } else if (strcmp(name,"valid_to")==0) {
00933 output_error("class_define_map(oclass='%s',...): property name '%s' conflicts with built-in property", oclass->name, name);
00934
00935 goto Error;
00936 } else if (strcmp(name,"latitude")==0) {
00937 output_error("class_define_map(oclass='%s',...): property name '%s' conflicts with built-in property", oclass->name, name);
00938
00939 goto Error;
00940 } else if (strcmp(name,"longitude")==0) {
00941 output_error("class_define_map(oclass='%s',...): property name '%s' conflicts with built-in property", oclass->name, name);
00942
00943 goto Error;
00944 } else if (strcmp(name,"in_svc")==0) {
00945 output_error("class_define_map(oclass='%s',...): property name '%s' conflicts with built-in property", oclass->name, name);
00946
00947 goto Error;
00948 } else if (strcmp(name,"out_svc")==0) {
00949 output_error("class_define_map(oclass='%s',...): property name '%s' conflicts with built-in property", oclass->name, name);
00950
00951 goto Error;
00952 } else if (strcmp(name,"name")==0) {
00953 output_error("class_define_map(oclass='%s',...): property name '%s' conflicts with built-in property", oclass->name, name);
00954
00955 goto Error;
00956 } else if (strcmp(name,"flags")==0) {
00957 output_error("class_define_map(oclass='%s',...): property name '%s' conflicts with built-in property", oclass->name, name);
00958
00959 goto Error;
00960 }
00961 prop = property_malloc(proptype,oclass,name,addr,delegation);
00962 if (prop==NULL)
00963 goto Error;
00964
00965
00966 class_add_property(oclass,prop);
00967 count++;
00968
00969
00970 if (prop->ptype>_PT_LAST)
00971 prop = NULL;
00972 }
00973 }
00974 va_end(arg);
00975 return count;
00976 Error:
00977 if (prop!=NULL)
00978 output_error("class_define_map(oclass='%s',...): processed up to '%s' before encountering error", oclass->name, prop->name);
00979 return -count;
00980 }
00981
00985 int class_define_enumeration_member(CLASS *oclass,
00986 char *property_name,
00987 char *member,
00988 enumeration value)
00989 {
00990 PROPERTY *prop = class_find_property(oclass,property_name);
00991 KEYWORD *key = (KEYWORD*)malloc(sizeof(KEYWORD));
00992 if (prop==NULL || key==NULL) return 0;
00993 key->next = prop->keywords;
00994 strncpy(key->name,member,sizeof(key->name));
00995 key->value = value;
00996 prop->keywords = key;
00997 return 1;
00998 }
00999
01002 int class_define_set_member(CLASS *oclass,
01003 char *property_name,
01004 char *member,
01005 unsigned int64 value)
01006 {
01007 PROPERTY *prop = class_find_property(oclass,property_name);
01008 KEYWORD *key = (KEYWORD*)malloc(sizeof(KEYWORD));
01009 if (prop==NULL || key==NULL) return 0;
01010 if (prop->keywords==NULL)
01011 prop->flags |= PF_CHARSET;
01012 key->next = prop->keywords;
01013 strncpy(key->name,member,sizeof(key->name));
01014 key->name[sizeof(key->name)-1]='\0';
01015 if (strlen(key->name)>1 && (prop->flags&PF_CHARSET))
01016 prop->flags ^= PF_CHARSET;
01017 key->value = value;
01018 prop->keywords = key;
01019 return 1;
01020 }
01021
01025 FUNCTION *class_define_function(CLASS *oclass, FUNCTIONNAME functionname, FUNCTIONADDR call)
01026 {
01027 FUNCTION *func;
01028 if (class_get_function(oclass->name,functionname)!=NULL)
01029 {
01030 output_error("class_define_function(CLASS *class={name='%s',...}, FUNCTIONNAME functionname='%s', ...) the function name has already been defined", oclass->name, functionname);
01031
01032
01033
01034
01035
01036 errno = 0;
01037 return NULL;
01038 }
01039
01040 func = (FUNCTION*)malloc(sizeof(FUNCTION));
01041 if (func==NULL)
01042 {
01043 errno = ENOMEM;
01044 return NULL;
01045 }
01046 func->addr = call;
01047 strcpy(func->name,functionname);
01048 func->next = NULL;
01049 func->oclass = oclass;
01050 if (oclass->fmap==NULL)
01051 oclass->fmap = func;
01052 else
01053 oclass->fmap->next = func;
01054 return func;
01055 }
01056
01057
01058
01059 FUNCTIONADDR class_get_function(char *classname, char *functionname)
01060 {
01061 CLASS *oclass = class_get_class_from_classname(classname);
01062 FUNCTION *func;
01063 for (func=oclass->fmap; func!=NULL && func->oclass==oclass; func=func->next)
01064 {
01065 if (strcmp(functionname,func->name)==0)
01066 return func->addr;
01067 }
01068 errno = ENOENT;
01069 return NULL;
01070 }
01071
01075 int class_saveall(FILE *fp)
01076 {
01077 unsigned count=0;
01078 count += fprintf(fp,"\n########################################################\n");
01079 count += fprintf(fp,"# classes\n");
01080 { CLASS *oclass;
01081 for (oclass=class_get_first_class(); oclass!=NULL; oclass=oclass->next)
01082 {
01083 PROPERTY *prop;
01084 FUNCTION *func;
01085 count += fprintf(fp,"class %s {\n",oclass->name);
01086 if (oclass->parent)
01087 count += fprintf(fp,"\tparent %s;\n", oclass->parent->name);
01088 for (func=oclass->fmap; func!=NULL && func->oclass==oclass; func=func->next)
01089 count += fprintf(fp, "\tfunction %s();\n", func->name);
01090 for (prop=oclass->pmap; prop!=NULL && prop->oclass==oclass; prop=prop->next)
01091 {
01092 char *propname = class_get_property_typename(prop->ptype);
01093 if (propname!=NULL)
01094 count += fprintf(fp,"\t%s %s;\n", propname, prop->name);
01095 }
01096 count += fprintf(fp,"}\n");
01097 }
01098 }
01099 return count;
01100 }
01101
01105 int class_saveall_xml(FILE *fp)
01106 {
01107 unsigned count=0;
01108 count += fprintf(fp,"\t<classes>\n");
01109 { CLASS *oclass;
01110 for (oclass=class_get_first_class(); oclass!=NULL; oclass=oclass->next)
01111 {
01112 PROPERTY *prop;
01113 FUNCTION *func;
01114 count += fprintf(fp,"\t\t<class name=\"%s\">\n",oclass->name);
01115 if (oclass->parent)
01116 count += fprintf(fp,"\t\t<parent>%s</parent>\n", oclass->parent->name);
01117 for (func=oclass->fmap; func!=NULL && func->oclass==oclass; func=func->next)
01118 count += fprintf(fp, "\t\t<function>%s</function>\n", func->name);
01119 for (prop=oclass->pmap; prop!=NULL && prop->oclass==oclass; prop=prop->next)
01120 {
01121 char *propname = class_get_property_typename(prop->ptype);
01122 if (propname!=NULL)
01123 count += fprintf(fp,"\t\t\t<property type=\"%s\">%s</property>\n", propname, prop->name);
01124 }
01125 count += fprintf(fp,"\t\t</class>\n");
01126 }
01127 }
01128 count += fprintf(fp,"\t</classes>\n");
01129 return count;
01130 }
01131
01134 void class_profiles(void)
01135 {
01136 CLASS *cl;
01137 int64 total=0;
01138 int count=0, i=0, hits;
01139 CLASS **index;
01140 output_profile("Model profiler results");
01141 output_profile("======================\n");
01142 output_profile("Class Time (s) Time (%%) msec/obj");
01143 output_profile("---------------- -------- -------- --------");
01144 for (cl=first_class; cl!=NULL; cl=cl->next)
01145 {
01146 total+=cl->profiler.clocks;
01147 count++;
01148 }
01149 index = (CLASS**)malloc(sizeof(CLASS*)*count);
01150 for (cl=first_class; cl!=NULL; cl=cl->next)
01151 index[i++]=cl;
01152 hits=-1;
01153 while (hits!=0)
01154 {
01155 hits=0;
01156 for (i=0; i<count-1; i++)
01157 {
01158 if (index[i]->profiler.clocks<index[i+1]->profiler.clocks)
01159 {
01160 CLASS *tmp = index[i];
01161 index[i]=index[i+1];
01162 index[i+1]=tmp;
01163 hits++;
01164 }
01165 }
01166 }
01167 for (i=0; i<count; i++)
01168 {
01169 cl = index[i];
01170 if (cl->profiler.clocks>0)
01171 {
01172 double ts = (double)cl->profiler.clocks/CLOCKS_PER_SEC;
01173 double tp = (double)cl->profiler.clocks/total*100;
01174 double mt = ts/cl->profiler.numobjs*1000;
01175 output_profile("%-16.16s %7.3f %8.1f%% %8.1f", cl->name, ts,tp,mt);
01176 }
01177 else
01178 break;
01179 }
01180 free(index);
01181 output_profile("================ ======== ======== ========");
01182 output_profile("%-16.16s %7.3f %8.1f%% %8.1f\n",
01183 "Total", (double)total/CLOCKS_PER_SEC,100.0,1000*(double)total/CLOCKS_PER_SEC/object_get_count());
01184
01185 }
01186
01194 DELEGATEDTYPE *class_register_type(CLASS *oclass,
01195 char *type,
01196 int (*from_string)(void*,char*),
01197 int (*to_string)(void*,char*,int))
01198 {
01199 DELEGATEDTYPE *dt = (DELEGATEDTYPE*)malloc(sizeof(DELEGATEDTYPE));
01200 if (dt!=NULL)
01201 {
01202 dt->oclass = oclass;
01203 strncpy(dt->type,type,sizeof(dt->type));
01204 dt->from_string = from_string;
01205 dt->to_string = to_string;
01206 }
01207 else
01208 output_error("unable to register delegated type (memory allocation failed)");
01209
01210
01211
01212
01213 return dt;
01214 }
01215
01216
01217 int class_define_type(CLASS *oclass, DELEGATEDTYPE *delegation, ...)
01218 {
01219 output_error("delegated types not supported using class_define_type (use class_define_map instead)");
01220
01221
01222
01223
01224 return 0;
01225 }
01226
01227 static int check = 0;
01228
01232 static int buffer_write(char *buffer, size_t len, char *format, ...){
01233 char temp[1025];
01234 unsigned int count = 0;
01235 va_list ptr;
01236
01237 if(buffer == NULL)
01238 return 0;
01239 if(len < 1)
01240 return 0;
01241 if(check == 0)
01242 return 0;
01243
01244 va_start(ptr,format);
01245 count = vsprintf(temp, format, ptr);
01246 va_end(ptr);
01247
01248 if(count < len){
01249 strncpy(buffer, temp, count);
01250 return count;
01251 } else {
01252 check = 0;
01253 return 0;
01254 }
01255 }
01256
01260 int class_get_xsd(CLASS *oclass,
01261 char *buffer,
01262 size_t len)
01263 {
01264 size_t n=0;
01265 PROPERTY *prop;
01266 int i;
01267 extern KEYWORD oflags[];
01268 struct {
01269 char *name;
01270 char *type;
01271 KEYWORD *keys;
01272 } attribute[]={
01273 {"id", "int64",NULL},
01274 {"parent", "object",NULL},
01275 {"rank", "int32",NULL},
01276 {"clock", "datetime",NULL},
01277 {"valid_to", "datetime",NULL},
01278 {"latitude", "latitude",NULL},
01279 {"longitude", "longitude",NULL},
01280 {"in_svc", "datetime",NULL},
01281 {"out_svc", "datetime",NULL},
01282 {"flags", "set",oflags},
01283 };
01284 check = 1;
01285 n += buffer_write(buffer+n, len-n, "<xs:element name=\"%s\">\n", oclass->name);
01286 n += buffer_write(buffer+n, len-n, "\t<xs:complexType>\n");
01287 n += buffer_write(buffer+n, len-n, "\t\t<xs:all>\n");
01288 for (i=0; i < sizeof(attribute) / sizeof(attribute[0]); i++)
01289 {
01290 n += buffer_write(buffer+n, len-n, "\t\t\t<xs:element name=\"%s\">\n", attribute[i].name);
01291 n += buffer_write(buffer+n, len-n, "\t\t\t\t<xs:simpleType>\n");
01292 if (attribute[i].keys==NULL){
01293 n += buffer_write(buffer+n, len-n, "\t\t\t\t\t<xs:restriction base=\"xs:%s\"/>\n", attribute[i].type);
01294 }
01295 else
01296 {
01297 KEYWORD *key;
01298 n += buffer_write(buffer+n, len-n, "\t\t\t\t\t<xs:restriction base=\"xs:string\">\n");
01299 n += buffer_write(buffer+n, len-n, "\t\t\t\t\t\t<xs:pattern value=\"");
01300 for (key=attribute[i].keys; key!=NULL; key=key->next){
01301 n += buffer_write(buffer+n, len-n, "%s%s", key==attribute[i].keys?"":"|", key->name);
01302 }
01303 n += buffer_write(buffer+n, len-n, "\"/>\n");
01304 n += buffer_write(buffer+n, len-n, "\t\t\t\t\t</xs:restriction>\n");
01305 }
01306 n += buffer_write(buffer+n, len-n, "\t\t\t\t</xs:simpleType>\n");
01307 n += buffer_write(buffer+n, len-n, "\t\t\t</xs:element>\n");
01308 }
01309 for (prop=oclass->pmap; prop!=NULL && prop->oclass==oclass; prop=prop->next)
01310 {
01311 char *proptype=class_get_property_typename(prop->ptype);
01312 if (prop->unit!=NULL){
01313 n += buffer_write(buffer+n, len-n, "\t\t\t\t<xs:element name=\"%s\" type=\"xs:string\"/>\n", prop->name);
01314 } else {
01315 n += buffer_write(buffer+n, len-n, "\t\t\t<xs:element name=\"%s\">\n", prop->name);
01316 n += buffer_write(buffer+n, len-n, "\t\t\t\t<xs:simpleType>\n");
01317 n += buffer_write(buffer+n, len-n, "\t\t\t\t\t<xs:restriction base=\"xs:%s\">\n", proptype==NULL?"string":proptype);
01318 if (prop->keywords!=NULL)
01319 {
01320 KEYWORD *key;
01321 n += buffer_write(buffer+n, len-n, "\t\t\t\t\t<xs:pattern value=\"");
01322 for (key=prop->keywords; key!=NULL; key=key->next){
01323 n += buffer_write(buffer+n, len-n, "%s%s", key==prop->keywords?"":"|", key->name);
01324 }
01325 n += buffer_write(buffer+n, len-n, "\"/>\n");
01326 }
01327 n += buffer_write(buffer+n, len-n, "\t\t\t\t\t</xs:restriction>\n");
01328 n += buffer_write(buffer+n, len-n, "\t\t\t\t</xs:simpleType>\n");
01329 n += buffer_write(buffer+n, len-n, "\t\t\t</xs:element>\n");
01330 }
01331 }
01332 n += buffer_write(buffer+n, len-n, "\t\t</xs:all>\n");
01333 n += buffer_write(buffer+n, len-n, "\t</xs:complexType>\n");
01334 n += buffer_write(buffer+n, len-n, "</xs:element>\n");
01335 buffer[n] = 0;
01336 if(check == 0){
01337 printf("class_get_xsd() overflowed.\n");
01338 buffer[0] = 0;
01339 return 0;
01340 }
01341 return (int)n;
01342 }
01343
01344