00001
00046 #include "class.h"
00047 #include "output.h"
00048 #include "convert.h"
00049 #include "module.h"
00050 #include "exception.h"
00051 #include "timestamp.h"
00052
00053
00054 static struct s_property_specs {
00058 char *name;
00059 unsigned int size;
00060 int (*data_to_string)(char *,int,void*,PROPERTY*);
00061 int (*string_to_data)(char *,void*,PROPERTY*);
00062 } property_type[] = {
00063 {"void", 0, convert_from_void,convert_to_void},
00064 {"double", sizeof(double), convert_from_double,convert_to_double},
00065 {"complex", sizeof(complex), convert_from_complex,convert_to_complex},
00066 {"enumeration",sizeof(long), convert_from_enumeration,convert_to_enumeration},
00067 {"set",sizeof(int64), convert_from_set,convert_to_set},
00068 {"int16", sizeof(int16), convert_from_int16,convert_to_int16},
00069 {"int32", sizeof(int32), convert_from_int32,convert_to_int32},
00070 {"int64", sizeof(int64), convert_from_int64,convert_to_int64},
00071 {"char8", sizeof(char8), convert_from_char8,convert_to_char8},
00072 {"char32", sizeof(char32), convert_from_char32,convert_to_char32},
00073 {"char256", sizeof(char256), convert_from_char256,convert_to_char256},
00074 {"char1024", sizeof(char1024), convert_from_char1024,convert_to_char1024},
00075 {"object", sizeof(OBJECT*), convert_from_object,convert_to_object},
00076 {"delegated", -1, convert_from_delegated, convert_to_delegated},
00077 {"bool", sizeof(unsigned int), convert_from_boolean, convert_to_boolean},
00078 {"timestamp", sizeof(int64), convert_from_timestamp_stub, convert_to_timestamp_stub},
00079 {"double_array", sizeof(double), convert_from_double_array, convert_to_double_array},
00080 {"complex_array", sizeof(complex), convert_from_complex_array, convert_to_complex_array},
00081 };
00082
00083
00084 PROPERTY *first_property = NULL;
00085 PROPERTY *last_property = NULL;
00086
00087
00088 OBJECTTYPE last_object_type = 0;
00089 static CLASS *first_class = NULL;
00090 static CLASS *last_class = NULL;
00091
00111 PROPERTY *class_get_first_property(CLASS *oclass)
00112 {
00113 if (oclass==NULL)
00114 return first_property;
00115 else
00116 return oclass->pmap;
00117 }
00118
00122 PROPERTY *class_get_next_property(PROPERTY *prop)
00123 {
00124 if (prop->next!=NULL && prop->otype==prop->next->otype)
00125 return prop->next;
00126 else
00127 return NULL;
00128 }
00129
00133 unsigned long property_size(PROPERTY *prop)
00134 {
00135 if (prop && prop->ptype>_PT_FIRST && prop->ptype<_PT_LAST)
00136 return property_type[prop->ptype].size;
00137 else
00138 return 0;
00139 }
00144 PROPERTY *class_find_property(CLASS *oclass,
00145 PROPERTYNAME name)
00146 {
00147 PROPERTY *prop;
00148 for (prop=oclass->pmap; prop!=NULL && prop->otype==oclass->type; prop=prop->next)
00149 {
00150 if (strcmp(name,prop->name)==0)
00151 return prop;
00152 }
00153 return NULL;
00154 }
00155
00159 CLASS *class_get_last_class(void)
00160 {
00161 return last_class;
00162 }
00163
00167 unsigned int class_get_count(void)
00168 {
00169 return last_object_type;
00170 }
00171
00175 char *class_get_property_typename(PROPERTYTYPE type)
00176 {
00177 if (type<=_PT_FIRST || type>=_PT_LAST)
00178 return "##UNDEF##";
00179 else
00180 return property_type[type].name;
00181 }
00182
00186 PROPERTYTYPE class_get_propertytype_from_typename(char *name)
00187 {
00188 int i;
00189 for (i=0; i<sizeof(property_type)/sizeof(property_type[0]); i++)
00190 {
00191 if (strcmp(property_type[i].name,name)==0)
00192 return i;
00193 }
00194 return PT_void;
00195 }
00196
00201 int class_string_to_property(PROPERTY *prop,
00202 void *addr,
00203 char *value)
00204 {
00205 if (prop->ptype==PT_delegated)
00206 {
00207 output_error("unable to convert to delegated property value");
00208 return 0;
00209 }
00210 else if (prop->ptype > _PT_FIRST && prop->ptype < _PT_LAST)
00211 return (*property_type[prop->ptype].string_to_data)(value,addr,prop);
00212 else
00213 return 0;
00214 }
00215
00220 int class_property_to_string(PROPERTY *prop,
00221 void *addr,
00222 char *value,
00223 int size)
00224 {
00225 if (prop->ptype==PT_delegated)
00226 {
00227 output_error("unable to convert from delegated property value");
00228 return 0;
00229 }
00230 else if (prop->ptype>_PT_FIRST && prop->ptype<_PT_LAST)
00231 return (*property_type[prop->ptype].data_to_string)(value,size,addr,prop);
00232 else
00233 return 0;
00234 }
00235
00236
00243 CLASS *class_register(MODULE *module,
00244 CLASSNAME name,
00245 PASSCONFIG passconfig)
00246 {
00247 CLASS *oclass = class_get_class_from_classname(name);
00248 MODULE *mod = NULL;
00249
00250
00251 int a = sizeof(property_type);
00252 int b = sizeof(property_type[0]);
00253 int c = _PT_LAST - _PT_FIRST - 1;
00254
00255 if (_PT_LAST-_PT_FIRST-1!=sizeof(property_type)/sizeof(property_type[0]))
00256 {
00257 output_fatal("property_type[] in class.c has an incorrect number of members");
00258 exit(1);
00259 }
00260 if (oclass!=NULL)
00261 {
00262 if(strcmp(oclass->module->name, module->name) == 0){
00263 output_error("module %s cannot register class %s, it is already registered by module %s", module->name,name,oclass->module->name);
00264 return NULL;
00265 } else {
00266 output_verbose("module %s is registering a 2nd class %s, previous one in module %s", module->name, name, oclass->module->name);
00267 }
00268 }
00269 if (strlen(name)>=sizeof(oclass->name) )
00270 {
00271 errno = E2BIG;
00272 return 0;
00273 }
00274 oclass = (CLASS*)malloc(sizeof(CLASS));
00275 if (oclass==NULL)
00276 {
00277 errno = ENOMEM;
00278 return 0;
00279 }
00280 oclass->module = module;
00281 oclass->type = ++last_object_type;
00282 strncpy(oclass->name,name,sizeof(oclass->name));
00283 oclass->next = NULL;
00284 oclass->pmap = NULL;
00285 oclass->fmap = NULL;
00286 oclass->sync = NULL;
00287 oclass->create = NULL;
00288 oclass->passconfig = passconfig;
00289 oclass->profiler.numobjs=0;
00290 oclass->profiler.count=0;
00291 oclass->profiler.clocks=0;
00292 if (first_class==NULL)
00293 first_class = oclass;
00294 else
00295 last_class->next = oclass;
00296 last_class = oclass;
00297 output_verbose("class %s registered ok", name);
00298 return oclass;
00299 }
00300
00305 CLASS *class_get_first_class(void)
00306 {
00307 return first_class;
00308 }
00309
00314 CLASS *class_get_class_from_objecttype(OBJECTTYPE type)
00315 {
00316 CLASS *oclass;
00317 for (oclass=first_class; oclass!=NULL; oclass=oclass->next)
00318 {
00319 if (oclass->type==type)
00320 return oclass;
00321 }
00322 return NULL;
00323 }
00324
00328 char *class_get_classname_from_objecttype(OBJECTTYPE type)
00329 {
00330 CLASS *oclass;
00331 for (oclass=first_class; oclass!=NULL; oclass=oclass->next)
00332 {
00333 if (oclass->type==type)
00334 return oclass->name;
00335 }
00336 return NULL;
00337 }
00338
00343 CLASS *class_get_class_from_classname_in_module(char *name, MODULE *mod){
00344 CLASS *oclass = NULL;
00345 if(name == NULL) return NULL;
00346 if(mod == NULL) return NULL;
00347 for (oclass=first_class; oclass!=NULL; oclass=oclass->next)
00348 {
00349 if(oclass->module == (MODULE *)mod)
00350 if(strcmp(oclass->name,name)==0)
00351 return oclass;
00352 }
00353 return NULL;
00354 }
00355
00360 CLASS *class_get_class_from_classname(char *name)
00361 {
00362 CLASS *oclass = NULL;
00363 MODULE *mod = NULL;
00364 char *ptr = NULL;
00365 char temp[1024];
00366 strcpy(temp, name);
00367 ptr = strchr(temp, '.');
00368 if(ptr != NULL){
00369 ptr[0] = 0;
00370 ++ptr;
00371 mod = module_find(temp);
00372 if(mod == NULL){
00373 output_verbose("could not search for '%s.%s', module not loaded", name, ptr);
00374 return NULL;
00375 }
00376 for (oclass=first_class; oclass!=NULL; oclass=oclass->next)
00377 {
00378 if(oclass->module == mod)
00379 if(strcmp(oclass->name,ptr)==0)
00380 return oclass;
00381 }
00382 return NULL;
00383 }
00384 for (oclass=first_class; oclass!=NULL; oclass=oclass->next)
00385 {
00386 if (strcmp(oclass->name,name)==0)
00387 return oclass;
00388 }
00389 return NULL;
00390 }
00391
00395 OBJECTTYPE class_get_classtype_from_classname(char *name)
00396 {
00397 CLASS *oclass;
00398 for (oclass=first_class; oclass!=NULL; oclass=oclass->next)
00399 {
00400 if (strcmp(oclass->name,name)==0)
00401 return oclass->type;
00402 }
00403 return 0;
00404 }
00405
00432 int class_define_map(CLASS *oclass,
00433 ...)
00434 {
00435 va_list arg;
00436 PROPERTYTYPE proptype;
00437 int count=0;
00438 PROPERTY *prop=NULL;
00439 va_start(arg,oclass);
00440 while ((proptype=va_arg(arg,PROPERTYTYPE))!=0)
00441 {
00442 if (proptype>_PT_LAST)
00443 {
00444 if (prop==NULL)
00445 {
00446 errno = EINVAL;
00447 output_error("class_map_define(): expected keyword missing after '%s'", class_get_property_typename(proptype));
00448 goto Error;
00449 }
00450 else if (proptype==PT_KEYWORD && prop->ptype==PT_enumeration)
00451 {
00452 char *keyword = va_arg(arg,char*);
00453 long keyvalue = va_arg(arg,long);
00454 if (!class_define_enumeration_member(oclass,prop->name,keyword,keyvalue))
00455 {
00456 errno = EINVAL;
00457 output_error("class_map_define(): property keyword '%s' could not be defined as value %d", keyword,keyvalue);
00458 goto Error;
00459 }
00460 }
00461 else if (proptype==PT_KEYWORD && prop->ptype==PT_set)
00462 {
00463 char *keyword = va_arg(arg,char*);
00464 unsigned long keyvalue = va_arg(arg, int);
00465 if (!class_define_set_member(oclass,prop->name,keyword,keyvalue))
00466 {
00467 errno = EINVAL;
00468 output_error("class_map_define(): property keyword '%s' could not be defined as value %d", keyword,keyvalue);
00469 goto Error;
00470 }
00471 }
00472 else if (proptype==PT_ACCESS)
00473 {
00474 PROPERTYACCESS pa = va_arg(arg,PROPERTYACCESS);
00475 switch (pa) {
00476 case PA_PUBLIC:
00477 case PA_PROTECTED:
00478 case PA_PRIVATE:
00479 case PA_REFERENCE:
00480 prop->access = pa;
00481 break;
00482 default:
00483 errno = EINVAL;
00484 output_error("class_map_define(): unrecognized property access code (value=%d is not valid)", pa);
00485 goto Error;
00486 break;
00487 }
00488 }
00489 else if (proptype==PT_SIZE)
00490 {
00491 prop->size = va_arg(arg,unsigned long);
00492 if (prop->size<1)
00493 {
00494 errno = EINVAL;
00495 output_error("class_map_define(): property size must be greater than 0", proptype);
00496 goto Error;
00497 }
00498 }
00499 else if (proptype==PT_FLAGS)
00500 {
00501 prop->flags = va_arg(arg,unsigned int);
00502 }
00503 else
00504 {
00505 char tcode[32];
00506 char *ptypestr=class_get_property_typename(proptype);
00507 sprintf(tcode,"%d",proptype);
00508 if (strcmp(ptypestr,"##UNDEF##")==0)
00509 ptypestr = tcode;
00510 errno = EINVAL;
00511 output_error("class_map_define(): unrecognized extended property (PROPERTYTYPE=%s)", ptypestr?ptypestr:tcode);
00512 goto Error;
00513 }
00514 }
00515
00516 else
00517 {
00518 DELEGATEDTYPE *delegation=(proptype==PT_delegated?va_arg(arg,DELEGATEDTYPE*):NULL);
00519 char *name = va_arg(arg,char*);
00520 PROPERTYADDR addr = va_arg(arg,PROPERTYADDR);
00521 char unitspec[1024];
00522 if (strlen(name)>=sizeof(prop->name))
00523 {
00524 output_error("class_map_define(): property name '%s' is too big", prop->name);
00525 errno = E2BIG;
00526 goto Error;
00527 }
00528 prop = (PROPERTY*)malloc(sizeof(PROPERTY));
00529 if (prop==NULL)
00530 {
00531 output_error("class_map_define(): memory allocation failed", prop->name);
00532 errno = ENOMEM;
00533 goto Error;
00534 }
00535 prop->ptype = proptype;
00536 prop->size = 0;
00537 prop->access = PA_PUBLIC;
00538 prop->otype = oclass->type;
00539 prop->flags = 0;
00540 prop->keywords = NULL;
00541 if (sscanf(name,"%[^[][%[A-Za-z0-9*/^]]",prop->name,unitspec)==2)
00542 {
00543 prop->unit = unit_find(unitspec);
00544 if (prop->unit==NULL)
00545 output_warning("property %s unit '%s' is not recognized",prop->name,unitspec);
00546 }
00547 else
00548 prop->unit = NULL;
00549 prop->addr = addr;
00550 prop->delegation = delegation;
00551 prop->next = NULL;
00552 if (first_property==NULL)
00553 first_property = prop;
00554 else
00555 last_property->next = prop;
00556 last_property = prop;
00557
00558
00559 if (oclass->pmap==NULL)
00560 oclass->pmap = prop;
00561 count++;
00562
00563
00564 if (prop->ptype>_PT_LAST)
00565 prop = NULL;
00566 }
00567 }
00568 va_end(arg);
00569 return count;
00570 Error:
00571 if (prop!=NULL)
00572 output_verbose("class_define_map() processed up to property %s", prop->name);
00573 return -count;
00574 }
00575
00579 int class_define_enumeration_member(CLASS *oclass,
00580 char *property_name,
00581 char *member,
00582 enumeration value)
00583 {
00584 PROPERTY *prop = class_find_property(oclass,property_name);
00585 KEYWORD *key = (KEYWORD*)malloc(sizeof(KEYWORD));
00586 if (prop==NULL || key==NULL) return 0;
00587 key->next = prop->keywords;
00588 strncpy(key->name,member,sizeof(key->name));
00589 key->value = value;
00590 prop->keywords = key;
00591 return 1;
00592 }
00593
00596 int class_define_set_member(CLASS *oclass,
00597 char *property_name,
00598 char *member,
00599 unsigned long value)
00600 {
00601 PROPERTY *prop = class_find_property(oclass,property_name);
00602 KEYWORD *key = (KEYWORD*)malloc(sizeof(KEYWORD));
00603 if (prop==NULL || key==NULL) return 0;
00604 if (prop->keywords==NULL)
00605 prop->flags |= PF_CHARSET;
00606 key->next = prop->keywords;
00607 strncpy(key->name,member,sizeof(key->name));
00608 key->name[sizeof(key->name)-1]='\0';
00609 if (strlen(key->name)>1 && (prop->flags&PF_CHARSET))
00610 prop->flags ^= PF_CHARSET;
00611 key->value = value;
00612 prop->keywords = key;
00613 return 1;
00614 }
00615
00616
00617
00618 FUNCTION *class_define_function(CLASS *oclass, FUNCTIONNAME functionname, FUNCTIONADDR call)
00619 {
00620 FUNCTION *func = (FUNCTION*)malloc(sizeof(FUNCTION));
00621 if (func==NULL)
00622 {
00623 errno = ENOMEM;
00624 return NULL;
00625 }
00626 func->addr = call;
00627 strcpy(func->name,functionname);
00628 func->next = NULL;
00629 func->otype = oclass->type;
00630 if (oclass->fmap==NULL)
00631 oclass->fmap = func;
00632 else
00633 oclass->fmap->next = func;
00634 return func;
00635 }
00636
00637
00638
00639 FUNCTIONADDR class_get_function(char *classname, char *functionname)
00640 {
00641 CLASS *oclass = class_get_class_from_classname(classname);
00642 FUNCTION *func;
00643 for (func=oclass->fmap; func!=NULL && func->otype==oclass->type; func=func->next)
00644 {
00645 if (strcmp(functionname,func->name)==0)
00646 return func->addr;
00647 }
00648 errno = ENOENT;
00649 return NULL;
00650 }
00651
00655 int class_saveall(FILE *fp)
00656 {
00657 unsigned count=0;
00658 count += fprintf(fp,"\n########################################################\n");
00659 count += fprintf(fp,"# classes\n");
00660 { CLASS *oclass;
00661 for (oclass=class_get_first_class(); oclass!=NULL; oclass=oclass->next)
00662 {
00663 PROPERTY *prop;
00664 FUNCTION *func;
00665 count += fprintf(fp,"class %s {\n",oclass->name,oclass->type);
00666 for (func=oclass->fmap; func!=NULL && func->otype==oclass->type; func=func->next)
00667 count += fprintf(fp, "\tfunction %s();\n", func->name);
00668 for (prop=oclass->pmap; prop!=NULL && prop->otype==oclass->type; prop=prop->next)
00669 {
00670 char *propname = class_get_property_typename(prop->ptype);
00671 if (propname!=NULL)
00672 count += fprintf(fp,"\t%s %s;\n", propname, prop->name);
00673 }
00674 count += fprintf(fp,"}\n");
00675 }
00676 }
00677 return count;
00678 }
00679
00683 int class_saveall_xml(FILE *fp)
00684 {
00685 unsigned count=0;
00686 count += fprintf(fp,"\t<classes>\n");
00687 { CLASS *oclass;
00688 for (oclass=class_get_first_class(); oclass!=NULL; oclass=oclass->next)
00689 {
00690 PROPERTY *prop;
00691 FUNCTION *func;
00692 count += fprintf(fp,"\t\t<class name=\"%s\">\n",oclass->name,oclass->type);
00693 for (func=oclass->fmap; func!=NULL && func->otype==oclass->type; func=func->next)
00694 count += fprintf(fp, "\t\t<function>%s</function>\n", func->name);
00695 for (prop=oclass->pmap; prop!=NULL && prop->otype==oclass->type; prop=prop->next)
00696 {
00697 char *propname = class_get_property_typename(prop->ptype);
00698 if (propname!=NULL)
00699 count += fprintf(fp,"\t\t\t<property type=\"%s\">%s</property>\n", propname, prop->name);
00700 }
00701 count += fprintf(fp,"\t\t</class>\n");
00702 }
00703 }
00704 count += fprintf(fp,"\t</classes>\n");
00705 return count;
00706 }
00707
00710 void class_profiles(void)
00711 {
00712 CLASS *cl;
00713 int64 total=0;
00714 int count=0, i=0, hits;
00715 CLASS **index;
00716 output_profile("Model profiler results");
00717 output_profile("======================\n");
00718 output_profile("Class Time (s) Time (%%) msec/obj");
00719 output_profile("---------------- -------- -------- --------");
00720 for (cl=first_class; cl!=NULL; cl=cl->next)
00721 {
00722 total+=cl->profiler.clocks;
00723 count++;
00724 }
00725 index = (CLASS**)malloc(sizeof(CLASS*)*count);
00726 for (cl=first_class; cl!=NULL; cl=cl->next)
00727 index[i++]=cl;
00728 hits=-1;
00729 while (hits!=0)
00730 {
00731 hits=0;
00732 for (i=0; i<count-1; i++)
00733 {
00734 if (index[i]->profiler.clocks<index[i+1]->profiler.clocks)
00735 {
00736 CLASS *tmp = index[i];
00737 index[i]=index[i+1];
00738 index[i+1]=tmp;
00739 hits++;
00740 }
00741 }
00742 }
00743 for (i=0; i<count; i++)
00744 {
00745 cl = index[i];
00746 if (cl->profiler.clocks>0)
00747 {
00748 double ts = (double)cl->profiler.clocks/CLOCKS_PER_SEC;
00749 double tp = (double)cl->profiler.clocks/total*100;
00750 double mt = ts/cl->profiler.numobjs*1000;
00751 output_profile("%-16.16s %7.3f %8.1f%% %8.1f", cl->name, ts,tp,mt);
00752 }
00753 else
00754 break;
00755 }
00756 free(index);
00757 output_profile("================ ======== ======== ========");
00758 output_profile("%-16.16s %7.3f %8.1f%% %8.1f\n",
00759 "Total", (double)total/CLOCKS_PER_SEC,100.0,1000*(double)total/CLOCKS_PER_SEC/object_get_count());
00760
00761 }
00762
00770 DELEGATEDTYPE *class_register_type(CLASS *oclass,
00771 char *type,
00772 int (*from_string)(void*,char*),
00773 int (*to_string)(void*,char*,int))
00774 {
00775 DELEGATEDTYPE *dt = (DELEGATEDTYPE*)malloc(sizeof(DELEGATEDTYPE));
00776 if (dt!=NULL)
00777 {
00778 dt->oclass = oclass;
00779 strncpy(dt->type,type,sizeof(dt->type));
00780 dt->from_string = from_string;
00781 dt->to_string = to_string;
00782 }
00783 else
00784 output_error("unable to register delegated type (memory allocation failed)");
00785 return dt;
00786 }
00787
00788
00789 int class_define_type(CLASS *oclass, DELEGATEDTYPE *delegation, ...)
00790 {
00791 output_error("delegated types not supported using class_define_type (use class_define_map instead)");
00792 return 0;
00793 }
00794
00795 static int check = 0;
00796
00800 static int buffer_write(char *buffer, size_t len, char *format, ...){
00801 char temp[1025];
00802 unsigned int count = 0;
00803 va_list ptr;
00804
00805 if(buffer == NULL)
00806 return 0;
00807 if(len < 1)
00808 return 0;
00809 if(check == 0)
00810 return 0;
00811
00812 va_start(ptr,format);
00813 count = vsprintf(temp, format, ptr);
00814 va_end(ptr);
00815
00816 if(count < len){
00817 strncpy(buffer, temp, count);
00818 return count;
00819 } else {
00820 check = 0;
00821 return 0;
00822 }
00823 }
00824
00828 int class_get_xsd(CLASS *oclass,
00829 char *buffer,
00830 size_t len)
00831 {
00832 size_t n=0;
00833 PROPERTY *prop;
00834 int i;
00835 extern KEYWORD oflags[];
00836 struct {
00837 char *name;
00838 char *type;
00839 KEYWORD *keys;
00840 } attribute[]={
00841 {"id", "int64",NULL},
00842 {"parent", "object",NULL},
00843 {"rank", "int32",NULL},
00844 {"clock", "datetime",NULL},
00845 {"latitude", "latitude",NULL},
00846 {"longitude", "longitude",NULL},
00847 {"in_svc", "datetime",NULL},
00848 {"out_svc", "datetime",NULL},
00849 {"flags", "set",oflags},
00850 };
00851 check = 1;
00852 n += buffer_write(buffer+n, len-n, "<xs:element name=\"%s\">\n", oclass->name);
00853 n += buffer_write(buffer+n, len-n, "\t<xs:complexType>\n");
00854 n += buffer_write(buffer+n, len-n, "\t\t<xs:all>\n");
00855 for (i=0; i < sizeof(attribute) / sizeof(attribute[0]); i++)
00856 {
00857 n += buffer_write(buffer+n, len-n, "\t\t\t<xs:element name=\"%s\">\n", attribute[i].name);
00858 n += buffer_write(buffer+n, len-n, "\t\t\t\t<xs:simpleType>\n");
00859 if (attribute[i].keys==NULL){
00860 n += buffer_write(buffer+n, len-n, "\t\t\t\t\t<xs:restriction base=\"xs:%s\"/>\n", attribute[i].type);
00861 }
00862 else
00863 {
00864 KEYWORD *key;
00865 n += buffer_write(buffer+n, len-n, "\t\t\t\t\t<xs:restriction base=\"xs:string\">\n");
00866 n += buffer_write(buffer+n, len-n, "\t\t\t\t\t\t<xs:pattern value=\"");
00867 for (key=attribute[i].keys; key!=NULL; key=key->next){
00868 n += buffer_write(buffer+n, len-n, "%s%s", key==attribute[i].keys?"":"|", key->name);
00869 }
00870 n += buffer_write(buffer+n, len-n, "\"/>\n");
00871 n += buffer_write(buffer+n, len-n, "\t\t\t\t\t</xs:restriction>\n");
00872 }
00873 n += buffer_write(buffer+n, len-n, "\t\t\t\t</xs:simpleType>\n");
00874 n += buffer_write(buffer+n, len-n, "\t\t\t</xs:element>\n");
00875 }
00876 for (prop=oclass->pmap; prop!=NULL && prop->otype==oclass->type; prop=prop->next)
00877 {
00878 char *proptype=class_get_property_typename(prop->ptype);
00879 if (prop->unit!=NULL){
00880 n += buffer_write(buffer+n, len-n, "\t\t\t\t<xs:element name=\"%s\" type=\"xs:string\"/>\n", prop->name);
00881 } else {
00882 n += buffer_write(buffer+n, len-n, "\t\t\t<xs:element name=\"%s\">\n", prop->name);
00883 n += buffer_write(buffer+n, len-n, "\t\t\t\t<xs:simpleType>\n");
00884 n += buffer_write(buffer+n, len-n, "\t\t\t\t\t<xs:restriction base=\"xs:%s\">\n", proptype==NULL?"string":proptype);
00885 if (prop->keywords!=NULL)
00886 {
00887 KEYWORD *key;
00888 n += buffer_write(buffer+n, len-n, "\t\t\t\t\t<xs:pattern value=\"");
00889 for (key=prop->keywords; key!=NULL; key=key->next){
00890 n += buffer_write(buffer+n, len-n, "%s%s", key==prop->keywords?"":"|", key->name);
00891 }
00892 n += buffer_write(buffer+n, len-n, "\"/>\n");
00893 }
00894 n += buffer_write(buffer+n, len-n, "\t\t\t\t\t</xs:restriction>\n");
00895 n += buffer_write(buffer+n, len-n, "\t\t\t\t</xs:simpleType>\n");
00896 n += buffer_write(buffer+n, len-n, "\t\t\t</xs:element>\n");
00897 }
00898 }
00899 n += buffer_write(buffer+n, len-n, "\t\t</xs:all>\n");
00900 n += buffer_write(buffer+n, len-n, "\t</xs:complexType>\n");
00901 n += buffer_write(buffer+n, len-n, "</xs:element>\n");
00902 buffer[n] = 0;
00903 if(check == 0){
00904 printf("class_get_xsd() overflowed.\n");
00905 buffer[0] = 0;
00906 return 0;
00907 }
00908 return (int)n;
00909 }
00910
00911