5
WSDL parser and converter to gSOAP header file format
7
--------------------------------------------------------------------------------
8
gSOAP XML Web services tools
9
Copyright (C) 2001-2007, Robert van Engelen, Genivia Inc. All Rights Reserved.
10
This software is released under one of the following two licenses:
11
GPL or Genivia's license for commercial use.
12
--------------------------------------------------------------------------------
15
This program is free software; you can redistribute it and/or modify it under
16
the terms of the GNU General Public License as published by the Free Software
17
Foundation; either version 2 of the License, or (at your option) any later
20
This program is distributed in the hope that it will be useful, but WITHOUT ANY
21
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
22
PARTICULAR PURPOSE. See the GNU General Public License for more details.
24
You should have received a copy of the GNU General Public License along with
25
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
26
Place, Suite 330, Boston, MA 02111-1307 USA
28
Author contact information:
29
engelen@genivia.com / engelen@acm.org
30
--------------------------------------------------------------------------------
31
A commercial use license is available from Genivia, Inc., contact@genivia.com
32
--------------------------------------------------------------------------------
38
static char *getline(char *s, size_t n, FILE *fd);
39
static const char *nonblank(const char *s);
40
static const char *fill(char *t, int n, const char *s, int e);
41
static const char *utf8(char *t, const char *s);
42
static const char *cstring(const char *s);
43
static const char *xstring(const char *s);
44
static bool is_integer(const char *s);
45
static void documentation(const char *text);
47
////////////////////////////////////////////////////////////////////////////////
49
// Keywords and reserved words
51
////////////////////////////////////////////////////////////////////////////////
53
static const char *keywords[] =
136
////////////////////////////////////////////////////////////////////////////////
140
////////////////////////////////////////////////////////////////////////////////
146
int Types::read(const char *file)
147
{ FILE *fd = fopen(file, "r");
148
char buf[1024], xsd[1024], def[1024], use[1024], ptr[1024], uri[1024];
152
{ fprintf(stderr, "Cannot open file '%s'\n", file);
155
fprintf(stderr, "Reading type map file '%s'\n\n", file);
156
while (getline(buf, sizeof(buf), fd))
162
fprintf(stream, "%s\n", buf);
167
{ s = fill(uri, sizeof(uri), s+1, -1);
168
infile[infiles++] = estrdup(uri);
169
if (infiles >= MAXINFILES)
170
{ fprintf(stderr, "wsdl2h: too many files\n");
175
{ s = fill(uri, sizeof(uri), s+1, -1);
177
{ outfile = estrdup(uri);
178
stream = fopen(outfile, "w");
180
{ fprintf(stderr, "Cannot write to %s\n", outfile);
184
fprintf(stream, "namespace %s {\n", cppnamespace);
185
fprintf(stderr, "Saving %s\n\n", outfile);
188
else if (*s && *s != '#')
189
{ s = fill(xsd, sizeof(xsd), s, '=');
190
if (strstr(xsd, "__"))
191
{ s = fill(def, sizeof(def), s, '|');
192
s = fill(use, sizeof(use), s, '|');
193
s = fill(ptr, sizeof(ptr), s, '|');
197
{ const char *t = modtypemap[s];
199
{ char *r = (char*)emalloc(strlen(t) + strlen(def) + 1);
202
free((void*)modtypemap[s]);
206
modtypemap[s] = estrdup(def);
210
deftypemap[s] = estrdup(def);
214
usetypemap[s] = estrdup(use);
216
usetypemap[s] = estrdup(xsd);
218
ptrtypemap[s] = estrdup(ptr);
223
{ s = fill(uri, sizeof(uri), s, 0);
225
{ uri[strlen(uri) - 1] = '\0';
226
nsprefix(xsd, estrdup(uri + 1));
228
else if (uri[0] == '<')
229
{ uri[strlen(uri) - 1] = '\0';
230
char *s = estrdup(uri + 1);
235
nsprefix(xsd, estrdup(uri));
249
knames.insert(keywords, keywords + sizeof(keywords)/sizeof(char*));
251
{ deftypemap["xsd__ur_type"] = "";
253
{ usetypemap["xsd__ur_type"] = "xsd__anyType";
254
ptrtypemap["xsd__ur_type"] = "xsd__anyType*";
257
{ usetypemap["xsd__ur_type"] = "_XML";
258
ptrtypemap["xsd__ur_type"] = "_XML";
262
{ deftypemap["xsd__ur_type"] = "class xsd__ur_type { _XML __item; struct soap *soap; };";
263
usetypemap["xsd__ur_type"] = "xsd__ur_type";
266
{ deftypemap["xsd__anyType"] = "";
268
{ usetypemap["xsd__anyType"] = "xsd__anyType";
269
ptrtypemap["xsd__anyType"] = "xsd__anyType*";
272
{ usetypemap["xsd__anyType"] = "_XML";
273
ptrtypemap["xsd__anyType"] = "_XML";
278
{ deftypemap["xsd__anyType"] = "";
279
usetypemap["xsd__anyType"] = "xsd__anyType";
280
ptrtypemap["xsd__anyType"] = "xsd__anyType*";
283
{ deftypemap["xsd__anyType"] = "class xsd__anyType { _XML __item; struct soap *soap; };";
284
usetypemap["xsd__anyType"] = "xsd__anyType*";
288
{ deftypemap["xsd__base64Binary"] = "struct xsd__base64Binary\n{\tunsigned char *__ptr;\n\tint __size;\n\tchar *id, *type, *options; // NOTE: for DIME and MTOM XOP attachments only\n};";
289
usetypemap["xsd__base64Binary"] = "struct xsd__base64Binary";
292
{ deftypemap["xsd__base64Binary"] = "class xsd__base64Binary\n{\tunsigned char *__ptr;\n\tint __size;\n\tchar *id, *type, *options; // NOTE: for DIME and MTOM XOP attachments only\n\tstruct soap *soap;\n};";
293
usetypemap["xsd__base64Binary"] = "xsd__base64Binary";
297
deftypemap["xsd__boolean"] = "enum xsd__boolean { false_, true_ };";
299
deftypemap["xsd__boolean"] = "enum xsd__boolean { xsd__boolean__false_, xsd__boolean__true_ };";
300
usetypemap["xsd__boolean"] = "enum xsd__boolean";
303
{ deftypemap["xsd__boolean"] = "";
304
usetypemap["xsd__boolean"] = "bool";
306
deftypemap["xsd__byte"] = "";
307
usetypemap["xsd__byte"] = "char";
308
ptrtypemap["xsd__byte"] = "short*"; // avoid char*
309
deftypemap["xsd__dateTime"] = "";
310
usetypemap["xsd__dateTime"] = "time_t";
311
deftypemap["xsd__double"] = "";
312
usetypemap["xsd__double"] = "double";
313
deftypemap["xsd__float"] = "";
314
usetypemap["xsd__float"] = "float";
316
{ deftypemap["xsd__hexBinary"] = "struct xsd__hexBinary { unsigned char *__ptr; int __size; };";
317
usetypemap["xsd__hexBinary"] = "struct xsd__hexBinary";
320
{ deftypemap["xsd__hexBinary"] = "class xsd__hexBinary { unsigned char *__ptr; int __size; };";
321
usetypemap["xsd__hexBinary"] = "xsd__hexBinary";
323
deftypemap["xsd__int"] = "";
324
usetypemap["xsd__int"] = "int";
325
deftypemap["xsd__long"] = "";
326
usetypemap["xsd__long"] = "LONG64";
327
deftypemap["xsd__short"] = "";
328
usetypemap["xsd__short"] = "short";
330
{ deftypemap["xsd__string"] = "";
331
usetypemap["xsd__string"] = "char*";
332
deftypemap["xsd__QName"] = "";
333
usetypemap["xsd__QName"] = "_QName";
334
ptrtypemap["xsd__QName"] = "_QName";
337
{ deftypemap["xsd__string"] = "";
338
usetypemap["xsd__string"] = "std::string";
340
deftypemap["xsd__unsignedByte"] = "";
341
usetypemap["xsd__unsignedByte"] = "unsigned char";
342
ptrtypemap["xsd__unsignedByte"] = "unsigned short*"; // avoid unsigned char*
343
deftypemap["xsd__unsignedInt"] = "";
344
usetypemap["xsd__unsignedInt"] = "unsigned int";
345
deftypemap["xsd__unsignedLong"] = "";
346
usetypemap["xsd__unsignedLong"] = "ULONG64";
347
deftypemap["xsd__unsignedShort"] = "";
348
usetypemap["xsd__unsignedShort"] = "unsigned short";
350
{ deftypemap["SOAP_ENC__base64Binary"] = "struct SOAP_ENC__base64Binary { unsigned char *__ptr; int __size; };";
351
usetypemap["SOAP_ENC__base64Binary"] = "struct SOAP_ENC__base64Binary";
352
deftypemap["SOAP_ENC__base64"] = "struct SOAP_ENC__base64 { unsigned char *__ptr; int __size; };";
353
usetypemap["SOAP_ENC__base64"] = "struct SOAP_ENC__base64";
356
{ deftypemap["SOAP_ENC__base64Binary"] = "class SOAP_ENC__base64Binary { unsigned char *__ptr; int __size; };";
357
usetypemap["SOAP_ENC__base64Binary"] = "SOAP_ENC__base64Binary";
358
deftypemap["SOAP_ENC__base64"] = "class SOAP_ENC__base64 { unsigned char *__ptr; int __size; };";
359
usetypemap["SOAP_ENC__base64"] = "SOAP_ENC__base64";
362
{ deftypemap["SOAP_ENC__boolean"] = "enum SOAP_ENC__boolean { false_, true_ };";
363
usetypemap["SOAP_ENC__boolean"] = "enum SOAP_ENC__boolean";
366
{ deftypemap["SOAP_ENC__boolean"] = "";
367
usetypemap["SOAP_ENC__boolean"] = "bool";
369
deftypemap["SOAP_ENC__byte"] = "";
370
usetypemap["SOAP_ENC__byte"] = "char";
371
deftypemap["SOAP_ENC__dateTime"] = "";
372
usetypemap["SOAP_ENC__dateTime"] = "time_t";
373
deftypemap["SOAP_ENC__double"] = "";
374
usetypemap["SOAP_ENC__double"] = "double";
375
deftypemap["SOAP_ENC__float"] = "";
376
usetypemap["SOAP_ENC__float"] = "float";
378
{ deftypemap["SOAP_ENC__hexBinary"] = "struct SOAP_ENC__hexBinary { unsigned char *__ptr; int __size; };";
379
usetypemap["SOAP_ENC__hexBinary"] = "struct SOAP_ENC__hexBinary";
382
{ deftypemap["SOAP_ENC__hexBinary"] = "class SOAP_ENC__hexBinary { unsigned char *__ptr; int __size; };";
383
usetypemap["SOAP_ENC__hexBinary"] = "SOAP_ENC__hexBinary";
385
deftypemap["SOAP_ENC__int"] = "";
386
usetypemap["SOAP_ENC__int"] = "int";
387
deftypemap["SOAP_ENC__long"] = "";
388
usetypemap["SOAP_ENC__long"] = "LONG64";
389
deftypemap["SOAP_ENC__short"] = "";
390
usetypemap["SOAP_ENC__short"] = "short";
391
ptrtypemap["SOAP_ENC__short"] = "int*";
393
{ deftypemap["SOAP_ENC__string"] = "";
394
usetypemap["SOAP_ENC__string"] = "char*";
397
{ deftypemap["SOAP_ENC__string"] = "";
398
usetypemap["SOAP_ENC__string"] = "std::string";
400
deftypemap["SOAP_ENC__unsignedByte"] = "";
401
usetypemap["SOAP_ENC__unsignedByte"] = "unsigned char";
402
ptrtypemap["SOAP_ENC__unsignedByte"] = "unsigned short*";
403
deftypemap["SOAP_ENC__unsignedInt"] = "";
404
usetypemap["SOAP_ENC__unsignedInt"] = "unsigned long";
405
deftypemap["SOAP_ENC__unsignedLong"] = "";
406
usetypemap["SOAP_ENC__unsignedLong"] = "ULONG64";
407
deftypemap["SOAP_ENC__unsignedShort"] = "";
408
usetypemap["SOAP_ENC__unsignedShort"] = "unsigned short";
409
deftypemap["SOAP_ENC__Array"] = "";
410
usetypemap["SOAP_ENC__Array"] = "struct { _XML *__ptr; int __size; }";
411
deftypemap["_SOAP_ENC__arrayType"] = "";
412
deftypemap["SOAP_ENV__Header"] = "";
413
usetypemap["SOAP_ENV__Header"] = "struct SOAP_ENV__Header";
414
deftypemap["SOAP_ENV__Fault"] = "";
415
usetypemap["SOAP_ENV__Fault"] = "struct SOAP_ENV__Fault";
416
deftypemap["SOAP_ENV__detail"] = "";
417
usetypemap["SOAP_ENV__detail"] = "struct SOAP_ENV__Detail";
418
deftypemap["SOAP_ENV__Detail"] = "";
419
usetypemap["SOAP_ENV__Detail"] = "struct SOAP_ENV__Detail";
420
deftypemap["SOAP_ENV__Code"] = "";
421
usetypemap["SOAP_ENV__Code"] = "struct SOAP_ENV__Code";
422
deftypemap["SOAP_ENV__Reason"] = "";
423
usetypemap["SOAP_ENV__Reason"] = "struct SOAP_ENV__Reason";
425
fprintf(stderr, "Problem reading type map file %s.\nUsing internal type definitions for %s instead.\n\n", mapfile, cflag?"C":"C++");
428
const char *Types::nsprefix(const char *prefix, const char *URI)
430
{ const char *s = uris[URI];
433
if (!prefix || !*prefix || *prefix == '_')
441
if (n != 1 || !prefix || !*prefix || *prefix == '_')
442
{ char *t = (char*)emalloc(strlen(s) + 16);
443
sprintf(t, "%s%lu", s, (unsigned long)n);
448
fprintf(stderr, "namespace prefix %s = \"%s\"\n", s, URI);
450
// if *prefix == '_', then add prefix string to s
451
if (prefix && *prefix == '_')
452
{ char *t = (char*)emalloc(strlen(s) + 2);
462
// Find a C name for a QName. If the name has no qualifier, use URI. Suggest prefix for URI
463
const char *Types::fname(const char *prefix, const char *URI, const char *qname, SetOfString *reserved, enum Lookup lookup)
464
{ char buf[1024], *t;
465
const char *p, *s, *name;
467
{ fprintf(stream, "// Warning: internal error, no QName in fname()\n");
469
fprintf(stderr, "Internal error, no QName in fname()\n");
472
s = strrchr(qname, ':');
475
if (qname[0] == '"' && qname[1] == '"')
477
else if (*qname == '"')
478
{ t = (char*)emalloc(s - qname - 1);
479
strncpy(t, qname + 1, s - qname - 2);
480
t[s - qname - 2] = '\0';
483
else if (!strncmp(qname, "xs:", 3)) // this hack is necessary since the nsmap table defines "xs" for "xsd"
488
{ t = (char*)emalloc(s - qname + 1);
489
strncpy(t, qname, s - qname);
498
p = nsprefix(prefix, URI);
503
if (lookup == LOOKUP)
504
{ s = qnames[Pair(p,name)];
509
if (!prefix || *prefix)
511
// no longer add '_' when URI != NULL, since nsprefix() will do this
512
if (prefix && *prefix == '_')
515
if (prefix[1] == '_') // ensures ns prefix starts with __
516
{ strcpy(t, prefix + 1);
517
t += strlen(prefix + 1);
524
else if (*s == '-' && s != p)
530
{ strcpy(t, "_USCORE");
543
if (!prefix || *prefix != '*')
548
else if (isdigit(*name))
551
for (s = name; *s; s++)
554
else if (*s == '-' && s != name)
556
else if (!_flag && *s == '_')
557
{ strcpy(t, "_USCORE");
566
while (knames.find(buf) != knames.end() || (reserved && reserved->find(buf) != reserved->end()))
570
if (isalpha(*buf) || *buf == '_')
571
{ t = (char*)emalloc(strlen(buf) + 1);
575
{ t = (char*)emalloc(strlen(buf) + 2);
579
if (lookup == LOOKUP)
580
{ qnames[Pair(p,name)] = t;
582
cerr << "Mapping " << p << ":" << name << " to " << t << endl;
584
for (MapOfPairToString::const_iterator i = qnames.begin(); i != qnames.end(); ++i)
585
cerr << "(" << (*i).first.first << "," << (*i).first.second << ") = " << (*i).second << endl;
591
bool Types::is_defined(const char *prefix, const char *URI, const char *qname)
592
{ const char *t = fname(prefix, URI, qname, NULL, LOOKUP);
593
return usetypemap.find(t) != usetypemap.end();
596
const char *Types::aname(const char *prefix, const char *URI, const char *qname)
597
{ return fname(prefix, URI, qname, NULL, NOLOOKUP);
600
const char *Types::cname(const char *prefix, const char *URI, const char *qname)
601
{ return fname(prefix, URI, qname, NULL, LOOKUP);
604
const char *Types::tname(const char *prefix, const char *URI, const char *qname)
606
t = cname(prefix, URI, qname);
607
if (usetypemap.find(t) != usetypemap.end())
611
fprintf(stream, "\n// Warning: undefined QName '%s' for type '%s' (FIXME: check WSDL and schema definitions)\n", qname?qname:"", t);
613
fprintf(stderr, "Warning: undefined QName '%s' for type '%s' in namespace '%s'\n", qname?qname:"", t, URI?URI:"?");
618
const char *Types::tnameptr(bool flag, const char *prefix, const char *URI, const char *qname)
619
{ const char *s = pname(flag, prefix, URI, qname);
621
{ if (!strncmp(s, "char*", 5))
624
{ char *r = (char*)emalloc(strlen(s) + 2);
633
const char *Types::pname(bool flag, const char *prefix, const char *URI, const char *qname)
634
{ const char *r, *s = NULL, *t;
635
t = cname(prefix, URI, qname);
637
{ if (ptrtypemap.find(t) != ptrtypemap.end())
640
{ if (usetypemap.find(t) != usetypemap.end())
644
fprintf(stream, "\n// Warning: undefined QName '%s' for pointer to type '%s' (FIXME: check WSDL and schema definitions)\n", qname, t);
646
fprintf(stderr, "Warning: undefined QName '%s' for pointer to type '%s' in namespace '%s'\n", qname, t, URI?URI:"?");
650
{ r = strchr(r + 1, '*');
651
if (r && *(r-1) != '/' && *(r+1) != '/')
654
if (!r) // already pointer?
655
{ char *p = (char*)emalloc(strlen(s) + 2);
661
fprintf(stderr, "Mapping pointer to %s to %s\n", t, s);
665
else if (usetypemap.find(t) != usetypemap.end())
669
fprintf(stream, "\n// Warning: undefined QName '%s' for type '%s' (FIXME: check WSDL and schema definitions)\n", qname, t);
671
fprintf(stderr, "Warning: undefined QName '%s' for type '%s' in namespace '%s'\n", qname, t, URI?URI:"?");
676
const char *Types::deftname(enum Type type, const char *pointer, bool is_pointer, const char *prefix, const char *URI, const char *qname)
679
const char *q = NULL, *t;
680
t = fname(prefix, URI, qname, NULL, LOOKUP);
683
fprintf(stderr, "Name %s already defined (probably in %s file)\n", qname, mapfile);
711
strcat(buf, pointer);
712
s = (char*)emalloc(strlen(buf) + 1);
715
if (pointer || is_pointer)
718
fprintf(stderr, "Defined %s in namespace %s as %s\n", qname, URI?URI:(prefix?prefix:""), s);
722
// get enumeration value. URI/type refers to the enum simpleType.
723
const char *Types::ename(const char *type, const char *value)
724
{ const char *s = enames[Pair(type,value)];
726
{ s = fname(NULL, NULL, value, &rnames, NOLOOKUP);
727
if (!eflag && type && *type)
728
{ // Add prefix to enum
729
if (!*s || (s[0] == '_' && s[1] == '\0'))
731
char *buf = (char*)emalloc(strlen(type) + strlen(s) + 3);
732
if (s[0] == '_' && s[1] != 'x') // _xXXXX is OK here
733
sprintf(buf, "%s_%s", type, s);
735
sprintf(buf, "%s__%s", type, s);
740
enames[Pair(type,value)] = s;
745
// get operation name
746
const char *Types::oname(const char *prefix, const char *URI, const char *qname)
747
{ const char *s = fname(prefix, URI, qname, NULL, LOOKUP);
748
if (s && usetypemap.find(s) != usetypemap.end())
749
{ // Avoid name clash with structs/classes of the same name
752
s = fname(prefix, URI, qname, &onames, NOLOOKUP);
757
// generate struct name
758
const char *Types::sname(const char *URI, const char *name)
763
for (VectorOfString::const_iterator i = scope.begin(); i != scope.end(); ++i)
764
len += strlen(*i) + 1;
765
t = (char*)emalloc(len + strlen(name) + 1);
767
for (VectorOfString::const_iterator j = scope.begin(); j != scope.end(); ++j)
772
s = fname("_", URI, t, &rnames, NOLOOKUP);
776
{ s = nsprefix(NULL, URI); /* TODO: this may be affected? */
777
t = (char*)emalloc(strlen(s) + 16);
778
sprintf(t, "_%s__struct_%d", s, snum++);
782
{ t = (char*)emalloc(16);
783
sprintf(t, "struct_%d", snum++);
789
// generate union name
790
const char *Types::uname(const char *URI)
795
for (VectorOfString::const_iterator i = scope.begin(); i != scope.end(); ++i)
796
len += strlen(*i) + 1;
797
t = (char*)emalloc(len + 6);
799
for (VectorOfString::const_iterator j = scope.begin(); j != scope.end(); ++j)
803
s = fname("_", URI, t, &rnames, NOLOOKUP);
807
{ s = nsprefix(NULL, URI); /* TODO: this may be affected? */
808
t = (char*)emalloc(strlen(s) + 16);
809
sprintf(t, "_%s__union_%d", s, unum++);
813
{ t = (char*)emalloc(16);
814
sprintf(t, "_union_%d", unum++);
820
// generate enum name
821
const char *Types::gname(const char *URI, const char *name)
826
for (VectorOfString::const_iterator i = scope.begin(); i != scope.end(); ++i)
827
len += strlen(*i) + 1;
828
t = (char*)emalloc(len + strlen(name) + 1);
830
for (VectorOfString::const_iterator j = scope.begin(); j != scope.end(); ++j)
835
s = fname("_", URI, t, &rnames, NOLOOKUP);
839
{ s = nsprefix(NULL, URI); /* TODO: this may be affected? */
840
t = (char*)emalloc(strlen(s) + 16);
841
sprintf(t, "_%s__enum_%d", s, gnum++);
845
{ t = (char*)emalloc(16);
846
sprintf(t, "enum_%d", gnum++);
852
// check if nillable or minOccurs=0 (and no default value is present)
853
bool Types::is_nillable(const xs__element& element)
854
{ return !element.default_ && (element.nillable || (element.minOccurs && !strcmp(element.minOccurs, "0")));
857
bool Types::is_basetype(const char *URI, const char *type)
858
{ const char *t = tname(NULL, URI, type);
859
if (!strcmp(t, "std::string")
862
return !strncmp(type, "xs:", 3) || !strncmp(type, "SOAP-ENC:", 9);
865
void Types::dump(FILE *fd)
866
{ fprintf(fd, "\nTypes:\n");
867
for (MapOfStringToString::const_iterator i = usetypemap.begin(); i != usetypemap.end(); ++i)
868
fprintf(fd, "%s=%s\n", (*i).first, (*i).second?(*i).second:"(null)");
869
fprintf(fd, "\nPointers:\n");
870
for (MapOfStringToString::const_iterator j = ptrtypemap.begin(); j != ptrtypemap.end(); ++j)
871
fprintf(fd, "%s=%s\n", (*j).first, (*j).second?(*j).second:"(null)");
874
void Types::define(const char *URI, const char *name, const xs__complexType& complexType)
875
{ // generate prototype for structs/classes and store name
876
const char *prefix = NULL;
877
if (complexType.name)
878
name = complexType.name;
881
if (complexType.complexContent && complexType.complexContent->restriction && !strcmp(complexType.complexContent->restriction->base, "SOAP-ENC:Array"))
882
{ if (strcmp(schema_prefix, "ns"))
888
{ const char *t = deftname(STRUCT, "*", true, prefix, URI, name);
891
fprintf(stream, "\n/// Typedef synonym for struct %s.\ntypedef struct %s %s;\n", t, t, t);
894
{ t = deftypemap[cname(prefix, URI, name)];
896
{ fprintf(stream, "\n/// Imported complexType \"%s\":%s from typemap %s.\n", URI, name, mapfile?mapfile:"");
897
document(complexType.annotation);
901
fprintf(stream, "// complexType definition intentionally left blank.\n");
906
{ const char *t = deftname(CLASS, "*", true, prefix, URI, name);
908
fprintf(stream, "\n// Forward declaration of class %s.\nclass %s;\n", t, t);
910
{ t = deftypemap[cname(prefix, URI, name)];
912
{ fprintf(stream, "\n/// Imported complexType \"%s\":%s from typemap %s.\n", URI, name, mapfile?mapfile:"");
913
document(complexType.annotation);
917
fprintf(stream, "// complexType definition intentionally left blank.\n");
923
void Types::gen(const char *URI, const char *name, const xs__simpleType& simpleType, bool anonymous)
924
{ const char *t = NULL;
925
const char *prefix = NULL;
927
name = simpleType.name;
931
{ t = deftypemap[cname(NULL, URI, name)];
933
{ fprintf(stream, "\n/// Imported simpleType \"%s\":%s from typemap %s.\n", URI, name, mapfile?mapfile:"");
934
document(simpleType.annotation);
938
fprintf(stream, "// simpleType definition intentionally left blank.\n");
942
if (simpleType.restriction && simpleType.restriction->base)
943
{ const char *base = simpleType.restriction->base;
944
const char *baseURI = NULL;
945
if (simpleType.restriction->simpleTypePtr() && simpleType.restriction->simpleTypePtr()->schemaPtr())
946
baseURI = simpleType.restriction->simpleTypePtr()->schemaPtr()->targetNamespace;
948
fprintf(stream, "\n/// \"%s\":%s is a simpleType restriction of %s.\n", URI?URI:"", name, simpleType.restriction->base);
949
document(simpleType.annotation);
950
document(simpleType.restriction->annotation);
951
if (!simpleType.restriction->enumeration.empty())
952
{ bool is_numeric = true; // check if all enumeration values are numeric
953
bool is_qname = !strcmp(base, "xs:QName");
955
{ t = deftname(ENUM, NULL, false, prefix, URI, name);
957
fprintf(stream, "/// Note: enum values are prefixed with '%s' to avoid name clashes, please use wsdl2h option -e to omit this prefix\n", t);
960
t = gname(URI, name);
962
fprintf(stream, "enum %s\n{\n", t);
964
fprintf(stream, " enum %s\n {\n", t);
965
for (vector<xs__enumeration>::const_iterator enumeration1 = simpleType.restriction->enumeration.begin(); enumeration1 != simpleType.restriction->enumeration.end(); ++enumeration1)
967
if ((s = (*enumeration1).value))
968
is_numeric &= is_integer(s);
970
SetOfString enumvals;
971
for (vector<xs__enumeration>::const_iterator enumeration2 = simpleType.restriction->enumeration.begin(); enumeration2 != simpleType.restriction->enumeration.end(); ++enumeration2)
973
document((*enumeration2).annotation);
974
if ((s = (*enumeration2).value))
975
{ if (!enumvals.count(s))
976
{ enumvals.insert(s);
978
fprintf(stream, "\t%s = %s,\t///< %s value=\"%s\"\n", ename(t, s), s, base, s);
979
else if (is_qname && (*enumeration2).value_)
980
fprintf(stream, "\t%s,\t///< %s value=\"%s\"\n", ename(t, (*enumeration2).value_), base, (*enumeration2).value_);
982
fprintf(stream, "\t%s,\t///< %s value=\"%s\"\n", ename(t, s), base, s);
986
fprintf(stream, "//\tunrecognized: enumeration '%s' has no value\n", name?name:"");
989
{ fprintf(stream, "};\n");
991
fprintf(stream, "/// Typedef synonym for enum %s.\ntypedef enum %s %s;\n", t, t, t);
992
if (pflag && simpleType.name)
993
{ const char *s = aname(prefix, URI, name);
995
s = aname(prefix, URI, name);
996
fprintf(stream, "\n/// Class wrapper\n");
997
fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", s);
998
fprintf(stream, elementformat, tname(prefix, URI, name), "__item;");
1000
fprintf(stream, "\n};\n");
1004
fprintf(stream, " }\n");
1007
{ if (simpleType.restriction->length && simpleType.restriction->length->value)
1008
fprintf(stream, "/// Length of this string is exactly %s characters\n", simpleType.restriction->length->value);
1010
{ const char *a = NULL, *b = NULL;
1011
if (simpleType.restriction->minLength)
1012
a = simpleType.restriction->minLength->value;
1013
if (simpleType.restriction->maxLength)
1014
b = simpleType.restriction->maxLength->value;
1016
fprintf(stream, "/// Length of this string is within %s..%s characters\n", a?a:"0", b?b:"");
1018
if (simpleType.restriction->precision && simpleType.restriction->precision->value)
1019
fprintf(stream, "/// %sprecision is %s\n", simpleType.restriction->precision->fixed?"fixed ":"", simpleType.restriction->precision->value);
1020
if (simpleType.restriction->scale && simpleType.restriction->scale->value)
1021
fprintf(stream, "/// %sscale is %s\n", simpleType.restriction->scale->fixed?"fixed ":"", simpleType.restriction->scale->value);
1022
if (simpleType.restriction->totalDigits && simpleType.restriction->totalDigits->value)
1023
fprintf(stream, "/// %snumber of total digits is %s\n", simpleType.restriction->totalDigits->fixed?"fixed ":"", simpleType.restriction->totalDigits->value);
1024
if (simpleType.restriction->fractionDigits && simpleType.restriction->fractionDigits->value)
1025
fprintf(stream, "/// %snumber of fraction digits is %s\n", simpleType.restriction->fractionDigits->fixed?"fixed ":"", simpleType.restriction->fractionDigits->value);
1026
for (vector<xs__pattern>::const_iterator pattern1 = simpleType.restriction->pattern.begin(); pattern1 != simpleType.restriction->pattern.end(); ++pattern1)
1027
fprintf(stream, "/// Content pattern is \"%s\"\n", xstring((*pattern1).value));
1028
const char *ai = NULL, *ae = NULL, *bi = NULL, *be = NULL;
1029
if (simpleType.restriction->minInclusive)
1030
ai = simpleType.restriction->minInclusive->value;
1031
else if (simpleType.restriction->minExclusive)
1032
ae = simpleType.restriction->minExclusive->value;
1033
if (simpleType.restriction->maxInclusive)
1034
bi = simpleType.restriction->maxInclusive->value;
1035
else if (simpleType.restriction->maxExclusive)
1036
be = simpleType.restriction->maxExclusive->value;
1037
if (ai || ae || bi || be)
1038
{ fprintf(stream, "/// Value range is ");
1040
fprintf(stream, "[%s..", ai);
1042
fprintf(stream, "(%s..", ae);
1044
fprintf(stream, "[..");
1046
fprintf(stream, "%s]\n", bi);
1048
fprintf(stream, "%s)\n", be);
1050
fprintf(stream, "]\n");
1052
if (!simpleType.restriction->attribute.empty())
1053
{ fprintf(stderr, "\nWarning: simpleType '%s' should not have attributes\n", name?name:"");
1055
const char *s = tname(NULL, baseURI, base);
1057
{ bool is_ptr = false;
1058
is_ptr = (strchr(s, '*') != NULL) || (s == pname(true, NULL, baseURI, base));
1059
t = deftname(TYPEDEF, NULL, is_ptr, prefix, URI, name);
1061
fprintf(stream, "typedef %s %s", s, t);
1065
fprintf(stream, elementformat, s, "");
1066
fprintf(stream, "\n");
1069
{ if (!anonymous && !simpleType.restriction->pattern.empty())
1070
{ fprintf(stream, " \"");
1071
for (vector<xs__pattern>::const_iterator pattern2 = simpleType.restriction->pattern.begin(); pattern2 != simpleType.restriction->pattern.end(); ++pattern2)
1072
{ if (pattern2 != simpleType.restriction->pattern.begin())
1073
fprintf(stream, "|");
1074
fprintf(stream, "%s", xstring((*pattern2).value));
1076
fprintf(stream, "\"");
1078
// add range info only when type is numeric
1079
bool is_numeric = false;
1080
if (!strncmp(s, "unsigned ", 9))
1082
if (strstr("char short int LONG64 float double ", s))
1084
if (!anonymous && simpleType.restriction->minLength && simpleType.restriction->minLength->value)
1085
fprintf(stream, " %s", simpleType.restriction->minLength->value);
1086
else if (is_numeric && !anonymous && simpleType.restriction->minInclusive && simpleType.restriction->minInclusive->value && is_integer(simpleType.restriction->minInclusive->value))
1087
fprintf(stream, " %s", simpleType.restriction->minInclusive->value);
1088
if (!anonymous && simpleType.restriction->maxLength && simpleType.restriction->maxLength->value)
1089
fprintf(stream, ":%s", simpleType.restriction->maxLength->value);
1090
else if (is_numeric && !anonymous && simpleType.restriction->maxInclusive && simpleType.restriction->maxInclusive->value && is_integer(simpleType.restriction->maxInclusive->value))
1091
fprintf(stream, ":%s", simpleType.restriction->maxInclusive->value);
1093
{ fprintf(stream, ";\n");
1094
if (pflag && simpleType.name)
1095
{ const char *s = aname(prefix, URI, name);
1097
s = aname(prefix, URI, name);
1098
fprintf(stream, "\n/// Class wrapper\n");
1099
fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", s);
1100
fprintf(stream, elementformat, tname(prefix, URI, name), "__item;");
1102
fprintf(stream, "\n};\n");
1108
else if (simpleType.list)
1109
{ if (simpleType.list->restriction && simpleType.list->restriction->base)
1111
{ fprintf(stream, "\n/// \"%s\":%s is a simpleType list restriction of %s.\n", URI?URI:"", name, simpleType.list->restriction->base);
1112
fprintf(stream, "/// Note: this enumeration is a bitmask, so a set of values is supported (using | and & bit-ops on the bit vector).\n");
1114
document(simpleType.annotation);
1116
{ t = deftname(ENUM, NULL, false, prefix, URI, name);
1118
fprintf(stream, "enum * %s\n{\n", t);
1122
fprintf(stream, "enum *\n{\n");
1125
{ for (vector<xs__enumeration>::const_iterator enumeration = simpleType.list->restriction->enumeration.begin(); enumeration != simpleType.list->restriction->enumeration.end(); ++enumeration)
1126
{ if ((*enumeration).value)
1127
{ if (!strcmp(simpleType.list->restriction->base, "xs:QName") && (*enumeration).value_)
1128
fprintf(stream, "\t%s,\t///< %s value=\"%s\"\n", ename(t, (*enumeration).value_), simpleType.list->restriction->base, (*enumeration).value_);
1130
fprintf(stream, "\t%s,\t///< %s value=\"%s\"\n", ename(t, (*enumeration).value), simpleType.list->restriction->base, (*enumeration).value);
1133
fprintf(stream, "//\tunrecognized: bitmask enumeration '%s' has no value\n", t);
1136
{ fprintf(stream, "};\n");
1138
fprintf(stream, "/// Typedef synonym for enum %s.\ntypedef enum %s %s;\n", t, t, t);
1139
if (pflag && simpleType.name)
1140
{ const char *s = aname(prefix, URI, name);
1142
s = aname(prefix, URI, name);
1143
fprintf(stream, "\n/// Class wrapper\n");
1144
fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", s);
1145
fprintf(stream, elementformat, tname(prefix, URI, name), "__item;");
1147
fprintf(stream, "\n};\n");
1151
fprintf(stream, "}\n");
1154
else if (simpleType.list->itemType)
1155
{ const xs__simpleType *p = simpleType.list->itemTypePtr();
1156
if (p && p->restriction && p->restriction->base && !p->restriction->enumeration.empty() && p->restriction->enumeration.size() <= 64)
1158
{ fprintf(stream, "\n/// \"%s\":%s is a simpleType list of %s.\n", URI?URI:"", name, simpleType.list->itemType);
1159
fprintf(stream, "/// Note: this enumeration is a bitmask, so a set of values is supported (using | and & bit-ops on the bit vector).\n");
1161
document(simpleType.annotation);
1163
{ t = deftname(ENUM, NULL, false, prefix, URI, name);
1165
fprintf(stream, "enum * %s\n{\n", t);
1169
fprintf(stream, "enum *\n{\n");
1172
{ for (vector<xs__enumeration>::const_iterator enumeration = p->restriction->enumeration.begin(); enumeration != p->restriction->enumeration.end(); ++enumeration)
1173
{ if ((*enumeration).value)
1174
fprintf(stream, "\t%s,\t///< %s value=\"%s\"\n", ename(t, (*enumeration).value), p->restriction->base, (*enumeration).value);
1176
fprintf(stream, "//\tunrecognized: bitmask enumeration '%s' has no value\n", t);
1179
{ fprintf(stream, "};\n");
1181
fprintf(stream, "/// Typedef synonym for enum %s.\ntypedef enum %s %s;\n", t, t, t);
1182
if (pflag && simpleType.name)
1183
{ const char *s = aname(prefix, URI, name);
1185
s = aname(prefix, URI, name);
1186
fprintf(stream, "\n/// Class wrapper.\n");
1187
fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", s);
1188
fprintf(stream, elementformat, tname(prefix, URI, name), "__item;");
1190
fprintf(stream, "\n};\n");
1194
fprintf(stream, "}\n");
1198
{ const char *s = tname(NULL, NULL, "xsd:string");
1200
{ fprintf(stream, "\n/// \"%s\":%s is a simpleType containing a whitespace separated list of %s.\n", URI?URI:"", name, simpleType.list->itemType);
1201
t = deftname(TYPEDEF, NULL, strchr(s, '*') != NULL, prefix, URI, name);
1203
document(simpleType.annotation);
1205
fprintf(stream, "typedef %s %s;\n", s, t);
1207
{ fprintf(stream, elementformat, s, "");
1208
fprintf(stream, "\n");
1214
{ fprintf(stream, "\n/// \"%s\":%s is a simpleType list.\n", URI?URI:"", name);
1215
fprintf(stream, "/// Note: this enumeration is a bitmask, so a set of values is supported (using | and & bit-ops on the bit vector).\n");
1217
document(simpleType.annotation);
1219
{ t = deftname(ENUM, NULL, false, prefix, URI, name);
1221
fprintf(stream, "/// Note: enum values are prefixed with '%s' to avoid name clashes, please use wsdl2h option -e to omit this prefix\n", t);
1226
{ fprintf(stream, "enum * %s\n{\n", t);
1227
for (vector<xs__simpleType>::const_iterator simple = simpleType.list->simpleType.begin(); simple != simpleType.list->simpleType.end(); ++simple)
1228
{ if ((*simple).restriction && (*simple).restriction->base)
1229
{ for (vector<xs__enumeration>::const_iterator enumeration = (*simple).restriction->enumeration.begin(); enumeration != (*simple).restriction->enumeration.end(); ++enumeration)
1230
{ if ((*enumeration).value)
1231
fprintf(stream, "\t%s,\t///< %s value=\"%s\"\n", ename(t, (*enumeration).value), (*simple).restriction->base, (*enumeration).value);
1233
fprintf(stream, "//\tunrecognized: bitmask enumeration '%s' has no value\n", t);
1238
{ fprintf(stream, "};\n");
1240
fprintf(stream, "/// Typedef synonym for enum %s.\ntypedef enum %s %s;\n", t, t, t);
1241
if (pflag && simpleType.name)
1242
{ const char *s = aname(prefix, URI, name);
1244
s = aname(prefix, URI, name);
1245
fprintf(stream, "\n/// Class wrapper.\n");
1246
fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", s);
1247
fprintf(stream, elementformat, tname(prefix, URI, name), "__item;");
1249
fprintf(stream, "\n};\n");
1253
fprintf(stream, "}\n");
1257
else if (simpleType.union_)
1258
{ if (simpleType.union_->memberTypes)
1259
{ const char *s = tname(NULL, NULL, "xsd:string");
1261
t = deftname(TYPEDEF, NULL, strchr(s, '*') != NULL, prefix, URI, name);
1262
fprintf(stream, "\n/// union of values \"%s\"\n", simpleType.union_->memberTypes);
1264
fprintf(stream, "typedef %s %s;\n", s, t);
1266
{ fprintf(stream, elementformat, s, "");
1267
fprintf(stream, "\n");
1270
else if (!simpleType.union_->simpleType.empty())
1271
{ const char *s = tname(NULL, NULL, "xsd:string");
1272
fprintf(stream, "\n");
1274
t = deftname(TYPEDEF, NULL, strchr(s, '*') != NULL, prefix, URI, name);
1275
for (vector<xs__simpleType>::const_iterator simpleType1 = simpleType.union_->simpleType.begin(); simpleType1 != simpleType.union_->simpleType.end(); ++simpleType1)
1276
if ((*simpleType1).restriction)
1277
{ fprintf(stream, "/// union of values from \"%s\"\n", (*simpleType1).restriction->base);
1278
// TODO: are there any other types we should report here?
1281
fprintf(stream, "typedef %s %s;\n", s, t);
1283
{ fprintf(stream, elementformat, s, "");
1284
fprintf(stream, "\n");
1288
fprintf(stream, "//\tunrecognized\n");
1291
fprintf(stream, "//\tunrecognized simpleType\n");
1294
void Types::gen(const char *URI, const char *name, const xs__complexType& complexType, bool anonymous)
1295
{ const char *t = NULL;
1296
const char *prefix = NULL;
1297
bool soapflag = false;
1298
if (complexType.name)
1299
name = complexType.name;
1302
if (anonymous && name)
1303
t = sname(URI, name);
1305
{ t = cname(prefix, URI, name);
1310
scope.push_back(name);
1311
if (complexType.simpleContent)
1313
fprintf(stream, "\n/// \"%s\":%s is a%s complexType with simpleContent.\n", URI?URI:"", name, complexType.abstract?"n abstract":"");
1314
document(complexType.annotation);
1315
if (complexType.simpleContent->restriction)
1318
fprintf(stream, " struct %s\n {\n", t);
1320
fprintf(stream, " class %s\n {\n", t);
1323
fprintf(stream, "struct %s\n{\n", t);
1324
else if (pflag && complexType.name)
1325
fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", t);
1327
fprintf(stream, "class %s\n{ public:\n", t);
1328
const char *base = "xs:string";
1329
const char *baseURI = NULL;
1330
const xs__complexType *p = &complexType;
1332
{ if (!p->simpleContent)
1334
if (p->simpleContent->restriction)
1335
{ if (p->simpleContent->restriction->complexTypePtr())
1336
p = p->simpleContent->restriction->complexTypePtr();
1338
{ base = p->simpleContent->restriction->base;
1339
if (p->simpleContent->restriction->simpleTypePtr() && p->simpleContent->restriction->simpleTypePtr()->schemaPtr())
1340
baseURI = p->simpleContent->restriction->simpleTypePtr()->schemaPtr()->targetNamespace;
1344
else if (p->simpleContent->extension)
1345
{ if (p->simpleContent->extension->complexTypePtr())
1346
p = p->simpleContent->extension->complexTypePtr();
1348
{ base = p->simpleContent->extension->base;
1349
if (p->simpleContent->extension->simpleTypePtr() && p->simpleContent->extension->simpleTypePtr()->schemaPtr())
1350
baseURI = p->simpleContent->extension->simpleTypePtr()->schemaPtr()->targetNamespace;
1358
fprintf(stream, "/// __item wraps '%s' simpleContent.\n", base);
1359
fprintf(stream, elementformat, tname(NULL, baseURI, base), "__item");
1360
fprintf(stream, ";\n");
1364
{ if (!p->simpleContent)
1366
if (p->simpleContent->restriction)
1367
{ // TODO: to avoid problems should only generate attribute when name is different
1368
gen(URI, p->simpleContent->restriction->attribute);
1369
if (p->simpleContent->restriction->anyAttribute && flag)
1370
{ gen(URI, *p->simpleContent->restriction->anyAttribute);
1373
if (p->simpleContent->restriction->complexTypePtr())
1374
p = p->simpleContent->restriction->complexTypePtr();
1378
else if (p->simpleContent->extension)
1379
{ gen(URI, p->simpleContent->extension->attribute);
1380
gen(URI, p->simpleContent->extension->attributeGroup);
1381
if (p->simpleContent->extension->anyAttribute && flag)
1382
{ gen(URI, *p->simpleContent->extension->anyAttribute);
1385
if (p->simpleContent->extension->complexTypePtr())
1386
p = p->simpleContent->extension->complexTypePtr();
1395
else if (complexType.simpleContent->extension)
1396
{ const char *base = "xs:string";
1397
const char *baseURI = NULL;
1398
if (cflag || fflag || anonymous)
1401
fprintf(stream, " struct %s\n {\n", t);
1403
fprintf(stream, " class %s\n {\n", t);
1406
fprintf(stream, "struct %s\n{\n", t);
1407
else if (pflag && complexType.name)
1408
fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", t);
1410
fprintf(stream, "class %s\n{ public:\n", t);
1411
const xs__complexType *p = &complexType;
1413
{ if (!p->simpleContent)
1415
if (p->simpleContent->restriction)
1416
{ if (p->simpleContent->restriction->complexTypePtr())
1417
p = p->simpleContent->restriction->complexTypePtr();
1419
{ base = p->simpleContent->restriction->base;
1420
if (p->simpleContent->restriction->simpleTypePtr() && p->simpleContent->restriction->simpleTypePtr()->schemaPtr())
1421
baseURI = p->simpleContent->restriction->simpleTypePtr()->schemaPtr()->targetNamespace;
1425
else if (p->simpleContent->extension)
1426
{ if (p->simpleContent->extension->complexTypePtr())
1427
p = p->simpleContent->extension->complexTypePtr();
1429
{ base = p->simpleContent->extension->base;
1430
if (p->simpleContent->extension->simpleTypePtr() && p->simpleContent->extension->simpleTypePtr()->schemaPtr())
1431
baseURI = p->simpleContent->extension->simpleTypePtr()->schemaPtr()->targetNamespace;
1439
fprintf(stream, "/// __item wraps '%s' simpleContent.\n", base);
1440
fprintf(stream, elementformat, tname(NULL, baseURI, base), "__item");
1441
fprintf(stream, ";\n");
1445
{ if (!p->simpleContent)
1447
if (p->simpleContent->restriction)
1448
{ gen(URI, p->simpleContent->restriction->attribute);
1449
if (p->simpleContent->restriction->anyAttribute && flag)
1450
gen(URI, *p->simpleContent->restriction->anyAttribute);
1453
else if (p->simpleContent->extension)
1454
{ gen(URI, p->simpleContent->extension->attribute);
1455
gen(URI, p->simpleContent->extension->attributeGroup);
1456
if (p->simpleContent->extension->anyAttribute && flag)
1457
{ gen(URI, *p->simpleContent->extension->anyAttribute);
1460
if (p->simpleContent->extension->complexTypePtr())
1461
p = p->simpleContent->extension->complexTypePtr();
1471
{ base = complexType.simpleContent->extension->base;
1473
/* TODO: in future, may want to add check here for base type == class
1474
complexType.simpleContent->extension->simpleTypePtr()
1477
complexType.simpleContent->extension->complexTypePtr())
1478
{ if (complexType.simpleContent->extension->complexTypePtr()->schemaPtr())
1479
baseURI = complexType.simpleContent->extension->complexTypePtr()->schemaPtr()->targetNamespace;
1480
fprintf(stream, "class %s : public %s\n{ public:\n", t, cname(NULL, baseURI, base));
1484
{ if (complexType.simpleContent->extension->simpleTypePtr() && complexType.simpleContent->extension->simpleTypePtr()->schemaPtr())
1485
baseURI = complexType.simpleContent->extension->simpleTypePtr()->schemaPtr()->targetNamespace;
1486
else if (complexType.simpleContent->extension->complexTypePtr() && complexType.simpleContent->extension->complexTypePtr()->schemaPtr())
1487
baseURI = complexType.simpleContent->extension->complexTypePtr()->schemaPtr()->targetNamespace;
1488
if (pflag && complexType.name)
1489
fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", t);
1491
fprintf(stream, "class %s\n{ public:\n", t);
1492
fprintf(stream, "/// __item wraps '%s' simpleContent.\n", base);
1493
fprintf(stream, elementformat, tname(NULL, baseURI, base), "__item");
1494
fprintf(stream, ";\n");
1496
gen(URI, complexType.simpleContent->extension->attribute);
1497
gen(URI, complexType.simpleContent->extension->attributeGroup);
1498
if (complexType.simpleContent->extension->anyAttribute)
1499
gen(URI, *complexType.simpleContent->extension->anyAttribute);
1503
fprintf(stream, "//\tunrecognized\n");
1505
else if (complexType.complexContent)
1506
{ if (complexType.complexContent->restriction)
1508
fprintf(stream, "\n/// \"%s\":%s is a%s complexType with complexContent restriction of %s.\n", URI?URI:"", name, complexType.abstract?"n abstract":"", complexType.complexContent->restriction->base);
1509
document(complexType.annotation);
1510
if (!strcmp(complexType.complexContent->restriction->base, "SOAP-ENC:Array"))
1511
{ char *item = NULL, *type = NULL;
1512
if (!complexType.complexContent->restriction->attribute.empty())
1513
{ xs__attribute& attribute = complexType.complexContent->restriction->attribute.front();
1514
if (attribute.wsdl__arrayType)
1515
type = attribute.wsdl__arrayType;
1517
if (complexType.complexContent->restriction->sequence && !complexType.complexContent->restriction->sequence->element.empty())
1518
{ xs__element& element = complexType.complexContent->restriction->sequence->element.front();
1521
type = element.type;
1522
else if (element.simpleTypePtr())
1523
{ if (element.simpleTypePtr()->name)
1524
type = element.simpleTypePtr()->name;
1525
else if (element.simpleTypePtr()->restriction)
1526
type = element.simpleTypePtr()->restriction->base;
1528
else if (element.complexTypePtr())
1529
{ if (element.complexTypePtr()->name)
1530
type = element.complexTypePtr()->name;
1531
else if (element.complexTypePtr()->complexContent && element.complexTypePtr()->complexContent->restriction)
1532
type = element.complexTypePtr()->complexContent->restriction->base;
1535
item = element.name;
1537
gen_soap_array(name, t, item, type);
1542
fprintf(stream, " struct %s\n {\n", t);
1544
fprintf(stream, " class %s\n {\n", t);
1547
fprintf(stream, "struct %s\n{\n", t);
1548
else if (pflag && complexType.name)
1549
fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", t);
1551
fprintf(stream, "class %s\n{ public:\n", t);
1552
if (complexType.complexContent->restriction->group)
1553
gen(URI, *complexType.complexContent->restriction->group);
1554
if (complexType.complexContent->restriction->all)
1555
gen(URI, *complexType.complexContent->restriction->all);
1556
if (complexType.complexContent->restriction->sequence)
1557
gen(URI, *complexType.complexContent->restriction->sequence);
1558
if (complexType.complexContent->restriction->choice)
1559
gen(URI, name, *complexType.complexContent->restriction->choice);
1560
const xs__complexType *p = &complexType;
1563
{ if (p->complexContent && p->complexContent->restriction)
1564
{ // TODO: to avoid problems should only generate attribute when name is different
1565
gen(URI, p->complexContent->restriction->attribute);
1566
if (p->complexContent->restriction->anyAttribute && flag)
1567
{ gen(URI, *p->complexContent->restriction->anyAttribute);
1570
if (p->complexContent->restriction->complexTypePtr())
1571
p = p->complexContent->restriction->complexTypePtr();
1575
else if (p->complexContent && p->complexContent->extension)
1576
{ gen(URI, p->complexContent->extension->attribute);
1577
gen(URI, p->complexContent->extension->attributeGroup);
1578
if (p->complexContent->extension->anyAttribute && flag)
1579
{ gen(URI, *p->complexContent->extension->anyAttribute);
1582
if (p->complexContent->extension->complexTypePtr())
1583
p = p->complexContent->extension->complexTypePtr();
1588
{ gen(URI, p->attribute);
1589
gen(URI, p->attributeGroup);
1590
if (p->anyAttribute && flag)
1591
gen(URI, *p->anyAttribute);
1598
else if (complexType.complexContent->extension)
1599
{ const char *base = complexType.complexContent->extension->base;
1600
xs__complexType *p = complexType.complexContent->extension->complexTypePtr();
1602
fprintf(stream, "\n/// \"%s\":%s is a%s complexType with complexContent extension of %s.\n", URI?URI:"", name, complexType.abstract?"n abstract":"", base);
1603
document(complexType.annotation);
1606
fprintf(stream, " struct %s\n {\n", t);
1608
fprintf(stream, " class %s\n {\n", t);
1611
fprintf(stream, "struct %s\n{\n", t);
1613
fprintf(stream, "class %s\n{ public:\n", t);
1614
else // TODO: what to do if base class is in another namespace and elements must be qualified in XML payload?
1615
{ const char *baseURI = NULL;
1616
if (p && p->schemaPtr())
1617
baseURI = p->schemaPtr()->targetNamespace;
1618
fprintf(stream, "class %s : public %s\n{ public:\n", t, cname(NULL, baseURI, base));
1624
pURI = p->schemaPtr()->targetNamespace;
1627
const char *b = cname(NULL, pURI, p->name);
1628
static int nesting = 0;
1629
if (cflag || fflag || anonymous)
1630
fprintf(stream, "/// INHERITED FROM %s:\n", b);
1631
else if (nesting == 0)
1632
fprintf(stream, "/* INHERITED FROM %s:\n", b);
1634
fprintf(stream, " INHERITED FROM %s:\n", b);
1636
if (p->complexContent && p->complexContent->extension)
1637
{ if (p->complexContent->extension->group)
1638
gen(pURI, *p->complexContent->extension->group); // schema URI?
1639
if (p->complexContent->extension->all)
1640
gen(pURI, *p->complexContent->extension->all);
1641
if (p->complexContent->extension->sequence)
1642
gen(pURI, *p->complexContent->extension->sequence);
1643
if (p->complexContent->extension->choice)
1644
gen(pURI, p->name, *p->complexContent->extension->choice);
1645
gen(pURI, p->complexContent->extension->attribute);
1646
gen(pURI, p->complexContent->extension->attributeGroup);
1647
if (p->complexContent->extension->anyAttribute)
1648
gen(pURI, *p->complexContent->extension->anyAttribute);
1649
p = p->complexContent->extension->complexTypePtr();
1652
if (cflag || fflag || anonymous)
1653
fprintf(stream, "// END OF INHERITED\n");
1654
else if (nesting == 0)
1655
fprintf(stream, " END OF INHERITED */\n");
1657
fprintf(stream, " END OF INHERITED\n");
1661
gen(pURI, p->all->element); // what about schema URI?
1664
else if (p->sequence)
1665
gen(pURI, *p->sequence);
1667
gen(pURI, p->name, *p->choice);
1670
gen(pURI, p->attribute);
1671
gen(pURI, p->attributeGroup);
1672
if (p->anyAttribute)
1673
gen(pURI, *p->anyAttribute);
1676
if (cflag || fflag || anonymous)
1677
fprintf(stream, "// END OF INHERITED\n");
1678
else if (nesting == 0)
1679
fprintf(stream, " END OF INHERITED */\n");
1681
fprintf(stream, " END OF INHERITED\n");
1685
if (complexType.complexContent->extension->group)
1686
gen(URI, *complexType.complexContent->extension->group);
1687
if (complexType.complexContent->extension->all)
1688
gen(URI, *complexType.complexContent->extension->all);
1689
if (complexType.complexContent->extension->sequence)
1690
gen(URI, *complexType.complexContent->extension->sequence);
1691
if (complexType.complexContent->extension->choice)
1692
gen(URI, name, *complexType.complexContent->extension->choice);
1693
gen(URI, complexType.complexContent->extension->attribute);
1694
gen(URI, complexType.complexContent->extension->attributeGroup);
1695
if (complexType.complexContent->extension->anyAttribute)
1696
gen(URI, *complexType.complexContent->extension->anyAttribute);
1699
fprintf(stream, "//\tunrecognized\n");
1703
fprintf(stream, "\n/// \"%s\":%s is a%s complexType.\n", URI?URI:"", name, complexType.abstract?"n abstract":"");
1704
document(complexType.annotation);
1707
fprintf(stream, " struct %s\n {\n", t);
1709
fprintf(stream, " class %s\n {\n", t);
1712
fprintf(stream, "struct %s\n{\n", t);
1713
else if (pflag && complexType.name)
1714
fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", t);
1716
fprintf(stream, "class %s\n{ public:\n", t);
1717
if (complexType.all)
1718
gen(URI, *complexType.all);
1719
else if (complexType.sequence)
1720
gen(URI, *complexType.sequence);
1721
else if (complexType.choice)
1722
gen(URI, name, *complexType.choice);
1723
else if (complexType.any)
1724
gen(URI, *complexType.any);
1726
gen(URI, complexType.attribute);
1727
gen(URI, complexType.attributeGroup);
1728
if (complexType.anyAttribute)
1729
gen(URI, *complexType.anyAttribute);
1730
if (complexType.mixed
1731
|| (complexType.complexContent && complexType.complexContent->extension && complexType.complexContent->extension->complexTypePtr() && complexType.complexContent->extension->complexTypePtr()->mixed))
1732
{ fprintf(stream, "/// TODO: this mixed complexType is user-definable.\n/// Consult the protocol documentation to change or insert declarations.\n/// Use wsdl2h option -d for xsd__anyType DOM (soap_dom_element).\n");
1734
{ fprintf(stream, pointerformat, "xsd__anyType", "__mixed");
1735
fprintf(stream, ";\t///< Catch mixed content in DOM soap_dom_element linked node structure.\n");
1738
{ fprintf(stream, elementformat, "_XML", "__mixed");
1739
fprintf(stream, ";\t///< Catch mixed content in XML string\n");
1743
{ if (!cflag && !(pflag && complexType.name) && !soapflag)
1744
{ if (!complexType.complexContent || !complexType.complexContent->extension || !complexType.complexContent->extension->complexTypePtr())
1745
{ fprintf(stream, "/// A handle to the soap struct that manages this instance (automatically set)\n");
1746
fprintf(stream, pointerformat, "struct soap", "soap");
1747
fprintf(stream, ";\n");
1751
fprintf(stream, "};\n");
1756
void Types::gen(const char *URI, const vector<xs__attribute>& attributes)
1757
{ for (vector<xs__attribute>::const_iterator attribute = attributes.begin(); attribute != attributes.end(); ++attribute)
1758
gen(URI, *attribute);
1761
void Types::gen(const char *URI, const xs__attribute& attribute)
1762
{ const char *name, *type, *nameURI = NULL, *typeURI = NULL;
1763
name = attribute.name;
1764
type = attribute.type;
1765
bool is_optional = attribute.use != required && attribute.use != default_ && attribute.use != fixed_ && !attribute.default_;
1766
document(attribute.annotation);
1767
if (!URI || strcmp(URI, attribute.schemaPtr()->targetNamespace))
1768
nameURI = attribute.schemaPtr()->targetNamespace;
1770
URI = attribute.schemaPtr()->targetNamespace;
1771
if (attribute.attributePtr()) // attribute ref
1772
{ char *prefix = NULL;
1773
name = attribute.attributePtr()->name;
1774
if (attribute.attributePtr()->schemaPtr())
1775
{ nameURI = typeURI = attribute.attributePtr()->schemaPtr()->targetNamespace;
1777
if (attribute.attributePtr()->type)
1778
{ type = attribute.attributePtr()->type;
1784
fprintf(stream, "/// Attribute reference %s.\n", attribute.ref);
1785
document(attribute.attributePtr()->annotation);
1786
fprintf(stream, attributeformat, pname(is_optional, prefix, typeURI, type), aname(NULL, nameURI, name)); // make sure no name - type clash
1788
else if (name && type)
1789
{ fprintf(stream, "/// Attribute %s of type %s.\n", name, type);
1790
fprintf(stream, attributeformat, pname(is_optional, NULL, URI, type), aname(NULL, nameURI, name)); // make sure no name - type clash
1792
else if (name && attribute.simpleTypePtr())
1793
{ fprintf(stream, "@");
1794
gen(URI, name, *attribute.simpleTypePtr(), true);
1795
fprintf(stream, (is_optional && !cflag && !sflag) ? pointerformat : elementformat, "", aname(NULL, nameURI, name));
1797
else if (attribute.ref)
1798
{ fprintf(stream, "/// Imported attribute reference %s.\n", attribute.ref);
1799
fprintf(stream, attributeformat, pname(is_optional, "_", NULL, attribute.ref), aname(NULL, NULL, attribute.ref));
1802
{ fprintf(stream, "/// Attribute '%s' has no type or ref: assuming string content.\n", name?name:"");
1803
fprintf(stream, attributeformat, tname(NULL, NULL, "xs:string"), aname(NULL, nameURI, name));
1805
switch (attribute.use)
1807
fprintf(stream, " 0:0");
1810
fprintf(stream, " 1");
1813
fprintf(stream, " 0");
1816
if (attribute.default_)
1818
{ const char *t = tname(NULL, typeURI?typeURI:URI, type);
1819
if (!strncmp(t, "unsigned ", 9))
1821
if (!strcmp(t, "bool")
1822
|| !strcmp(t, "char")
1823
|| !strcmp(t, "double")
1824
|| !strcmp(t, "float")
1825
|| !strcmp(t, "int")
1826
|| !strcmp(t, "long")
1827
|| !strcmp(t, "LONG64")
1828
|| !strcmp(t, "short")
1829
|| !strcmp(t, "ULONG64"))
1830
fprintf(stream, " = %s", attribute.default_);
1831
else if (!strncmp(t, "enum ", 5))
1832
fprintf(stream, " = %s", ename(t + 5, attribute.default_));
1833
else if (!strcmp(t, "char*")
1834
|| !strcmp(t, "char *") // not elegant
1835
|| !strcmp(t, "std::string")
1836
|| !strcmp(t, "std::string*")
1837
|| !strcmp(t, "std::string *")) // not elegant
1838
fprintf(stream, " = \"%s\"", cstring(attribute.default_));
1839
else if (!strcmp(t, "xsd__QName") && attribute.default__) // QName is in default__
1840
fprintf(stream, " = \"%s\"", cstring(attribute.default__));
1842
fprintf(stream, ";\t///< Default value=\"%s\".\n", attribute.default_);
1844
else if (attribute.use == required)
1845
fprintf(stream, ";\t///< Required attribute.\n");
1846
else if (attribute.use == prohibited)
1847
fprintf(stream, ";\t///< Prohibited attribute.\n");
1849
fprintf(stream, ";\t///< Optional attribute.\n");
1852
void Types::gen(const char *URI, const vector<xs__attributeGroup>& attributeGroups)
1853
{ for (vector<xs__attributeGroup>::const_iterator attributeGroup = attributeGroups.begin(); attributeGroup != attributeGroups.end(); ++attributeGroup)
1854
{ if ((*attributeGroup).attributeGroupPtr()) // attributeGroup ref
1855
{ if ((*attributeGroup).schemaPtr() == (*attributeGroup).attributeGroupPtr()->schemaPtr())
1856
{ gen(URI, (*attributeGroup).attributeGroupPtr()->attribute);
1857
gen(URI, (*attributeGroup).attributeGroupPtr()->attributeGroup);
1860
{ gen((*attributeGroup).attributeGroupPtr()->schemaPtr()->targetNamespace, (*attributeGroup).attributeGroupPtr()->attribute);
1861
gen((*attributeGroup).attributeGroupPtr()->schemaPtr()->targetNamespace, (*attributeGroup).attributeGroupPtr()->attributeGroup);
1863
if ((*attributeGroup).attributeGroupPtr()->anyAttribute)
1864
gen(URI, *(*attributeGroup).attributeGroupPtr()->anyAttribute);
1867
{ gen(URI, (*attributeGroup).attribute);
1868
gen(URI, (*attributeGroup).attributeGroup);
1869
if ((*attributeGroup).anyAttribute)
1870
gen(URI, *(*attributeGroup).anyAttribute);
1875
void Types::gen(const char *URI, const vector<xs__all>& alls)
1876
{ for (vector<xs__all>::const_iterator all = alls.begin(); all != alls.end(); ++all)
1880
void Types::gen(const char *URI, const xs__all& all)
1881
{ bool tmp_union1 = with_union;
1882
bool tmp_union2 = fake_union;
1885
gen(URI, all.element);
1886
with_union = tmp_union1;
1887
fake_union = tmp_union2;
1890
void Types::gen(const char *URI, const vector<xs__sequence>& sequences)
1891
{ for (vector<xs__sequence>::const_iterator sequence = sequences.begin(); sequence != sequences.end(); ++sequence)
1892
gen(URI, *sequence);
1895
void Types::gen(const char *URI, const vector<xs__sequence*>& sequences)
1896
{ for (vector<xs__sequence*>::const_iterator sequence = sequences.begin(); sequence != sequences.end(); ++sequence)
1897
gen(URI, **sequence);
1900
void Types::gen(const char *URI, const xs__sequence& sequence)
1901
{ const char *s = NULL;
1903
bool tmp_union1 = with_union;
1904
bool tmp_union2 = fake_union;
1907
if (sequence.maxOccurs && strcmp(sequence.maxOccurs, "1"))
1908
{ fprintf(stream, "/// SEQUENCE OF ELEMENTS");
1909
if (sequence.minOccurs)
1910
fprintf(stream, " minOccurs=\"%s\"", sequence.minOccurs);
1911
if (sequence.maxOccurs)
1912
fprintf(stream, " maxOccurs=\"%s\"", sequence.maxOccurs);
1913
fprintf(stream, "\n");
1914
document(sequence.annotation);
1915
s = sname(URI, "sequence");
1916
t = (char*)emalloc(strlen(s)+2);
1919
s = strstr(s, "__");
1922
fprintf(stream, sizeformat, "int", s + 1);
1923
if (sequence.minOccurs)
1924
fprintf(stream, " %s", sequence.minOccurs);
1925
if (sequence.maxOccurs && strcmp(sequence.maxOccurs, "1") && is_integer(sequence.maxOccurs))
1926
fprintf(stream, ":%s", sequence.maxOccurs);
1928
fprintf(stream, ";\n struct %s\n {\n", t);
1930
fprintf(stream, ";\n class %s\n {\n", t);
1933
document(sequence.annotation);
1934
gen(URI, sequence.group);
1935
gen(URI, sequence.element);
1936
gen(URI, sequence.sequence);
1937
gen(URI, sequence.choice);
1938
gen(URI, sequence.any);
1940
{ fprintf(stream, pointerformat, "}", s);
1941
fprintf(stream, ";\n// END OF SEQUENCE\n");
1943
with_union = tmp_union1;
1944
fake_union = tmp_union2;
1947
void Types::gen(const char *URI, const vector<xs__element>& elements)
1948
{ for (vector<xs__element>::const_iterator element = elements.begin(); element != elements.end(); ++element)
1952
void Types::gen(const char *URI, const xs__element& element)
1953
{ const char *name, *type, *nameURI = NULL, *typeURI = NULL;
1954
name = element.name;
1955
type = element.type;
1956
document(element.annotation);
1957
if (!URI || strcmp(URI, element.schemaPtr()->targetNamespace))
1958
nameURI = element.schemaPtr()->targetNamespace;
1960
URI = element.schemaPtr()->targetNamespace;
1961
if (element.elementPtr()) // element ref
1962
{ char *prefix = NULL;
1963
name = element.elementPtr()->name;
1964
if (element.elementPtr()->schemaPtr())
1965
{ nameURI = typeURI = element.elementPtr()->schemaPtr()->targetNamespace;
1967
if (element.elementPtr()->type)
1968
{ type = element.elementPtr()->type;
1974
document(element.elementPtr()->annotation);
1975
if (element.elementPtr()->abstract)
1976
{ fprintf(stream, "/// Reference %s to abstract element.\n", element.ref);
1977
gen_substitutions(URI, element);
1980
{ if (element.elementPtr()->substitutionsPtr() && !element.elementPtr()->substitutionsPtr()->empty())
1981
{ fprintf(stream, "/// Warning: element ref '%s' stands as the head of a substitutionGroup but is not declared abstract.\n", element.ref);
1982
fprintf(stderr, "Warning: element ref '%s' stands as the head of a substitutionGroup but is not declared abstract\n", element.ref);
1983
gen_substitutions(URI, element);
1985
if (element.maxOccurs && strcmp(element.maxOccurs, "1")) // maxOccurs != "1"
1986
{ const char *s = tnameptr(cflag && !zflag, prefix, typeURI, type);
1988
{ fprintf(stream, "/// Size of the dynamic array of %s is %s..%s\n", s, element.minOccurs ? element.minOccurs : "1", element.maxOccurs);
1989
fprintf(stream, sizeformat, "int", aname(NULL, NULL, name));
1990
if (is_integer(element.maxOccurs))
1991
fprintf(stream, " %s:%s", element.minOccurs ? element.minOccurs : "1", element.maxOccurs);
1992
fprintf(stream, ";\n");
1993
if (cflag && !zflag)
1994
{ fprintf(stream, "/// Array of length %s..%s\n", element.minOccurs ? element.minOccurs : "1", element.maxOccurs);
1995
fprintf(stream, elementformat, s, aname(NULL, nameURI, name));
1998
{ fprintf(stream, "/// Pointer to array of length %s..%s\n", element.minOccurs ? element.minOccurs : "1", element.maxOccurs);
1999
fprintf(stream, pointerformat, s, aname(NULL, nameURI, name));
2003
{ fprintf(stream, "/// Vector of %s with length %s..%s\n", s, element.minOccurs ? element.minOccurs : "1", element.maxOccurs);
2005
fprintf(stream, pointervectorformat, s, aname(NULL, nameURI, name));
2007
fprintf(stream, vectorformat, s, aname(NULL, nameURI, name));
2011
{ fprintf(stream, "/// Element reference %s.\n", element.ref);
2012
fprintf(stream, elementformat, pname((with_union && !cflag && !is_basetype(typeURI, type)) || fake_union || is_nillable(element), prefix, typeURI, type), aname(NULL, nameURI, name));
2016
else if (name && type)
2017
{ if (element.abstract)
2018
{ fprintf(stream, "/// Abstract element %s of type %s.\n", name, type);
2019
gen_substitutions(URI, element);
2022
{ if (element.substitutionsPtr() && !element.substitutionsPtr()->empty())
2023
{ fprintf(stream, "/// Warning: element '%s' stands as the head of a substitutionGroup but is not declared abstract.\n", name);
2024
fprintf(stderr, "Warning: element '%s' stands as the head of a substitutionGroup but is not declared abstract\n", name);
2025
gen_substitutions(URI, element);
2027
if (element.maxOccurs && strcmp(element.maxOccurs, "1")) // maxOccurs != "1"
2028
{ const char *s = tnameptr(cflag && !zflag, NULL, URI, type);
2030
{ fprintf(stream, "/// Size of array of %s is %s..%s\n", s, element.minOccurs ? element.minOccurs : "1", element.maxOccurs);
2031
fprintf(stream, sizeformat, "int", aname(NULL, NULL, name));
2032
if (is_integer(element.maxOccurs))
2033
fprintf(stream, " %s:%s", element.minOccurs ? element.minOccurs : "1", element.maxOccurs);
2034
fprintf(stream, ";\n");
2035
if (cflag && !zflag)
2036
{ fprintf(stream, "/// Array of length %s..%s\n", element.minOccurs ? element.minOccurs : "1", element.maxOccurs);
2037
fprintf(stream, elementformat, s, aname(NULL, nameURI, name));
2040
{ fprintf(stream, "/// Pointer to array of length %s..%s\n", element.minOccurs ? element.minOccurs : "1", element.maxOccurs);
2041
fprintf(stream, pointerformat, s, aname(NULL, nameURI, name));
2045
{ fprintf(stream, "/// Vector of %s with length %s..%s\n", s, element.minOccurs ? element.minOccurs : "1", element.maxOccurs);
2047
fprintf(stream, pointervectorformat, s, aname(NULL, nameURI, name));
2049
fprintf(stream, vectorformat, s, aname(NULL, nameURI, name));
2053
{ fprintf(stream, "/// Element %s of type %s.\n", name, type);
2054
fprintf(stream, elementformat, pname((with_union && !cflag && !is_basetype(URI, type)) || fake_union || is_nillable(element), NULL, URI, type), aname(NULL, nameURI, name));
2058
else if (name && element.simpleTypePtr())
2059
{ document(element.simpleTypePtr()->annotation);
2060
if (element.maxOccurs && strcmp(element.maxOccurs, "1")) // maxOccurs != "1"
2061
{ fprintf(stream, "/// Size of %s array is %s..%s\n", name, element.minOccurs ? element.minOccurs : "1", element.maxOccurs);
2062
fprintf(stream, sizeformat, "int", aname(NULL, NULL, name));
2063
if (is_integer(element.maxOccurs))
2064
fprintf(stream, " %s:%s", element.minOccurs ? element.minOccurs : "1", element.maxOccurs);
2065
fprintf(stream, ";\n");
2067
gen(URI, name, *element.simpleTypePtr(), true);
2068
if (is_nillable(element)
2069
|| element.maxOccurs && strcmp(element.maxOccurs, "1") // maxOccurs != "1"
2070
|| (with_union && !cflag) || fake_union)
2071
fprintf(stream, pointerformat, "", aname(NULL, nameURI, name));
2073
fprintf(stream, elementformat, "", aname(NULL, nameURI, name));
2075
else if (name && element.complexTypePtr())
2076
{ if (element.maxOccurs && strcmp(element.maxOccurs, "1")) // maxOccurs != "1"
2077
{ fprintf(stream, "/// Size of %s array is %s..%s\n", name, element.minOccurs ? element.minOccurs : "1", element.maxOccurs);
2078
fprintf(stream, sizeformat, "int", aname(NULL, NULL, name));
2079
if (is_integer(element.maxOccurs))
2080
fprintf(stream, " %s:%s", element.minOccurs ? element.minOccurs : "1", element.maxOccurs);
2081
fprintf(stream, ";\n");
2083
gen(URI, name, *element.complexTypePtr(), true);
2084
if (is_nillable(element)
2085
|| element.maxOccurs && strcmp(element.maxOccurs, "1") // maxOccurs != "1"
2086
|| (with_union && !cflag) || fake_union)
2087
fprintf(stream, pointerformat, "}", aname(NULL, nameURI, name));
2089
fprintf(stream, elementformat, "}", aname(NULL, nameURI, name));
2091
else if (element.ref)
2092
{ fprintf(stream, "/// Imported element reference %s.\n", element.ref);
2093
fprintf(stream, elementformat, pname((with_union && !cflag) || fake_union || is_nillable(element), "_", NULL, element.ref), aname(NULL, nameURI, element.ref));
2096
{ fprintf(stream, "/// Element '%s' has no type or ref: assuming XML content.\n", name?name:"");
2097
if (element.maxOccurs && strcmp(element.maxOccurs, "1")) // maxOccurs != "1"
2098
{ if (cflag || sflag)
2099
{ fprintf(stream, sizeformat, "int", aname(NULL, NULL, name));
2100
if (is_integer(element.maxOccurs))
2101
fprintf(stream, " %s:%s", element.minOccurs ? element.minOccurs : "1", element.maxOccurs);
2102
fprintf(stream, ";\n");
2103
fprintf(stream, "/// Pointer to array of XML.\n");
2104
fprintf(stream, pointerformat, "_XML", aname(NULL, nameURI, name));
2107
{ fprintf(stream, "/// Vector of XML with length %s..%s\n", element.minOccurs ? element.minOccurs : "1", element.maxOccurs);
2109
fprintf(stream, pointervectorformat, "_XML", aname(NULL, nameURI, name));
2111
fprintf(stream, vectorformat, "_XML", aname(NULL, nameURI, name));
2115
fprintf(stream, elementformat, "_XML", aname(NULL, nameURI, name));
2118
fprintf(stream, "/// Element has no type or ref.");
2119
if (!element.abstract && !(element.elementPtr() && element.elementPtr()->abstract))
2120
{ if (!element.minOccurs && !element.nillable && !element.default_)
2121
fprintf(stream, " 1");
2122
else if (element.minOccurs)
2123
fprintf(stream, " %s", element.minOccurs);
2124
if (element.maxOccurs && strcmp(element.maxOccurs, "1") && is_integer(element.maxOccurs))
2125
fprintf(stream, ":%s", element.maxOccurs);
2126
if (element.default_)
2127
{ // determine whether the element can be assigned a default value, this is dependent on the choice of mapping for primitive types
2129
{ const char *t = tname(NULL, typeURI?typeURI:URI, type);
2130
if (!strncmp(t, "unsigned ", 9))
2132
if (!strcmp(t, "bool")
2133
|| !strcmp(t, "char")
2134
|| !strcmp(t, "double")
2135
|| !strcmp(t, "float")
2136
|| !strcmp(t, "int")
2137
|| !strcmp(t, "long")
2138
|| !strcmp(t, "LONG64")
2139
|| !strcmp(t, "short")
2140
|| !strcmp(t, "ULONG64"))
2141
fprintf(stream, " = %s", element.default_);
2142
else if (!strncmp(t, "enum ", 5))
2143
fprintf(stream, " = %s", ename(t + 5, element.default_));
2144
else if (!strcmp(t, "char*")
2145
|| !strcmp(t, "char *") // not elegant
2146
|| !strcmp(t, "std::string")
2147
|| !strcmp(t, "std::string*")
2148
|| !strcmp(t, "std::string *")) // not elegant
2149
fprintf(stream, " = \"%s\"", cstring(element.default_));
2150
else if (!strcmp(t, "xsd__QName") && element.default__) // QName is in value_
2151
fprintf(stream, " = \"%s\"", cstring(element.default__));
2153
fprintf(stream, ";\t///< Default value=\"%s\".\n", element.default_);
2155
else if (element.nillable)
2156
fprintf(stream, ";\t///< Nullable pointer.\n");
2157
else if ((!element.minOccurs || !strcmp(element.minOccurs, "1")) && (!element.maxOccurs || !strcmp(element.maxOccurs, "1")))
2158
fprintf(stream, ";\t///< Required element.\n");
2159
else if (element.minOccurs && !strcmp(element.minOccurs, "0") && (!element.maxOccurs || !strcmp(element.maxOccurs, "1")))
2160
fprintf(stream, ";\t///< Optional element.\n");
2162
fprintf(stream, ";\n");
2166
void Types::gen(const char *URI, const vector<xs__group>& groups)
2167
{ for (vector<xs__group>::const_iterator group = groups.begin(); group != groups.end(); ++group)
2171
void Types::gen(const char *URI, const xs__group& group)
2172
{ if (group.groupPtr())
2173
{ if (group.schemaPtr() == group.groupPtr()->schemaPtr())
2174
gen(URI, *group.groupPtr());
2176
gen(group.groupPtr()->schemaPtr()->targetNamespace, *group.groupPtr());
2179
gen(URI, group.all->element);
2180
else if (group.sequence)
2181
gen(URI, group.sequence->element);
2182
else if (group.choice)
2183
gen(URI, NULL, *group.choice);
2186
void Types::gen(const char *URI, const vector<xs__choice>& choices)
2187
{ for (vector<xs__choice>::const_iterator choice = choices.begin(); choice != choices.end(); ++choice)
2188
gen(URI, NULL, *choice);
2191
void Types::gen(const char *URI, const char *name, const xs__choice& choice)
2192
{ const char *r = NULL, *s = NULL, *t = NULL;
2193
bool use_union = !uflag;
2194
bool wrap_union = false;
2196
if (!URI && choice.schemaPtr())
2197
URI = choice.schemaPtr()->targetNamespace;
2198
fprintf(stream, "/// CHOICE OF ELEMENTS FOR choice");
2199
document(choice.annotation);
2200
if (choice.minOccurs)
2201
fprintf(stream, " minOccurs=\"%s\"", choice.minOccurs);
2202
if (choice.maxOccurs)
2203
fprintf(stream, " maxOccurs=\"%s\"", choice.maxOccurs);
2204
fprintf(stream, "\n");
2205
if (!choice.group.empty() || !choice.sequence.empty())
2207
else if (cflag || sflag)
2208
{ for (vector<xs__element>::const_iterator el = choice.element.begin(); el != choice.element.end(); el++)
2209
{ if ((*el).maxOccurs && strcmp((*el).maxOccurs, "1"))
2210
{ use_union = false;
2217
s = strstr(t, "__union");
2224
if (choice.maxOccurs && strcmp(choice.maxOccurs, "1"))
2226
{ // Generate a wrapper when we need a union within a union
2228
fprintf(stream, " struct __%s\n {\n", t);
2230
fprintf(stream, sizeformat, "int", r);
2231
if (choice.minOccurs)
2232
fprintf(stream, " %s", choice.minOccurs);
2233
if (choice.maxOccurs && strcmp(choice.maxOccurs, "1") && is_integer(choice.maxOccurs))
2234
fprintf(stream, ":%s", choice.maxOccurs);
2236
fprintf(stream, ";\n struct _%s\n {\n", t);
2238
fprintf(stream, ";\n class _%s\n {\n", t);
2240
if (!with_union || wrap_union)
2241
{ fprintf(stream, choiceformat, "int", r);
2242
if (choice.minOccurs)
2243
fprintf(stream, " %s", choice.minOccurs);
2244
fprintf(stream, ";\t///< Union %s selector: set to SOAP_UNION_%s_<fieldname>%s\n", t, t, choice.minOccurs && !strcmp(choice.minOccurs, "0") ? " or 0" : "");
2246
fprintf(stream, "/// Union for choice in type %s\n", cname(NULL, URI, name));
2247
fprintf(stream, " union %s\n {\n", t);
2249
tmp_union = with_union;
2253
{ tmp_union = fake_union;
2256
gen(URI, choice.group);
2257
gen(URI, choice.element);
2258
gen(URI, choice.sequence); // TODO: check potential name conflicts
2259
gen(URI, choice.choice); // TODO: check potential name conflicts
2260
gen(URI, choice.any);
2262
{ with_union = tmp_union;
2263
if (!with_union || wrap_union)
2264
fprintf(stream, elementformat, "}", s+2);
2265
if (choice.maxOccurs && strcmp(choice.maxOccurs, "1"))
2266
{ fprintf(stream, ";\n");
2267
fprintf(stream, pointerformat, "}", s);
2269
fprintf(stream, ";\n");
2271
{ fprintf(stream, elementformat, "}", s);
2272
fprintf(stream, ";\n");
2276
fake_union = tmp_union;
2277
fprintf(stream, "// END OF CHOICE\n");
2280
void Types::gen(const char *URI, const vector<xs__any>& anys)
2281
{ for (vector<xs__any>::const_iterator any = anys.begin(); any != anys.end(); ++any)
2285
void Types::gen(const char *URI, const xs__any& any)
2286
{ fprintf(stream, "/// TODO: <any");
2288
fprintf(stream, " namespace=\"%s\"", any.namespace_);
2290
fprintf(stream, " minOccurs=\"%s\"", any.minOccurs);
2292
fprintf(stream, " maxOccurs=\"%s\"", any.maxOccurs);
2293
fprintf(stream, ">\n/// TODO: Schema extensibility is user-definable.\n/// Consult the protocol documentation to change or insert declarations.\n/// Use wsdl2h option -x to remove this element.\n/// Use wsdl2h option -d for xsd__anyType DOM (soap_dom_element).\n");
2295
{ if (any.maxOccurs && strcmp(any.maxOccurs, "1"))
2296
{ if (cflag || sflag)
2297
{ fprintf(stream, "/// Size of the dynamic array of DOM is %s..%s\n", any.minOccurs ? any.minOccurs : "1", any.maxOccurs);
2298
fprintf(stream, sizeformat, "int", "");
2299
fprintf(stream, ";\n");
2300
fprintf(stream, pointerformat, "xsd__anyType", "__any");
2303
fprintf(stream, elementformat, "std::vector<xsd__anyType>", "__any");
2306
fprintf(stream, pointerformat, "xsd__anyType", "__any");
2307
fprintf(stream, ";\t///< Store element content in DOM soap_dom_element linked node structure.\n");
2310
{ if (any.maxOccurs && strcmp(any.maxOccurs, "1"))
2311
{ if (cflag || sflag)
2312
{ fprintf(stream, "/// Size of the dynamic array of XML is %s..%s\n", any.minOccurs ? any.minOccurs : "1", any.maxOccurs);
2313
fprintf(stream, sizeformat, "int", "");
2314
fprintf(stream, ";\n");
2315
fprintf(stream, pointerformat, "_XML", "__any");
2318
fprintf(stream, elementformat, "std::vector<_XML>", "__any");
2321
fprintf(stream, elementformat, "_XML", "__any");
2322
fprintf(stream, ";\t///< Catch any element content in XML string.\n");
2326
void Types::gen(const char *URI, const xs__anyAttribute& anyAttribute)
2327
{ if (anyAttribute.namespace_)
2328
fprintf(stream, "/// <anyAttribute namespace=\"%s\">\n", anyAttribute.namespace_);
2329
fprintf(stream, "/// TODO: Schema extensibility is user-definable.\n/// Consult the protocol documentation to change or insert declarations.\n/// Use wsdl2h option -x to remove this attribute.\n/// Use wsdl2h option -d for xsd__anyAttribute DOM (soap_dom_attribute).\n");
2331
{ fprintf(stream, attributeformat, "xsd__anyAttribute", "__anyAttribute");
2332
fprintf(stream, ";\t///< Store anyAttribute content in DOM soap_dom_attribute linked node structure.\n");
2335
{ fprintf(stream, attributeformat, "_XML", "__anyAttribute");
2336
fprintf(stream, ";\t///< A placeholder that has no effect: please see comment.\n");
2340
void Types::gen_soap_array(const char *name, const char *t, const char *item, const char *type)
2341
{ char *tmp = NULL, *dims = NULL, size[8];
2343
{ tmp = (char*)emalloc(strlen(type) + 1);
2348
dims = strrchr(tmp, '[');
2351
fprintf(stream, "/// SOAP encoded array of %s\n", tmp ? tmp : "xs:anyType");
2353
fprintf(stream, "struct %s\n{\n", t);
2355
fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", t);
2357
fprintf(stream, "class %s\n{ public:\n", t);
2359
{ char *s = strchr(dims, ']');
2361
sprintf(size, "[%d]", (int)(s - dims + 1));
2364
{ if (strchr(tmp, '[') != NULL)
2365
{ gen_soap_array(NULL, "", item, tmp);
2366
fprintf(stream, arrayformat, "}", item ? aname(NULL, NULL, item) : "");
2367
fprintf(stream, ";\n");
2370
{ const char *s = pname(!is_basetype(NULL, tmp), NULL, NULL, tmp);
2371
fprintf(stream, "/// Pointer to array of %s.\n", s);
2372
fprintf(stream, arrayformat, s, item ? aname(NULL, NULL, item) : "");
2373
fprintf(stream, ";\n");
2376
fprintf(stream, "/// Size of the multidimensional dynamic array with dimensions=%s\n", size);
2378
fprintf(stream, "/// Size of the dynamic array.\n");
2379
fprintf(stream, sizeformat, "int", size);
2380
fprintf(stream, ";\n/// Offset for partially transmitted arrays (uncomment only when required).\n");
2381
fprintf(stream, offsetformat, "int", size);
2382
fprintf(stream, ";\n");
2385
{ // TODO: how to handle generic SOAP array? E.g. as an array of anyType
2386
fprintf(stream, "// TODO: add declarations to handle generic SOAP-ENC:Array (array of anyType)\n");
2392
void Types::gen_substitutions(const char *URI, const xs__element &element)
2393
{ const std::vector<xs__element*> *substitutions;
2395
const char *r = NULL, *s = NULL;
2396
bool use_union = !uflag;
2397
bool wrap_union = false;
2399
if (!URI && element.schemaPtr())
2400
URI = element.schemaPtr()->targetNamespace;
2401
if (element.elementPtr())
2402
{ name = element.elementPtr()->name;
2403
substitutions = element.elementPtr()->substitutionsPtr();
2406
{ name = element.name;
2407
substitutions = element.substitutionsPtr();
2409
fprintf(stream, "/// CHOICE OF ELEMENTS FOR substitutionGroup=\"%s\"", name);
2410
if (element.minOccurs)
2411
fprintf(stream, " minOccurs=\"%s\"", element.minOccurs);
2412
if (element.maxOccurs)
2413
fprintf(stream, " maxOccurs=\"%s\"", element.maxOccurs);
2414
fprintf(stream, " with elements");
2415
for (std::vector<xs__element*>::const_iterator i1 = substitutions->begin(); i1 != substitutions->end(); ++i1)
2416
fprintf(stream, " %s", (*i1)->name);
2417
fprintf(stream, "\n");
2419
{ const char *t = uname(URI);
2420
s = strstr(t, "__union");
2423
r = aname(NULL, NULL, name);
2424
if (element.maxOccurs && strcmp(element.maxOccurs, "1"))
2426
{ // Generate a wrapper when we need a union within a union
2428
fprintf(stream, " struct __%s\n {\n", t);
2430
fprintf(stream, sizeformat, "int", r);
2431
if (element.minOccurs)
2432
fprintf(stream, " %s", element.minOccurs);
2433
if (element.maxOccurs && strcmp(element.maxOccurs, "1") && is_integer(element.maxOccurs))
2434
fprintf(stream, ":%s", element.maxOccurs);
2436
fprintf(stream, ";\n struct _%s\n {\n", t);
2438
fprintf(stream, ";\n class _%s\n {\n", t);
2440
if (!with_union || wrap_union)
2441
{ fprintf(stream, choiceformat, "int", r);
2442
if (element.minOccurs)
2443
fprintf(stream, " %s", element.minOccurs);
2444
fprintf(stream, ";\t///< Union %s selector: set to SOAP_UNION_%s_<fieldname>%s\n", t, t, element.minOccurs && !strcmp(element.minOccurs, "0") ? " or 0" : "");
2445
fprintf(stream, "/// Union for substitutionGroup=\"%s\"\n", name);
2446
fprintf(stream, " union %s\n {\n", t);
2448
tmp_union = with_union;
2452
{ tmp_union = fake_union;
2455
for (vector<xs__element*>::const_iterator i2 = substitutions->begin(); i2 != substitutions->end(); ++i2)
2458
{ with_union = tmp_union;
2459
if (!with_union || wrap_union)
2460
fprintf(stream, elementformat, "}", s);
2461
if (element.maxOccurs && strcmp(element.maxOccurs, "1"))
2462
{ fprintf(stream, ";\n");
2463
fprintf(stream, pointerformat, "}", s);
2465
fprintf(stream, ";\n");
2467
{ fprintf(stream, elementformat, "}", s);
2468
fprintf(stream, ";\n");
2472
fake_union = tmp_union;
2473
fprintf(stream, "// END OF CHOICE\n");
2476
void Types::document(const xs__annotation *annotation)
2477
{ if (annotation && annotation->documentation)
2478
{ fprintf(stream, "/// @brief");
2479
documentation(annotation->documentation);
2483
void Types::modify(const char *name)
2484
{ // TODO: consider support removal of elements/attributes with ns__X = $- Y
2485
const char *s = modtypemap[name];
2489
fprintf(stream, "/// Member declared in %s\n ", mapfile);
2495
const char* Types::format(const char *text)
2496
{ const char *s = text;
2499
while (*s && *s != '$')
2503
fputc('\n', stream);
2506
fputc('\t', stream);
2509
fputc(s[1], stream);
2517
fputc('\n', stream);
2521
////////////////////////////////////////////////////////////////////////////////
2523
// Type map file parsing
2525
////////////////////////////////////////////////////////////////////////////////
2527
static char *getline(char *s, size_t n, FILE *fd)
2547
if (c == '\n' || c == EOF)
2555
if (!*s && c == EOF)
2560
static const char *nonblank(const char *s)
2561
{ while (*s && isspace(*s))
2566
static const char *fill(char *t, int n, const char *s, int e)
2569
while (*s && *s != e && --i)
2571
while (*s && *s != e)
2579
{ while (isspace(*--t) && i--)
2586
////////////////////////////////////////////////////////////////////////////////
2590
////////////////////////////////////////////////////////////////////////////////
2592
static const char *utf8(char *t, const char *s)
2593
{ unsigned int c = 0;
2595
c = (unsigned char)*s;
2603
c = ((c & 0x1F) << 6) | c1;
2607
c = ((c & 0x0F) << 12) | (c1 << 6) | c2;
2611
c = ((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
2615
c = ((c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
2617
c = ((c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | *++s & 0x3F;
2623
sprintf(t, "_x%.4x", c);
2627
static const char *cstring(const char *s)
2631
for (n = 0, r = s; *r; n++, r++)
2632
if (*r == '"' || *r == '\\')
2636
r = t = (char*)emalloc(n + 1);
2638
{ if (*s == '"' || *s == '\\')
2643
{ sprintf(t, "\\%03o", (unsigned int)(unsigned char)*s);
2653
static const char *xstring(const char *s)
2657
for (n = 0, r = s; *r; n++, r++)
2658
{ if (*r < 32 || *r >= 127)
2660
else if (*r == '<' || *r == '>')
2666
else if (*r == '\\')
2669
r = t = (char*)emalloc(n + 1);
2671
{ if (*s < 32 || *s >= 127)
2672
{ sprintf(t, "&#%.2x;", (unsigned char)*s);
2676
{ strcpy(t, "<");
2680
{ strcpy(t, ">");
2684
{ strcpy(t, "&");
2688
{ strcpy(t, """);
2691
else if (*s == '\\')
2692
{ strcpy(t, "\\\\");
2702
static bool is_integer(const char *s)
2703
{ if ((*s == '-' || *s == '+') && s[1])
2705
if (!*s || strlen(s) > 9)
2707
while (*s && isdigit(*s))
2712
static void documentation(const char *text)
2713
{ const char *s = text;
2727
{ fputc(' ', stream);
2735
fputc('\n', stream);
2738
////////////////////////////////////////////////////////////////////////////////
2742
////////////////////////////////////////////////////////////////////////////////
2744
void *emalloc(size_t size)
2745
{ void *p = malloc(size);
2747
{ fprintf(stderr, "Error: Malloc failed\n");
2753
char *estrdup(const char *s)
2754
{ char *t = (char*)emalloc(strlen(s) + 1);