Mercurial > repos > ktnyt > gembassy
diff GEMBASSY-1.0.3/gsoap/wsdl/types.cpp @ 0:8300eb051bea draft
Initial upload
author | ktnyt |
---|---|
date | Fri, 26 Jun 2015 05:19:29 -0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GEMBASSY-1.0.3/gsoap/wsdl/types.cpp Fri Jun 26 05:19:29 2015 -0400 @@ -0,0 +1,3289 @@ +/* + types.cpp + + Generate gSOAP types from XML schemas (e.g. embedded in WSDL). + +-------------------------------------------------------------------------------- +gSOAP XML Web services tools +Copyright (C) 2001-2013, Robert van Engelen, Genivia Inc. All Rights Reserved. +This software is released under one of the following licenses: +GPL or Genivia's license for commercial use. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia, Inc., contact@genivia.com +-------------------------------------------------------------------------------- + +*/ + +#include "types.h" + +static char *getline(char *s, size_t n, FILE *fd); +static const char *nonblank(const char *s); +static const char *fill(char *t, int n, const char *s, int e); +static const char *utf8(char *t, const char *s); +static const char *cstring(const char *s); +static const char *xstring(const char *s); +static bool is_integer(const char *s); +static LONG64 to_integer(const char *s); +static void documentation(const char *text); +static void operations(const char *t); + +static int comment_nest = 0; /* keep track of block comments to avoid nesting */ + +//////////////////////////////////////////////////////////////////////////////// +// +// Keywords and reserved words +// +//////////////////////////////////////////////////////////////////////////////// + +static const char *keywords[] = +{ "and", + "asm", + "auto", + "bool", + "break", + "case", + "catch", + "char", + "class", + "const", + "const_cast", + "continue", + "default", + "delete", + "do", + "double", + "dynamic_cast", + "else", + "enum", + "errno", + "explicit", + "export", + "extern", + "false", + "FILE", + "float", + "for", + "friend", + "goto", + "if", + "inline", + "int", + "interface", + "long", + "LONG64", + "max", + "min", + "mustUnderstand", + "mutable", + "namespace", + "new", + "not", + "NULL", + "operator", + "or", + "private", + "protected", + "public", + "_QName", + "register", + "reinterpret_cast", + "restrict", + "return", + "short", + "signed", + "size_t", + "sizeof", + "soap", + "static", + "static_cast", + "struct", + "switch", + "template", + "this", + "throw", + "time_t", + "true", + "typedef", + "typeid", + "typeof", + "typename", + "ULONG64", + "union", + "unsigned", + "using", + "virtual", + "void", + "volatile", + "wchar_t", + "while", + "XML", + "_XML", + "xor", +}; + +//////////////////////////////////////////////////////////////////////////////// +// +// Types methods +// +//////////////////////////////////////////////////////////////////////////////// + +Types::Types() +{ init(); +} + +int Types::read(const char *file) +{ FILE *fd; + char buf[1024], xsd[1024], def[1024], use[1024], ptr[1024], uri[1024]; + const char *s; + short copy = 0; + strcpy(buf, file); + fd = fopen(buf, "r"); + if (!fd && import_path) + { strcpy(buf, import_path); + strcat(buf, "/"); + strcat(buf, file); + fd = fopen(buf, "r"); + } + if (!fd) + { fprintf(stderr, "Cannot open file '%s'\n", buf); + return SOAP_EOF; + } + fprintf(stderr, "Reading type definitions from type map file '%s'\n", buf); + while (getline(buf, sizeof(buf), fd)) + { s = buf; + if (copy) + { if (*s == ']') + copy = 0; + else + fprintf(stream, "%s\n", buf); + } + else if (*s == '[') + copy = 1; + else if (*s == '<') + { s = fill(uri, sizeof(uri), s+1, -1); + infile[infiles++] = estrdup(uri); + if (infiles >= MAXINFILES) + { fprintf(stderr, "wsdl2h: too many files\n"); + exit(1); + } + } + else if (*s == '>') + { s = fill(uri, sizeof(uri), s+1, -1); + if (!outfile) + { outfile = estrdup(uri); + stream = fopen(outfile, "w"); + if (!stream) + { fprintf(stderr, "Cannot write to %s\n", outfile); + exit(1); + } + if (cppnamespace) + fprintf(stream, "namespace %s {\n", cppnamespace); + fprintf(stderr, "Saving %s\n\n", outfile); + } + } + else if (*s && *s != '#') + { s = fill(xsd, sizeof(xsd), s, '='); + if (strstr(xsd, "__")) + { if (s && *s == '=') + { s = fill(use, sizeof(use), s+1, '|'); + if (*xsd && *use) + { s = estrdup(xsd); + eqvtypemap[s] = estrdup(use); + } + } + else + { s = fill(def, sizeof(def), s, '|'); + s = fill(use, sizeof(use), s, '|'); + s = fill(ptr, sizeof(ptr), s, '|'); + if (*xsd) + { s = estrdup(xsd); + if (*def == '$') + { const char *t = modtypemap[s]; + if (t) + { char *r = (char*)emalloc(strlen(t) + strlen(def) + 1); + strcpy(r, t); + strcat(r, def); + free((void*)modtypemap[s]); + modtypemap[s] = r; + } + else + modtypemap[s] = estrdup(def); + } + else + { if (*def) + { if (strcmp(def, "...")) + deftypemap[s] = estrdup(def); + } + else + deftypemap[s] = ""; + if (*use) + usetypemap[s] = estrdupf(use); + else + usetypemap[s] = estrdupf(xsd); + if (*ptr) + ptrtypemap[s] = estrdupf(ptr); + } + } + } + } + else if (*xsd) + { s = fill(uri, sizeof(uri), s, 0); + if (uri[0] == '"') + { uri[strlen(uri) - 1] = '\0'; + nsprefix(xsd, estrdup(uri + 1)); + } + else if (uri[0] == '<') + { uri[strlen(uri) - 1] = '\0'; + char *s = estrdup(uri + 1); + nsprefix(xsd, s); + exturis.insert(s); + } + else + nsprefix(xsd, estrdup(uri)); + } + } + } + fclose(fd); + return SOAP_OK; +} + +void Types::init() +{ snum = 1; + unum = 1; + gnum = 1; + with_union = false; + fake_union = false; + knames.insert(keywords, keywords + sizeof(keywords)/sizeof(char*)); + if (cflag) + { deftypemap["xsd__ur_type"] = ""; + if (dflag) + { usetypemap["xsd__ur_type"] = "xsd__anyType"; + ptrtypemap["xsd__ur_type"] = "xsd__anyType*"; + } + else + { usetypemap["xsd__ur_type"] = "_XML"; + ptrtypemap["xsd__ur_type"] = "_XML"; + } + } + else + { deftypemap["xsd__ur_type"] = "class xsd__ur_type { _XML __item; struct soap *soap; };"; + usetypemap["xsd__ur_type"] = "xsd__ur_type"; + } + if (cflag) + { deftypemap["xsd__anyType"] = ""; + if (dflag) + { usetypemap["xsd__anyType"] = "xsd__anyType"; + ptrtypemap["xsd__anyType"] = "xsd__anyType*"; + } + else + { usetypemap["xsd__anyType"] = "_XML"; + ptrtypemap["xsd__anyType"] = "_XML"; + } + } + else + { if (dflag) + { deftypemap["xsd__anyType"] = ""; + usetypemap["xsd__anyType"] = "xsd__anyType"; + ptrtypemap["xsd__anyType"] = "xsd__anyType*"; + } + else + { deftypemap["xsd__anyType"] = "class xsd__anyType { _XML __item; struct soap *soap; };"; + usetypemap["xsd__anyType"] = "xsd__anyType*"; + } + } + deftypemap["xsd__any"] = ""; + if (dflag) + { usetypemap["xsd__any"] = "xsd__anyType"; + ptrtypemap["xsd__any"] = "xsd__anyType*"; + } + else + { usetypemap["xsd__any"] = "_XML"; + ptrtypemap["xsd__any"] = "_XML"; + } + deftypemap["xsd__anyAttribute"] = ""; + if (dflag) + { usetypemap["xsd__anyAttribute"] = "xsd__anyAttribute"; + ptrtypemap["xsd__anyAttribute"] = "xsd__anyAttribute*"; + } + else + { usetypemap["xsd__anyAttribute"] = "_XML"; + ptrtypemap["xsd__anyAttribute"] = "_XML"; + } + if (cflag) + { deftypemap["xsd__base64Binary"] = "struct xsd__base64Binary\n{\tunsigned char *__ptr;\n\tint __size;\n\tchar *id, *type, *options; // NOTE: non-NULL for DIMEM/MIME/MTOM XOP attachments only\n};"; + usetypemap["xsd__base64Binary"] = "struct xsd__base64Binary"; + } + else + { deftypemap["xsd__base64Binary"] = "class xsd__base64Binary\n{\tunsigned char *__ptr;\n\tint __size;\n\tchar *id, *type, *options; // NOTE: non-NULL for DIMEM/MIME/MTOM XOP attachments only\n\tstruct soap *soap;\n};"; + usetypemap["xsd__base64Binary"] = "xsd__base64Binary"; + } + if (cflag) + { if (eflag) + deftypemap["xsd__boolean"] = "enum xsd__boolean { false_, true_ };"; + else + deftypemap["xsd__boolean"] = "enum xsd__boolean { xsd__boolean__false_, xsd__boolean__true_ };"; + usetypemap["xsd__boolean"] = "enum xsd__boolean"; + } + else + { deftypemap["xsd__boolean"] = ""; + usetypemap["xsd__boolean"] = "bool"; + } + deftypemap["xsd__byte"] = "typedef char xsd__byte;"; + usetypemap["xsd__byte"] = "xsd__byte"; + deftypemap["xsd__dateTime"] = ""; + usetypemap["xsd__dateTime"] = "time_t"; + deftypemap["xsd__double"] = ""; + usetypemap["xsd__double"] = "double"; + deftypemap["xsd__float"] = ""; + usetypemap["xsd__float"] = "float"; + if (cflag) + { deftypemap["xsd__hexBinary"] = "struct xsd__hexBinary { unsigned char *__ptr; int __size; };"; + usetypemap["xsd__hexBinary"] = "struct xsd__hexBinary"; + } + else + { deftypemap["xsd__hexBinary"] = "class xsd__hexBinary { unsigned char *__ptr; int __size; };"; + usetypemap["xsd__hexBinary"] = "xsd__hexBinary"; + } + deftypemap["xsd__int"] = ""; + usetypemap["xsd__int"] = "int"; + deftypemap["xsd__long"] = ""; + usetypemap["xsd__long"] = "LONG64"; + deftypemap["xsd__short"] = ""; + usetypemap["xsd__short"] = "short"; + if (cflag || sflag) + { deftypemap["xsd__string"] = ""; + usetypemap["xsd__string"] = "char*"; + } + else + { deftypemap["xsd__string"] = ""; + usetypemap["xsd__string"] = "std::string"; + } + if (cflag || sflag) + { deftypemap["xsd__QName"] = ""; + usetypemap["xsd__QName"] = "_QName"; + ptrtypemap["xsd__QName"] = "_QName"; + } + else + { deftypemap["xsd__QName"] = "typedef std::string xsd__QName;"; + usetypemap["xsd__QName"] = "xsd__QName"; + } + deftypemap["xsd__unsignedByte"] = "typedef unsigned char xsd__unsignedByte;"; + usetypemap["xsd__unsignedByte"] = "xsd__unsignedByte"; + deftypemap["xsd__unsignedInt"] = ""; + usetypemap["xsd__unsignedInt"] = "unsigned int"; + deftypemap["xsd__unsignedLong"] = ""; + usetypemap["xsd__unsignedLong"] = "ULONG64"; + deftypemap["xsd__unsignedShort"] = ""; + usetypemap["xsd__unsignedShort"] = "unsigned short"; + if (cflag) + { deftypemap["SOAP_ENC__base64Binary"] = "struct SOAP_ENC__base64Binary { unsigned char *__ptr; int __size; };"; + usetypemap["SOAP_ENC__base64Binary"] = "struct SOAP_ENC__base64Binary"; + deftypemap["SOAP_ENC__base64"] = "struct SOAP_ENC__base64 { unsigned char *__ptr; int __size; };"; + usetypemap["SOAP_ENC__base64"] = "struct SOAP_ENC__base64"; + } + else + { deftypemap["SOAP_ENC__base64Binary"] = "class SOAP_ENC__base64Binary { unsigned char *__ptr; int __size; };"; + usetypemap["SOAP_ENC__base64Binary"] = "SOAP_ENC__base64Binary"; + deftypemap["SOAP_ENC__base64"] = "class SOAP_ENC__base64 { unsigned char *__ptr; int __size; };"; + usetypemap["SOAP_ENC__base64"] = "SOAP_ENC__base64"; + } + if (cflag) + { deftypemap["SOAP_ENC__boolean"] = "enum SOAP_ENC__boolean { false_, true_ };"; + usetypemap["SOAP_ENC__boolean"] = "enum SOAP_ENC__boolean"; + } + else + { deftypemap["SOAP_ENC__boolean"] = "typedef bool SOAP_ENC__boolean;"; + usetypemap["SOAP_ENC__boolean"] = "SOAP_ENC__boolean"; + } + deftypemap["SOAP_ENC__byte"] = "typedef char SOAP_ENC__byte;"; + usetypemap["SOAP_ENC__byte"] = "SOAP_ENC__byte"; + deftypemap["SOAP_ENC__dateTime"] = "typedef time_t SOAP_ENC__dateTime;"; + usetypemap["SOAP_ENC__dateTime"] = "SOAP_ENC__dateTime"; + deftypemap["SOAP_ENC__double"] = "typedef double SOAP_ENC__double;"; + usetypemap["SOAP_ENC__double"] = "SOAP_ENC__double"; + deftypemap["SOAP_ENC__float"] = "typedef float SOAP_ENC__float"; + usetypemap["SOAP_ENC__float"] = "SOAP_ENC__float"; + if (cflag) + { deftypemap["SOAP_ENC__hexBinary"] = "struct SOAP_ENC__hexBinary { unsigned char *__ptr; int __size; };"; + usetypemap["SOAP_ENC__hexBinary"] = "struct SOAP_ENC__hexBinary"; + } + else + { deftypemap["SOAP_ENC__hexBinary"] = "class SOAP_ENC__hexBinary { unsigned char *__ptr; int __size; };"; + usetypemap["SOAP_ENC__hexBinary"] = "SOAP_ENC__hexBinary"; + } + deftypemap["SOAP_ENC__int"] = "typedef int SOAP_ENC__int;"; + usetypemap["SOAP_ENC__int"] = "SOAP_ENC__int"; + deftypemap["SOAP_ENC__long"] = "typedef LONG64 SOAP_ENC__long;"; + usetypemap["SOAP_ENC__long"] = "SOAP_ENC__long"; + deftypemap["SOAP_ENC__short"] = "typedef short SOAP_ENC__short;"; + usetypemap["SOAP_ENC__short"] = "SOAP_ENC__short"; + if (cflag || sflag) + { deftypemap["SOAP_ENC__string"] = ""; + usetypemap["SOAP_ENC__string"] = "char*"; + } + else + { deftypemap["SOAP_ENC__string"] = ""; + usetypemap["SOAP_ENC__string"] = "std::string"; + } + deftypemap["SOAP_ENC__unsignedByte"] = "typedef unsigned char SOAP_ENC__unsignedByte;"; + usetypemap["SOAP_ENC__unsignedByte"] = "SOAP_ENC__unsignedByte"; + deftypemap["SOAP_ENC__unsignedInt"] = "typedef unsigned int SOAP_ENC__unsignedInt;"; + usetypemap["SOAP_ENC__unsignedInt"] = "SOAP_ENC__unsignedInt"; + deftypemap["SOAP_ENC__unsignedLong"] = "typedef ULONG64 SOAP_ENC__unsignedLong;"; + usetypemap["SOAP_ENC__unsignedLong"] = "SOAP_ENC__unsignedLong"; + deftypemap["SOAP_ENC__unsignedShort"] = "typedef unsigned short SOAP_ENC__unsignedShort;"; + usetypemap["SOAP_ENC__unsignedShort"] = "SOAP_ENC__unsignedShort"; + deftypemap["SOAP_ENC__Array"] = ""; + usetypemap["SOAP_ENC__Array"] = "struct { _XML *__ptr; int __size; }"; + deftypemap["_SOAP_ENC__arrayType"] = ""; + deftypemap["SOAP_ENV__Header"] = ""; + usetypemap["SOAP_ENV__Header"] = "struct SOAP_ENV__Header"; + deftypemap["_SOAP_ENV__mustUnderstand"] = ""; + if (cflag || sflag) + usetypemap["_SOAP_ENV__mustUnderstand"] = "char*"; + else + usetypemap["_SOAP_ENV__mustUnderstand"] = "std::string"; + deftypemap["SOAP_ENV__Fault"] = ""; + usetypemap["SOAP_ENV__Fault"] = "struct SOAP_ENV__Fault"; + deftypemap["SOAP_ENV__detail"] = ""; + usetypemap["SOAP_ENV__detail"] = "struct SOAP_ENV__Detail"; + deftypemap["SOAP_ENV__Detail"] = ""; + usetypemap["SOAP_ENV__Detail"] = "struct SOAP_ENV__Detail"; + deftypemap["SOAP_ENV__Code"] = ""; + usetypemap["SOAP_ENV__Code"] = "struct SOAP_ENV__Code"; + deftypemap["SOAP_ENV__Reason"] = ""; + usetypemap["SOAP_ENV__Reason"] = "struct SOAP_ENV__Reason"; + if (read(mapfile)) + fprintf(stderr, "Problem reading type map file '%s'.\nUsing internal type definitions for %s instead.\n\n", mapfile, cflag?"C":"C++"); +} + +const char *Types::nsprefix(const char *prefix, const char *URI) +{ if (URI) + { const char *s = uris[URI]; + if (!s) + { size_t n; + if (!prefix || !*prefix || *prefix == '_') + s = schema_prefix; + else + s = estrdup(prefix); + if (!syms[s]) + n = syms[s] = 1; + else + n = ++syms[s]; + if (n != 1 || !prefix || !*prefix || *prefix == '_') + { char *t = (char*)emalloc(strlen(s) + 16); + sprintf(t, "%s%lu", s, (unsigned long)n); + s = t; + } + uris[URI] = s; + if (vflag) + fprintf(stderr, "namespace prefix %s = \"%s\"\n", s, URI); + } + // if *prefix == '_', then add prefix string to s + if (prefix && *prefix == '_') + { char *t = (char*)emalloc(strlen(s) + 2); + *t = '_'; + strcpy(t + 1, s); + s = t; + } + return s; + } + return NULL; +} + +const char *Types::prefix(const char *name) +{ const char *s; + char *t; + if (*name == '"') + { s = strchr(name + 1, '"'); + t = (char*)emalloc(s - name); + strncpy(t, name + 1, s - name - 1); + t[s - name - 1] = '\0'; + return nsprefix(NULL, t); + } + s = strchr(name, ':'); + if (s) + { t = (char*)emalloc(s - name + 1); + strncpy(t, name, s - name); + t[s - name] = '\0'; + return t; + } + return NULL; +} + +const char *Types::uri(const char *name) +{ const char *s; + char *t; + if (*name == '"') + { s = strchr(name + 1, '"'); + t = (char*)emalloc(s - name); + strncpy(t, name + 1, s - name - 1); + t[s - name - 1] = '\0'; + return t; + } + s = strchr(name, ':'); + if (s) + { struct Namespace *p = namespaces; + if (p) + { for (p += 6; p->id; p++) + { if (!strncmp(p->id, name, s - name) && !p->id[s - name]) + { if (p->in && *p->in) + return p->in; + return p->ns; + } + } + } + } + return NULL; +} + +// Find a C name for a QName. If the name has no qualifier, use URI. Suggest prefix for URI +const char *Types::fname(const char *prefix, const char *URI, const char *qname, SetOfString *reserved, enum Lookup lookup, bool isqname) +{ char buf[1024], *t; + const char *p, *s, *name; + if (!qname) + { fprintf(stream, "// Warning: internal error, no QName in fname()\n"); + if (vflag) + fprintf(stderr, "Internal error, no QName in fname()\n"); + qname = "?"; + } + name = qname; + if (isqname) + s = strrchr(name, ':'); + else + s = NULL; + if (s) + { name = s + 1; + if (qname[0] == '"' && qname[1] == '"') + s = NULL; + else if (*qname == '"') + { t = (char*)emalloc(s - qname - 1); + strncpy(t, qname + 1, s - qname - 2); + t[s - qname - 2] = '\0'; + URI = t; + } + else if (!strncmp(qname, "xs:", 3)) // this hack is necessary since the nsmap table defines "xs" for "xsd" + { s = "xsd"; + URI = NULL; + } + else + { t = (char*)emalloc(s - qname + 1); + strncpy(t, qname, s - qname); + t[s - qname] = '\0'; + s = t; + URI = NULL; + } + } + if (URI) + p = nsprefix(prefix, URI); + else if (s) + p = s; + else + p = ""; + s = NULL; + if (lookup == LOOKUP) + { if (qnames.find(Pair(p,name)) != qnames.end()) + s = qnames[Pair(p,name)]; + } + if (!s) + { t = buf; + if (!prefix || *prefix) + { s = p; + // no longer add '_' when URI != NULL, since nsprefix() will do this + if (prefix && *prefix == ':') + *t++ = ':'; + else if (prefix && *prefix == '_') + { if (!URI) + *t++ = '_'; + if (prefix[1] == '_') // ensures ns prefix starts with __ + { strcpy(t, prefix + 1); + t += strlen(prefix + 1); + } + } + if (s && *s) + { for (; *s; s++) + { if (isalnum(*s)) + *t++ = *s; + else if (*s == '-' && s[1] != '-' && s != p) + *t++ = '_'; + else if (*s == '_') + { if (s == p) + *t++ = '_'; + else if (!_flag) + { strcpy(t, "_USCORE"); + t += 7; + } + else + { s = utf8(t, s); + t += 6; + } + } + else + { s = utf8(t, s); + t += 6; + } + } + if (!prefix || *prefix != '*') + { *t++ = '_'; + *t++ = '_'; + } + } + else if (isdigit(*name)) + *t++ = '_'; + } + for (s = name; *s; s++) + { if (isalnum(*s)) + *t++ = *s; + else if (*s == '-' && s[1] != '-' && s[1] != '\0' && s != name) + *t++ = '_'; + else if (!_flag && *s == '_') + { strcpy(t, "_USCORE"); + t += 7; + } + else + { s = utf8(t, s); + t += 6; + } + if (t >= buf + sizeof(buf)) + break; + } + *t = '\0'; + while (knames.find(buf) != knames.end() || (reserved && reserved->find(buf) != reserved->end())) + { *t++ = '_'; + *t = '\0'; + } + if (isalpha(*buf) || *buf == '_' || *buf == ':') + { t = (char*)emalloc(strlen(buf) + 1); + strcpy(t, buf); + } + else + { t = (char*)emalloc(strlen(buf) + 2); + *t = '_'; + strcpy(t + 1, buf); + } + if (lookup == LOOKUP) + { qnames[Pair(p,name)] = t; + if (vflag) + { cerr << "Mapping '" << p << ":" << name << "' to '" << t << "'" << endl; +#ifdef DEBUG + for (MapOfPairToString::const_iterator i = qnames.begin(); i != qnames.end(); ++i) + cerr << "Map[" << (*i).first.first << ":" << (*i).first.second << "]='" << (*i).second << "'" << endl; +#endif + } + } + s = t; + } + if (eqvtypemap.find(s) != eqvtypemap.end()) + s = eqvtypemap[s]; + return s; +} + +bool Types::is_defined(const char *prefix, const char *URI, const char *qname) +{ const char *t = fname(prefix, URI, qname, NULL, LOOKUP, true); + return usetypemap.find(t) != usetypemap.end(); +} + +const char *Types::aname(const char *prefix, const char *URI, const char *qname) +{ return fname(prefix, URI, qname, NULL, NOLOOKUP, true); +} + +const char *Types::cname(const char *prefix, const char *URI, const char *qname) +{ return fname(prefix, URI, qname, NULL, LOOKUP, true); +} + +const char *Types::tname(const char *prefix, const char *URI, const char *qname) +{ const char *s, *t; + t = cname(prefix, URI, qname); + if (usetypemap.find(t) != usetypemap.end()) + { s = usetypemap[t]; + if (vflag) + cerr << "Mapping use of '" << t << "' to '" << s << "'" << endl; + } + else + { s = t; + fprintf(stream, "\n// Warning: undefined QName '%s' for type '%s' in namespace '%s' (FIXME: check WSDL and schema definitions)\n", qname?qname:"", t, URI?URI:"?"); + if (vflag) + fprintf(stderr, "\nWarning: undefined QName '%s' for type '%s' in namespace '%s'\n", qname?qname:"", t, URI?URI:"?"); + } + return s; +} + +const char *Types::tnameptr(bool flag, const char *prefix, const char *URI, const char *qname) +{ const char *s = pname(flag, prefix, URI, qname); + if (flag) + { if (!strncmp(s, "char*", 5)) + return "char**"; + if (!strchr(s, '*')) + { char *r = (char*)emalloc(strlen(s) + 2); + strcpy(r, s); + strcat(r, "*"); + return r; + } + } + return s; +} + +const char *Types::pname(bool flag, const char *prefix, const char *URI, const char *qname) +{ const char *r, *s = NULL, *t; + t = cname(prefix, URI, qname); + if (flag) + { if (ptrtypemap.find(t) != ptrtypemap.end()) + s = ptrtypemap[t]; + else + { if (usetypemap.find(t) != usetypemap.end()) + s = usetypemap[t]; + if (!s) + { s = t; + fprintf(stream, "\n// Warning: undefined QName '%s' for pointer to type '%s' (FIXME: check WSDL and schema definitions)\n", qname, t); + if (vflag) + fprintf(stderr, "\nWarning: undefined QName '%s' for pointer to type '%s' in namespace '%s'\n", qname, t, URI?URI:"?"); + } + r = s; + while (r && *r) + { r = strchr(r + 1, '*'); + if (r && *(r-1) != '/' && *(r+1) != '/') + break; + } + if (!r) // already pointer? + { char *p = (char*)emalloc(strlen(s) + 2); + strcpy(p, s); + strcat(p, "*"); + s = p; + } + if (vflag) + cerr << "Mapping pointer to '" << t << "' to '" << s << "'" << endl; + ptrtypemap[t] = s; + } + } + else if (usetypemap.find(t) != usetypemap.end()) + s = usetypemap[t]; + else + { s = t; + fprintf(stream, "\n// Warning: undefined QName '%s' for type '%s' in namespace '%s' (FIXME: check WSDL and schema definitions)\n", qname, t, URI?URI:"?"); + if (vflag) + fprintf(stderr, "\nWarning: undefined QName '%s' for type '%s' in namespace '%s'\n", qname, t, URI?URI:"?"); + } + return s; +} + +const char *Types::deftname(enum Type type, const char *pointer, bool is_pointer, const char *prefix, const char *URI, const char *qname) +{ char buf[1024]; + char *s; + const char *q = NULL, *t; + t = fname(prefix, URI, qname, NULL, LOOKUP, true); + if (deftypemap[t]) + { if (vflag) + fprintf(stderr, "Name %s already defined (probably in %s file)\n", qname, mapfile); + return NULL; + } + if (usetypemap[t]) + { if (vflag) + fprintf(stderr, "Name %s is mapped\n", qname); + return t; + } + switch (type) + { case ENUM: + q = "enum"; + if (yflag) + knames.insert(t); + break; + case STRUCT: + q = "struct"; + if (yflag) + knames.insert(t); + break; + case CLASS: + case TYPEDEF: + knames.insert(t); + default: + break; + } + if (q) + { strcpy(buf, q); + strcat(buf, " "); + } + else + buf[0] = '\0'; + strcat(buf, t); + if (pointer) + strcat(buf, pointer); + s = (char*)emalloc(strlen(buf) + 1); + strcpy(s, buf); + usetypemap[t] = s; + if (pointer || is_pointer) + ptrtypemap[t] = s; + if (vflag) + cerr << "Defined '" << t << "' ('" << qname << "' in namespace '" << (URI?URI:prefix?prefix:"") << "') as '" << s << endl; + return t; +} + +// get enumeration value. URI/type refers to the enum simpleType. +const char *Types::ename(const char *type, const char *value, bool isqname) +{ const char *s = enames[Pair(type,value)]; + if (!s) + { s = fname(NULL, NULL, value, &rnames, NOLOOKUP, isqname); + if (!eflag && type && *type) + { // Add prefix to enum + if (!*s || (s[0] == '_' && s[1] == '\0')) + s = "_x0000"; + char *buf = (char*)emalloc(strlen(type) + strlen(s) + 3); + // _xXXXX is OK here + if (s[0] == '_' && s[1] != 'x' && strncmp(s, "_USCORE", 7)) + sprintf(buf, "%s_%s", type, s); + else + sprintf(buf, "%s__%s", type, s); + s = buf; + } + else + rnames.insert(s); + enames[Pair(type,value)] = s; + } + return s; +} + +// get operation name +const char *Types::oname(const char *prefix, const char *URI, const char *qname) +{ const char *s = fname(prefix, URI, qname, NULL, LOOKUP, true); + if (s && usetypemap.find(s) != usetypemap.end()) + { // Avoid name clash with structs/classes of the same name + onames.insert(s); + } + s = fname(prefix, URI, qname, &onames, NOLOOKUP, true); + onames.insert(s); + return s; +} + +// generate struct name +const char *Types::sname(const char *URI, const char *name) +{ const char *s; + char *t; + if (!aflag && name) + { size_t len = 0; + for (VectorOfString::const_iterator i = scope.begin(); i != scope.end(); ++i) + len += strlen(*i) + 1; + t = (char*)emalloc(len + strlen(name) + 1); + *t = '\0'; + for (VectorOfString::const_iterator j = scope.begin(); j != scope.end(); ++j) + { strcat(t, *j); + strcat(t, "-"); + } + strcat(t, name); + s = fname("_", URI, t, &rnames, NOLOOKUP, true); + rnames.insert(s); + } + else if (URI) + { s = nsprefix(NULL, URI); + t = (char*)emalloc(strlen(s) + 16); + sprintf(t, "_%s__struct_%d", s, snum++); + s = t; + } + else + { t = (char*)emalloc(16); + sprintf(t, "struct_%d", snum++); + s = t; + } + return s; +} + +// generate union name +const char *Types::uname(const char *URI) +{ const char *s; + char *t; + if (!aflag) + { size_t len = 0; + for (VectorOfString::const_iterator i = scope.begin(); i != scope.end(); ++i) + len += strlen(*i) + 1; + t = (char*)emalloc(len + 6); + strcpy(t, "union"); + for (VectorOfString::const_iterator j = scope.begin(); j != scope.end(); ++j) + { strcat(t, "-"); + strcat(t, *j); + } + s = fname("_", URI, t, &rnames, NOLOOKUP, true); + rnames.insert(s); + } + else if (URI) + { s = nsprefix(NULL, URI); + t = (char*)emalloc(strlen(s) + 16); + sprintf(t, "_%s__union_%d", s, unum++); + s = t; + } + else + { t = (char*)emalloc(16); + sprintf(t, "_union_%d", unum++); + s = t; + } + return s; +} + +// generate enum name +const char *Types::gname(const char *URI, const char *name) +{ const char *s; + char *t; + if (!aflag && name) + { size_t len = 0; + for (VectorOfString::const_iterator i = scope.begin(); i != scope.end(); ++i) + len += strlen(*i) + 1; + t = (char*)emalloc(len + strlen(name) + 1); + *t = '\0'; + for (VectorOfString::const_iterator j = scope.begin(); j != scope.end(); ++j) + { strcat(t, *j); + strcat(t, "-"); + } + strcat(t, name); + s = fname("_", URI, t, &rnames, LOOKUP, true); + rnames.insert(s); + } + else if (URI) + { s = nsprefix(NULL, URI); + t = (char*)emalloc(strlen(s) + 16); + sprintf(t, "_%s__enum_%d", s, gnum++); + s = t; + } + else + { t = (char*)emalloc(16); + sprintf(t, "enum_%d", gnum++); + s = t; + } + return s; +} + +// checks if nillable or minOccurs=0 (and no default value is present) +bool Types::is_nillable(const xs__element& element) +{ return !element.default_ && (element.nillable || (element.minOccurs && !strcmp(element.minOccurs, "0"))); +} + +bool Types::is_basetypeforunion(const char *prefix, const char *URI, const char *type) +{ const char *t = tname(prefix, URI, type); + if (!strcmp(t, "std::string") || !strcmp(t, "std::wstring")) + return false; + return is_basetype(prefix, URI, type); +} + +bool Types::is_basetype(const char *prefix, const char *URI, const char *type) +{ const char *t = tname(prefix, URI, type); + if (!strncmp(t, "enum ", 5)) + return true; + if (strstr(t, "__") && strcmp(t, "xsd__byte")) + return false; + return !strncmp(type, "xs:", 3) || !strncmp(type, "SOAP-ENC:", 9); +} + +void Types::dump(FILE *fd) +{ fprintf(fd, "\nTypes:\n"); + for (MapOfStringToString::const_iterator i = usetypemap.begin(); i != usetypemap.end(); ++i) + fprintf(fd, "%s=%s\n", (*i).first, (*i).second?(*i).second:"(null)"); + fprintf(fd, "\nPointers:\n"); + for (MapOfStringToString::const_iterator j = ptrtypemap.begin(); j != ptrtypemap.end(); ++j) + fprintf(fd, "%s=%s\n", (*j).first, (*j).second?(*j).second:"(null)"); +} + +void Types::define(const char *URI, const char *name, const xs__complexType& complexType) +{ // generate prototype for structs/classes and store name + const char *prefix = NULL; + if (complexType.name) + name = complexType.name; + else + prefix = "_"; + if (complexType.complexContent + && complexType.complexContent->restriction + && !strcmp(complexType.complexContent->restriction->base, "SOAP-ENC:Array")) + { if (strcmp(schema_prefix, "ns")) + prefix = "*"; + else + prefix = ""; + } + if (cflag) + { const char *t = deftname(STRUCT, "*", true, prefix, URI, name); + if (t) + { if (yflag) + fprintf(stream, "\n/// Typedef synonym for struct %s.\ntypedef struct %s %s;\n", t, t, t); + } + else if (name) + { t = deftypemap[cname(prefix, URI, name)]; + if (t) + { fprintf(stream, "\n/// Imported complexType \"%s\":%s from typemap %s.\n", URI, name, mapfile?mapfile:""); + document(complexType.annotation); + if (*t) + format(t); + else + fprintf(stream, "// complexType definition intentionally left blank.\n"); + } + } + } + else + { const char *t = deftname(CLASS, "*", true, prefix, URI, name); + if (t) + fprintf(stream, "\n// Forward declaration of class %s.\nclass %s;\n", t, t); + else if (name) + { t = deftypemap[cname(prefix, URI, name)]; + if (t) + { fprintf(stream, "\n/// Imported complexType \"%s\":%s from typemap %s.\n", URI, name, mapfile?mapfile:""); + document(complexType.annotation); + if (*t) + format(t); + else + fprintf(stream, "// complexType definition intentionally left blank.\n"); + } + } + } +} + +void Types::gen(const char *URI, const char *name, const xs__simpleType& simpleType, bool anonymous) +{ const char *t = NULL; + const char *prefix = NULL; + if (simpleType.name) + name = simpleType.name; + else + prefix = "_"; + if (!anonymous) + { t = deftypemap[cname(NULL, URI, name)]; + if (t) + { fprintf(stream, "\n/// Imported simpleType \"%s\":%s from typemap %s.\n", URI, name, mapfile?mapfile:""); + document(simpleType.annotation); + if (*t) + format(t); + else + fprintf(stream, "// simpleType definition intentionally left blank.\n"); + return; + } + } + if (simpleType.restriction) + { const char *base = simpleType.restriction->base; + if (!base && simpleType.restriction->simpleType) + { if (!anonymous) + { if (simpleType.restriction->simpleType->list && simpleType.restriction->length && simpleType.restriction->length->value) + { fprintf(stream, "\n/// \"%s\":%s is a simpleType restriction list with length %s.", URI?URI:"", name, simpleType.restriction->length->value); + document(simpleType.restriction->length->annotation); + } + else + fprintf(stream, "\n/// \"%s\":%s is a simpleType restriction.", URI?URI:"", name); + } + gen(URI, name, *simpleType.restriction->simpleType, anonymous); + } + else + { if (!base) + base = "xsd:string"; + const char *baseURI = NULL; + if (simpleType.restriction->simpleTypePtr() && simpleType.restriction->simpleTypePtr()->schemaPtr()) + baseURI = simpleType.restriction->simpleTypePtr()->schemaPtr()->targetNamespace; + if (!anonymous) + fprintf(stream, "\n/// \"%s\":%s is a simpleType restriction of %s.\n", URI?URI:"", name, base); + document(simpleType.annotation); + document(simpleType.restriction->annotation); + if (!simpleType.restriction->enumeration.empty()) + { bool is_numeric = true; // check if all enumeration values are numeric + bool is_qname = !strcmp(base, "xs:QName"); + if (!anonymous) + { t = deftname(ENUM, NULL, false, prefix, URI, name); + if (t && !eflag) + fprintf(stream, "/// Note: enum values are prefixed with '%s' to avoid name clashes, please use wsdl2h option -e to omit this prefix\n", t); + } + if (!t) + t = gname(URI, name); + if (!anonymous) + fprintf(stream, "enum %s\n{\n", t); + else + fprintf(stream, " enum %s\n {\n", t); + for (vector<xs__enumeration>::const_iterator enumeration1 = simpleType.restriction->enumeration.begin(); enumeration1 != simpleType.restriction->enumeration.end(); ++enumeration1) + { const char *s; + if ((s = (*enumeration1).value)) + is_numeric &= is_integer(s); + } + SetOfString enumvals; + for (vector<xs__enumeration>::const_iterator enumeration2 = simpleType.restriction->enumeration.begin(); enumeration2 != simpleType.restriction->enumeration.end(); ++enumeration2) + { const char *s; + document((*enumeration2).annotation); + if ((s = (*enumeration2).value)) + { if (!enumvals.count(s)) + { enumvals.insert(s); + if (is_numeric) + fprintf(stream, "\t%s = %s,\t///< %s value=\"%s\"\n", ename(t, s, false), s, base, s); + else if (is_qname && (*enumeration2).value_) + fprintf(stream, "\t%s,\t///< %s value=\"%s\"\n", ename(t, (*enumeration2).value_, true), base, (*enumeration2).value_); + else + fprintf(stream, "\t%s,\t///< %s value=\"%s\"\n", ename(t, s, false), base, s); + } + } + else + fprintf(stream, "//\tunrecognized: enumeration '%s' has no value\n", name?name:""); + } + if (!anonymous) + { fprintf(stream, "};\n"); + if (yflag) + fprintf(stream, "/// Typedef synonym for enum %s.\ntypedef enum %s %s;\n", t, t, t); + if (pflag && simpleType.name) + { const char *s = aname(prefix, URI, name); + knames.insert(s); + s = aname(prefix, URI, name); + fprintf(stream, "\n/// Class wrapper\n"); + fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", s); + fprintf(stream, elementformat, tname(prefix, URI, name), "__item;"); + modify(s); + fprintf(stream, "\n};\n"); + } + } + else + fprintf(stream, " }\n"); + } + else + { if (simpleType.restriction->length && simpleType.restriction->length->value) + { fprintf(stream, "/// Length of this string is exactly %s characters\n", simpleType.restriction->length->value); + document(simpleType.restriction->length->annotation); + } + else + { const char *a = NULL, *b = NULL; + if (simpleType.restriction->minLength) + { a = simpleType.restriction->minLength->value; + document(simpleType.restriction->minLength->annotation); + } + if (simpleType.restriction->maxLength) + { b = simpleType.restriction->maxLength->value; + document(simpleType.restriction->maxLength->annotation); + } + if (a || b) + fprintf(stream, "/// Length of this string is within %s..%s characters\n", a?a:"0", b?b:""); + } + if (simpleType.restriction->precision && simpleType.restriction->precision->value) + fprintf(stream, "/// %sprecision is %s (note: not automatically enforced)\n", simpleType.restriction->precision->fixed?"fixed ":"", simpleType.restriction->precision->value); + if (simpleType.restriction->scale && simpleType.restriction->scale->value) + fprintf(stream, "/// %sscale is %s (note: not automatically enforced)\n", simpleType.restriction->scale->fixed?"fixed ":"", simpleType.restriction->scale->value); + if (simpleType.restriction->totalDigits && simpleType.restriction->totalDigits->value) + fprintf(stream, "/// %snumber of total digits is %s (note: not automatically enforced)\n", simpleType.restriction->totalDigits->fixed?"fixed ":"", simpleType.restriction->totalDigits->value); + if (simpleType.restriction->fractionDigits && simpleType.restriction->fractionDigits->value) + fprintf(stream, "/// %snumber of fraction digits is %s (note: not automatically enforced)\n", simpleType.restriction->fractionDigits->fixed?"fixed ":"", simpleType.restriction->fractionDigits->value); + for (vector<xs__pattern>::const_iterator pattern1 = simpleType.restriction->pattern.begin(); pattern1 != simpleType.restriction->pattern.end(); ++pattern1) + fprintf(stream, "/// Content pattern is \"%s\" (note: not automatically enforced)\n", xstring((*pattern1).value)); + const char *ai = NULL, *ae = NULL, *bi = NULL, *be = NULL; + if (simpleType.restriction->minInclusive) + { ai = simpleType.restriction->minInclusive->value; + document(simpleType.restriction->minInclusive->annotation); + } + else if (simpleType.restriction->minExclusive) + { ae = simpleType.restriction->minExclusive->value; + document(simpleType.restriction->minExclusive->annotation); + } + if (simpleType.restriction->maxInclusive) + { bi = simpleType.restriction->maxInclusive->value; + document(simpleType.restriction->maxInclusive->annotation); + } + else if (simpleType.restriction->maxExclusive) + { be = simpleType.restriction->maxExclusive->value; + document(simpleType.restriction->maxExclusive->annotation); + } + if (ai || ae || bi || be) + { fprintf(stream, "/// Value range is "); + if (ai) + fprintf(stream, "[%s..", ai); + else if (ae) + fprintf(stream, "(%s..", ae); + else + fprintf(stream, "[.."); + if (bi) + fprintf(stream, "%s]\n", bi); + else if (be) + fprintf(stream, "%s)\n", be); + else + fprintf(stream, "]\n"); + } + if (!simpleType.restriction->attribute.empty()) + { if (!Wflag) + fprintf(stderr, "\nWarning: simpleType '%s' should not have attributes\n", name?name:""); + } + const char *s = tname(NULL, baseURI, base); + if (!anonymous) + { bool is_ptr = false; + is_ptr = (strchr(s, '*') != NULL) || (s == pname(true, NULL, baseURI, base)); + t = deftname(TYPEDEF, NULL, is_ptr, prefix, URI, name); + if (t) + fprintf(stream, "typedef %s %s", s, t); + } + else + { t = ""; + fprintf(stream, elementformat, s, ""); + fprintf(stream, "\n"); + } + if (t) + { if (!anonymous && !simpleType.restriction->pattern.empty()) + { fprintf(stream, " \""); + for (vector<xs__pattern>::const_iterator pattern2 = simpleType.restriction->pattern.begin(); pattern2 != simpleType.restriction->pattern.end(); ++pattern2) + { if (pattern2 != simpleType.restriction->pattern.begin()) + fprintf(stream, "|"); + fprintf(stream, "%s", xstring((*pattern2).value)); + } + fprintf(stream, "\""); + } + // add range info only when type is numeric + bool is_numeric = false, is_float = false; + if (!strncmp(s, "unsigned ", 9)) + s += 9; + else if (!strncmp(s, "xsd__unsigned", 13)) + s += 13; + else if (!strncmp(s, "xsd__", 5)) + s += 5; + if (!strcmp(s, "double") + || !strcmp(s, "float")) + is_numeric = is_float = true; + else if (!strcmp(s, "bool") + || !strcmp(s, "byte") + || !strcmp(s, "Byte") + || !strcmp(s, "char") + || !strcmp(s, "double") + || !strcmp(s, "float") + || !strcmp(s, "int") + || !strcmp(s, "Int") + || !strcmp(s, "long") + || !strcmp(s, "Long") + || !strcmp(s, "LONG64") + || !strcmp(s, "short") + || !strcmp(s, "Short") + || !strcmp(s, "ULONG64")) + is_numeric = true; + if (!anonymous + && simpleType.restriction->minLength + && simpleType.restriction->minLength->value) + fprintf(stream, " %s", simpleType.restriction->minLength->value); + else if (is_numeric + && !anonymous + && simpleType.restriction->minInclusive + && simpleType.restriction->minInclusive->value + && is_integer(simpleType.restriction->minInclusive->value)) + fprintf(stream, " %s", simpleType.restriction->minInclusive->value); + else if (is_float + && !anonymous + && simpleType.restriction->minExclusive + && simpleType.restriction->minExclusive->value + && is_integer(simpleType.restriction->minExclusive->value)) + fprintf(stream, " %s", simpleType.restriction->minExclusive->value); + else if (is_numeric + && !anonymous + && simpleType.restriction->minExclusive + && simpleType.restriction->minExclusive->value + && is_integer(simpleType.restriction->minExclusive->value)) + fprintf(stream, " " SOAP_LONG_FORMAT, to_integer(simpleType.restriction->minExclusive->value)+1); + if (!anonymous + && simpleType.restriction->maxLength + && simpleType.restriction->maxLength->value) + fprintf(stream, ":%s", simpleType.restriction->maxLength->value); + else if (is_numeric + && !anonymous + && simpleType.restriction->maxInclusive + && simpleType.restriction->maxInclusive->value + && is_integer(simpleType.restriction->maxInclusive->value)) + fprintf(stream, ":%s", simpleType.restriction->maxInclusive->value); + else if (is_float + && !anonymous + && simpleType.restriction->maxExclusive + && simpleType.restriction->maxExclusive->value + && is_integer(simpleType.restriction->maxExclusive->value)) + fprintf(stream, ":%s", simpleType.restriction->maxExclusive->value); + else if (is_numeric + && !anonymous + && simpleType.restriction->maxExclusive + && simpleType.restriction->maxExclusive->value + && is_integer(simpleType.restriction->maxExclusive->value)) + fprintf(stream, ":" SOAP_LONG_FORMAT, to_integer(simpleType.restriction->maxExclusive->value)-1); + if (!anonymous) + { fprintf(stream, ";\n"); + if (pflag && simpleType.name) + { const char *s = aname(prefix, URI, name); + knames.insert(s); + s = aname(prefix, URI, name); + fprintf(stream, "\n/// Class wrapper\n"); + fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", s); + fprintf(stream, elementformat, tname(prefix, URI, name), "__item;"); + modify(s); + fprintf(stream, "\n};\n"); + } + } + } + } + } + } + else if (simpleType.list) + { if (simpleType.list->restriction && simpleType.list->restriction->base) + { if (!anonymous) + { fprintf(stream, "\n/// \"%s\":%s is a simpleType list restriction of %s.\n", URI?URI:"", name, simpleType.list->restriction->base); + fprintf(stream, "/// Note: this enumeration is a bitmask, so a set of values is supported (using | and & bit-ops on the bit vector).\n"); + } + document(simpleType.annotation); + if (!anonymous) + { t = deftname(ENUM, NULL, false, prefix, URI, name); + if (t) + fprintf(stream, "enum * %s\n{\n", t); + } + else + { t = ""; + fprintf(stream, "enum *\n{\n"); + } + if (t) + { for (vector<xs__enumeration>::const_iterator enumeration = simpleType.list->restriction->enumeration.begin(); enumeration != simpleType.list->restriction->enumeration.end(); ++enumeration) + { if ((*enumeration).value) + { if (!strcmp(simpleType.list->restriction->base, "xs:QName") && (*enumeration).value_) + fprintf(stream, "\t%s,\t///< %s value=\"%s\"\n", ename(t, (*enumeration).value_, true), simpleType.list->restriction->base, (*enumeration).value_); + else + fprintf(stream, "\t%s,\t///< %s value=\"%s\"\n", ename(t, (*enumeration).value, false), simpleType.list->restriction->base, (*enumeration).value); + } + else + fprintf(stream, "//\tunrecognized: bitmask enumeration '%s' has no value\n", t); + } + if (!anonymous) + { fprintf(stream, "};\n"); + if (yflag) + fprintf(stream, "/// Typedef synonym for enum %s.\ntypedef enum %s %s;\n", t, t, t); + if (pflag && simpleType.name) + { const char *s = aname(prefix, URI, name); + knames.insert(s); + s = aname(prefix, URI, name); + fprintf(stream, "\n/// Class wrapper\n"); + fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", s); + fprintf(stream, elementformat, tname(prefix, URI, name), "__item;"); + modify(s); + fprintf(stream, "\n};\n"); + } + } + else + fprintf(stream, "}\n"); + } + } + else if (simpleType.list->itemType) + { const xs__simpleType *p = simpleType.list->itemTypePtr(); + if (p + && p->restriction + && p->restriction->base + && !p->restriction->enumeration.empty() + && p->restriction->enumeration.size() <= 64) + { if (!anonymous) + { fprintf(stream, "\n/// \"%s\":%s is a simpleType list of %s.\n", URI?URI:"", name, simpleType.list->itemType); + fprintf(stream, "/// Note: this enumeration is a bitmask, so a set of values is supported (using | and & bit-ops on the bit vector).\n"); + } + document(simpleType.annotation); + if (!anonymous) + { t = deftname(ENUM, NULL, false, prefix, URI, name); + if (t) + fprintf(stream, "enum * %s\n{\n", t); + } + else + { t = ""; + fprintf(stream, "enum *\n{\n"); + } + if (t) + { for (vector<xs__enumeration>::const_iterator enumeration = p->restriction->enumeration.begin(); enumeration != p->restriction->enumeration.end(); ++enumeration) + { if ((*enumeration).value) + { if (!strcmp(p->restriction->base, "xs:QName") && (*enumeration).value_) + fprintf(stream, "\t%s,\t///< %s value=\"%s\"\n", ename(t, (*enumeration).value_, true), p->restriction->base, (*enumeration).value_); + else + fprintf(stream, "\t%s,\t///< %s value=\"%s\"\n", ename(t, (*enumeration).value, false), p->restriction->base, (*enumeration).value); + } + else + fprintf(stream, "//\tunrecognized: bitmask enumeration '%s' has no value\n", t); + } + if (!anonymous) + { fprintf(stream, "};\n"); + if (yflag) + fprintf(stream, "/// Typedef synonym for enum %s.\ntypedef enum %s %s;\n", t, t, t); + if (pflag && simpleType.name) + { const char *s = aname(prefix, URI, name); + knames.insert(s); + s = aname(prefix, URI, name); + fprintf(stream, "\n/// Class wrapper.\n"); + fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", s); + fprintf(stream, elementformat, tname(prefix, URI, name), "__item;"); + modify(s); + fprintf(stream, "\n};\n"); + } + } + else + fprintf(stream, "}\n"); + } + } + else + { const char *s; + if (!strcmp(simpleType.list->itemType, "xs:QName")) + s = tname(NULL, NULL, "xsd:QName"); + else + s = tname(NULL, NULL, "xsd:string"); + if (!anonymous) + { fprintf(stream, "\n/// \"%s\":%s is a simpleType containing a whitespace separated list of %s.\n", URI?URI:"", name, simpleType.list->itemType); + t = deftname(TYPEDEF, NULL, strchr(s, '*') != NULL, prefix, URI, name); + } + document(simpleType.annotation); + if (t) + fprintf(stream, "typedef %s %s;\n", s, t); + else + { fprintf(stream, elementformat, s, ""); + fprintf(stream, "\n"); + } + } + } + else + { if (!anonymous) + { fprintf(stream, "\n/// \"%s\":%s is a simpleType list.\n", URI?URI:"", name); + fprintf(stream, "/// Note: this enumeration is a bitmask, so a set of values is supported (using | and & bit-ops on the bit vector).\n"); + } + document(simpleType.annotation); + if (!anonymous) + { t = deftname(ENUM, NULL, false, prefix, URI, name); + if (t && !eflag) + fprintf(stream, "/// Note: enum values are prefixed with '%s' to avoid name clashes, please use wsdl2h option -e to omit this prefix\n", t); + } + else + t = ""; + if (t) + { fprintf(stream, "enum * %s\n{\n", t); + for (vector<xs__simpleType>::const_iterator simple = simpleType.list->simpleType.begin(); simple != simpleType.list->simpleType.end(); ++simple) + { if ((*simple).restriction && (*simple).restriction->base) + { for (vector<xs__enumeration>::const_iterator enumeration = (*simple).restriction->enumeration.begin(); enumeration != (*simple).restriction->enumeration.end(); ++enumeration) + { if ((*enumeration).value) + { if (!strcmp((*simple).restriction->base, "xs:QName") && (*enumeration).value_) + fprintf(stream, "\t%s,\t///< %s value=\"%s\"\n", ename(t, (*enumeration).value_, true), (*simple).restriction->base, (*enumeration).value_); + else + fprintf(stream, "\t%s,\t///< %s value=\"%s\"\n", ename(t, (*enumeration).value, false), (*simple).restriction->base, (*enumeration).value); + } + else + fprintf(stream, "//\tunrecognized: bitmask enumeration '%s' has no value\n", t); + } + } + } + if (!anonymous) + { fprintf(stream, "};\n"); + if (yflag) + fprintf(stream, "/// Typedef synonym for enum %s.\ntypedef enum %s %s;\n", t, t, t); + if (pflag && simpleType.name) + { const char *s = aname(prefix, URI, name); + knames.insert(s); + s = aname(prefix, URI, name); + fprintf(stream, "\n/// Class wrapper.\n"); + fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", s); + fprintf(stream, elementformat, tname(prefix, URI, name), "__item;"); + modify(s); + fprintf(stream, "\n};\n"); + } + } + else + fprintf(stream, "}\n"); + } + } + } + else if (simpleType.union_) + { if (simpleType.union_->memberTypes) + { const char *s = tname(NULL, NULL, "xsd:string"); + if (!anonymous) + t = deftname(TYPEDEF, NULL, strchr(s, '*') != NULL, prefix, URI, name); + fprintf(stream, "\n/// union of values \"%s\"\n", simpleType.union_->memberTypes); + if (t) + fprintf(stream, "typedef %s %s;\n", s, t); + else + { fprintf(stream, elementformat, s, ""); + fprintf(stream, "\n"); + } + } + else if (!simpleType.union_->simpleType.empty()) + { const char *s = tname(NULL, NULL, "xsd:string"); + fprintf(stream, "\n"); + if (!anonymous) + t = deftname(TYPEDEF, NULL, strchr(s, '*') != NULL, prefix, URI, name); + for (vector<xs__simpleType>::const_iterator simpleType1 = simpleType.union_->simpleType.begin(); simpleType1 != simpleType.union_->simpleType.end(); ++simpleType1) + if ((*simpleType1).restriction) + { fprintf(stream, "/// union of values from \"%s\"\n", (*simpleType1).restriction->base); + // TODO: are there any other types we should report here? + } + if (t) + fprintf(stream, "typedef %s %s;\n", s, t); + else + { fprintf(stream, elementformat, s, ""); + fprintf(stream, "\n"); + } + } + else + fprintf(stream, "//\tunrecognized\n"); + } + else + fprintf(stream, "//\tunrecognized simpleType\n"); +} + +void Types::gen(const char *URI, const char *name, const xs__complexType& complexType, bool anonymous) +{ const char *t = NULL; + const char *prefix = NULL; + bool soapflag = false; + if (complexType.name) + name = complexType.name; + else + prefix = "_"; + if (anonymous && name) + t = sname(URI, name); + else if (name) + { t = cname(prefix, URI, name); + if (deftypemap[t]) + return; + } + if (name) + scope.push_back(name); + if (complexType.simpleContent) + { if (!anonymous) + fprintf(stream, "\n/// \"%s\":%s is a%s complexType with simpleContent.\n", URI?URI:"", name, complexType.abstract?"n abstract":""); + document(complexType.annotation); + operations(t); + if (complexType.simpleContent->restriction) + { if (anonymous) + { if (cflag) + fprintf(stream, " struct %s\n {\n", t); + else + fprintf(stream, " class %s\n {\n", t); + } + else if (cflag) + fprintf(stream, "struct %s\n{\n", t); + else if (pflag && complexType.name) + fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", t); + else + fprintf(stream, "class %s\n{ public:\n", t); + const char *base = "xs:string"; + const char *baseURI = NULL; + const xs__complexType *p = &complexType; + do + { if (!p->simpleContent) + break; + if (p->simpleContent->restriction) + { if (p->simpleContent->restriction->complexTypePtr()) + p = p->simpleContent->restriction->complexTypePtr(); + else + { base = p->simpleContent->restriction->base; + if (p->simpleContent->restriction->simpleTypePtr() && p->simpleContent->restriction->simpleTypePtr()->schemaPtr()) + baseURI = p->simpleContent->restriction->simpleTypePtr()->schemaPtr()->targetNamespace; + break; + } + } + else if (p->simpleContent->extension) + { if (p->simpleContent->extension->complexTypePtr()) + p = p->simpleContent->extension->complexTypePtr(); + else + { base = p->simpleContent->extension->base; + if (p->simpleContent->extension->simpleTypePtr() && p->simpleContent->extension->simpleTypePtr()->schemaPtr()) + baseURI = p->simpleContent->extension->simpleTypePtr()->schemaPtr()->targetNamespace; + break; + } + } + else + break; + } + while (p); + fprintf(stream, "/// __item wraps '%s' simpleContent.\n", base); + fprintf(stream, elementformat, tname(NULL, baseURI, base), "__item"); + fprintf(stream, ";\n"); + p = &complexType; + bool flag = true; + do + { if (!p->simpleContent) + break; + if (p->simpleContent->restriction) + { // TODO: should only generate attribute when name is different? + gen(URI, p->simpleContent->restriction->attribute); + if (p->simpleContent->restriction->anyAttribute && flag) + { gen(URI, *p->simpleContent->restriction->anyAttribute); + flag = false; + } + if (p->simpleContent->restriction->complexTypePtr()) + p = p->simpleContent->restriction->complexTypePtr(); + else + break; + } + else if (p->simpleContent->extension) + { gen(URI, p->simpleContent->extension->attribute); + gen(URI, p->simpleContent->extension->attributeGroup); + if (p->simpleContent->extension->anyAttribute && flag) + { gen(URI, *p->simpleContent->extension->anyAttribute); + flag = false; + } + if (p->simpleContent->extension->complexTypePtr()) + p = p->simpleContent->extension->complexTypePtr(); + else + break; + } + else + break; + } + while (p); + } + else if (complexType.simpleContent->extension) + { const char *base = "xs:string"; + const char *baseURI = NULL; + if (cflag || fflag || anonymous) + { if (anonymous) + { if (cflag) + fprintf(stream, " struct %s\n {\n", t); + else + fprintf(stream, " class %s\n {\n", t); + } + else if (cflag) + fprintf(stream, "struct %s\n{\n", t); + else if (pflag && complexType.name) + fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", t); + else + fprintf(stream, "class %s\n{ public:\n", t); + const xs__complexType *p = &complexType; + do + { if (!p->simpleContent) + break; + if (p->simpleContent->restriction) + { if (p->simpleContent->restriction->complexTypePtr()) + p = p->simpleContent->restriction->complexTypePtr(); + else + { base = p->simpleContent->restriction->base; + if (p->simpleContent->restriction->simpleTypePtr() && p->simpleContent->restriction->simpleTypePtr()->schemaPtr()) + baseURI = p->simpleContent->restriction->simpleTypePtr()->schemaPtr()->targetNamespace; + break; + } + } + else if (p->simpleContent->extension) + { if (p->simpleContent->extension->complexTypePtr()) + p = p->simpleContent->extension->complexTypePtr(); + else + { base = p->simpleContent->extension->base; + if (p->simpleContent->extension->simpleTypePtr() && p->simpleContent->extension->simpleTypePtr()->schemaPtr()) + baseURI = p->simpleContent->extension->simpleTypePtr()->schemaPtr()->targetNamespace; + break; + } + } + else + break; + } + while (p); + fprintf(stream, "/// __item wraps '%s' simpleContent.\n", base); + fprintf(stream, elementformat, tname(NULL, baseURI, base), "__item"); + fprintf(stream, ";\n"); + p = &complexType; + bool flag = true; + do + { if (!p->simpleContent) + break; + if (p->simpleContent->restriction) + { gen(URI, p->simpleContent->restriction->attribute); + if (p->simpleContent->restriction->anyAttribute && flag) + gen(URI, *p->simpleContent->restriction->anyAttribute); + break; + } + else if (p->simpleContent->extension) + { gen(URI, p->simpleContent->extension->attribute); + gen(URI, p->simpleContent->extension->attributeGroup); + if (p->simpleContent->extension->anyAttribute && flag) + { gen(URI, *p->simpleContent->extension->anyAttribute); + flag = false; + } + if (p->simpleContent->extension->complexTypePtr()) + p = p->simpleContent->extension->complexTypePtr(); + else + break; + } + else + break; + } + while (p); + } + else + { base = complexType.simpleContent->extension->base; + if ( + /* TODO: in future, may want to add check here for base type == class + complexType.simpleContent->extension->simpleTypePtr() + || + */ + complexType.simpleContent->extension->complexTypePtr()) + { if (complexType.simpleContent->extension->complexTypePtr()->schemaPtr()) + baseURI = complexType.simpleContent->extension->complexTypePtr()->schemaPtr()->targetNamespace; + fprintf(stream, "class %s : public %s\n{ public:\n", t, cname(NULL, baseURI, base)); + soapflag = true; + } + else + { if (complexType.simpleContent->extension->simpleTypePtr() && complexType.simpleContent->extension->simpleTypePtr()->schemaPtr()) + baseURI = complexType.simpleContent->extension->simpleTypePtr()->schemaPtr()->targetNamespace; + else if (complexType.simpleContent->extension->complexTypePtr() && complexType.simpleContent->extension->complexTypePtr()->schemaPtr()) + baseURI = complexType.simpleContent->extension->complexTypePtr()->schemaPtr()->targetNamespace; + if (pflag && complexType.name) + fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", t); + else + fprintf(stream, "class %s\n{ public:\n", t); + fprintf(stream, "/// __item wraps '%s' simpleContent.\n", base); + fprintf(stream, elementformat, tname(NULL, baseURI, base), "__item"); + fprintf(stream, ";\n"); + } + gen(URI, complexType.simpleContent->extension->attribute); + gen(URI, complexType.simpleContent->extension->attributeGroup); + if (complexType.simpleContent->extension->anyAttribute) + gen(URI, *complexType.simpleContent->extension->anyAttribute); + } + } + else + fprintf(stream, "//\tunrecognized\n"); + } + else if (complexType.complexContent) + { if (complexType.complexContent->restriction) + { if (!anonymous) + 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); + document(complexType.annotation); + operations(t); + if (!strcmp(complexType.complexContent->restriction->base, "SOAP-ENC:Array")) + { char *item = NULL, *type = NULL; + if (!complexType.complexContent->restriction->attribute.empty()) + { xs__attribute& attribute = complexType.complexContent->restriction->attribute.front(); + if (attribute.wsdl__arrayType) + type = attribute.wsdl__arrayType; + } + xs__seqchoice *s = complexType.complexContent->restriction->sequence; + if (s + && !s->__contents.empty() + && s->__contents.front().__union == SOAP_UNION_xs__union_content_element + && s->__contents.front().__content.element) + { xs__element& element = *s->__contents.front().__content.element; + if (!type) + { if (element.type) + type = element.type; + else if (element.simpleTypePtr()) + { if (element.simpleTypePtr()->name) + type = element.simpleTypePtr()->name; + else if (element.simpleTypePtr()->restriction) + type = element.simpleTypePtr()->restriction->base; + } + else if (element.complexTypePtr()) + { if (element.complexTypePtr()->name) + type = element.complexTypePtr()->name; + else if (element.complexTypePtr()->complexContent && element.complexTypePtr()->complexContent->restriction) + type = element.complexTypePtr()->complexContent->restriction->base; + } + } + item = element.name; // <sequence><element name="item" type="..."/></sequence> + } + gen_soap_array(name, t, item, type); + } + else + { if (anonymous) + { if (cflag) + fprintf(stream, " struct %s\n {\n", t); + else + fprintf(stream, " class %s\n {\n", t); + } + else if (cflag) + fprintf(stream, "struct %s\n{\n", t); + else if (pflag && complexType.name) + fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", t); + else + fprintf(stream, "class %s\n{ public:\n", t); + if (complexType.complexContent->restriction->group) + gen(URI, *complexType.complexContent->restriction->group, NULL, NULL); + if (complexType.complexContent->restriction->all) + gen(URI, *complexType.complexContent->restriction->all, NULL, NULL); + if (complexType.complexContent->restriction->sequence) + gen(URI, *complexType.complexContent->restriction->sequence, NULL, NULL); + if (complexType.complexContent->restriction->choice) + gen(URI, name, *complexType.complexContent->restriction->choice, NULL, NULL); + gen(URI, complexType.complexContent->restriction->attribute); + bool flag = true; + if (complexType.complexContent->restriction->anyAttribute) + { gen(URI, *complexType.complexContent->restriction->anyAttribute); + flag = false; + } + const xs__complexType *p = complexType.complexContent->restriction->complexTypePtr(); + while (p) + { const char *pURI; + if (p->schemaPtr()) + pURI = p->schemaPtr()->targetNamespace; + else + pURI = URI; + const char *b = cname(NULL, pURI, p->name); + if (zflag && zflag <= 5) + fprintf(stream, "/// RESTRICTED FROM %s:\n", b); + else if (comment_nest == 0) + fprintf(stream, "/* RESTRICTED FROM %s:\n", b); + else + fprintf(stream, " RESTRICTED FROM %s:\n", b); + comment_nest++; + if (p->complexContent && p->complexContent->restriction) + { gen(URI, p->complexContent->restriction->attribute); + if (p->complexContent->restriction->anyAttribute && flag) + { gen(URI, *p->complexContent->restriction->anyAttribute); + flag = false; + } + p = p->complexContent->restriction->complexTypePtr(); + } + else if (p->complexContent && p->complexContent->extension) + { gen(URI, p->complexContent->extension->attribute); + gen(URI, p->complexContent->extension->attributeGroup); + if (p->complexContent->extension->anyAttribute && flag) + { gen(URI, *p->complexContent->extension->anyAttribute); + flag = false; + } + p = p->complexContent->extension->complexTypePtr(); + } + else + { gen(URI, p->attribute); + gen(URI, p->attributeGroup); + if (p->anyAttribute && flag) + gen(URI, *p->anyAttribute); + p = NULL; + } + comment_nest--; + if (zflag && zflag <= 5) + fprintf(stream, "// END OF RESTRICTED FROM %s\n", b); + else if (comment_nest == 0) + fprintf(stream, " END OF RESTRICTED FROM %s */\n", b); + else + fprintf(stream, " END OF RESTRICTED FROM %s\n", b); + } + } + } + else if (complexType.complexContent->extension) + { const char *base = complexType.complexContent->extension->base; + xs__complexType *p = complexType.complexContent->extension->complexTypePtr(); + if (!anonymous) + fprintf(stream, "\n/// \"%s\":%s is a%s complexType with complexContent extension of %s.\n", URI?URI:"", name, complexType.abstract?"n abstract":"", base); + document(complexType.annotation); + operations(t); + if (anonymous) + { if (cflag) + fprintf(stream, " struct %s\n {\n", t); + else + fprintf(stream, " class %s\n {\n", t); + } + else if (cflag) + fprintf(stream, "struct %s\n{\n", t); + else if (fflag) + fprintf(stream, "class %s\n{ public:\n", t); + else // TODO: what to do if base class is in another namespace and elements must be qualified in XML payload? + { const char *baseURI = NULL; + if (p && p->schemaPtr()) + baseURI = p->schemaPtr()->targetNamespace; + fprintf(stream, "class %s : public %s\n{ public:\n", t, cname(NULL, baseURI, base)); + soapflag = true; + } + gen_inh(URI, p, anonymous); + if (complexType.complexContent->extension->group) + gen(URI, *complexType.complexContent->extension->group, NULL, NULL); + if (complexType.complexContent->extension->all) + gen(URI, *complexType.complexContent->extension->all, NULL, NULL); + if (complexType.complexContent->extension->sequence) + gen(URI, *complexType.complexContent->extension->sequence, NULL, NULL); + if (complexType.complexContent->extension->choice) + gen(URI, name, *complexType.complexContent->extension->choice, NULL, NULL); + gen(URI, complexType.complexContent->extension->attribute); + gen(URI, complexType.complexContent->extension->attributeGroup); + if (complexType.complexContent->extension->anyAttribute) + gen(URI, *complexType.complexContent->extension->anyAttribute); + } + else + fprintf(stream, "//\tunrecognized\n"); + } + else + { if (!anonymous) + fprintf(stream, "\n/// \"%s\":%s is a%s complexType.\n", URI?URI:"", name, complexType.abstract?"n abstract":""); + document(complexType.annotation); + operations(t); + if (anonymous) + { if (cflag) + fprintf(stream, " struct %s\n {\n", t); + else + fprintf(stream, " class %s\n {\n", t); + } + else if (cflag) + fprintf(stream, "struct %s\n{\n", t); + else if (pflag && complexType.name) + fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", t); + else + fprintf(stream, "class %s\n{ public:\n", t); + if (complexType.all) + gen(URI, *complexType.all, NULL, NULL); + else if (complexType.choice) + gen(URI, name, *complexType.choice, NULL, NULL); + else if (complexType.sequence) + gen(URI, *complexType.sequence, NULL, NULL); + else if (complexType.any) + gen(URI, *complexType.any, NULL, NULL); + } + gen(URI, complexType.attribute); + gen(URI, complexType.attributeGroup); + if (complexType.anyAttribute) + gen(URI, *complexType.anyAttribute); + if (complexType.mixed + || ( complexType.complexContent + && complexType.complexContent->extension + && complexType.complexContent->extension->complexTypePtr() + && complexType.complexContent->extension->complexTypePtr()->mixed + )) + { 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"); + if (dflag) + { if (with_union) + fprintf(stream, pointerformat, "xsd__anyType", "__mixed"); + else + fprintf(stream, elementformat, "xsd__anyType", "__mixed"); + fprintf(stream, "0;\t///< Catch mixed content in DOM soap_dom_element linked node structure.\n"); + } + else + { fprintf(stream, elementformat, "_XML", "__mixed"); + fprintf(stream, "0;\t///< Catch mixed content in XML string\n"); + } + } + if (t) + modify(t); + if (!anonymous) + { if (!cflag + && !(pflag && complexType.name) + && !soapflag) + { if (!complexType.complexContent || !complexType.complexContent->extension || !complexType.complexContent->extension->complexTypePtr()) + { fprintf(stream, "/// A handle to the soap struct that manages this instance (automatically set)\n"); + fprintf(stream, pointerformat, "struct soap", "soap"); + fprintf(stream, ";\n"); + } + } + fprintf(stream, "};\n"); + } + scope.pop_back(); +} + +void Types::gen(const char *URI, const vector<xs__attribute>& attributes) +{ for (vector<xs__attribute>::const_iterator attribute = attributes.begin(); attribute != attributes.end(); ++attribute) + gen(URI, *attribute); +} + +void Types::gen(const char *URI, const xs__attribute& attribute) +{ const char *name, *type, *nameURI = NULL, *typeURI = NULL, *nameprefix = NULL, *typeprefix = NULL; + name = attribute.name; + type = attribute.type; + bool is_optional = attribute.use != required && attribute.use != default_ && attribute.use != fixed_ && !attribute.default_; + document(attribute.annotation); + if (!URI) + URI = attribute.schemaPtr()->targetNamespace; + if (attribute.form) + { if (*attribute.form == qualified) + nameURI = URI; + else + nameprefix = ":"; + } + if (URI && attribute.schemaPtr() && attribute.schemaPtr()->targetNamespace && strcmp(URI, attribute.schemaPtr()->targetNamespace)) + nameURI = attribute.schemaPtr()->targetNamespace; // handles attributeGroup defined in another namespace + if (attribute.attributePtr()) // attribute ref + { name = attribute.attributePtr()->name; + type = attribute.attributePtr()->type; + if (!type) + { type = name; + typeprefix = "_"; + } + if (attribute.attributePtr()->schemaPtr()) + { typeURI = attribute.attributePtr()->schemaPtr()->targetNamespace; + if (attribute.form && *attribute.form == unqualified) + nameprefix = ":"; + else if (zflag != 3 && zflag != 2 + && URI + && typeURI + && attribute.schemaPtr()->elementFormDefault == qualified + && !strcmp(URI, typeURI)) + nameprefix = NULL; + else if (zflag == 3 + && URI + && typeURI + && attribute.schemaPtr()->attributeFormDefault == unqualified + && !strcmp(URI, typeURI)) + nameprefix = NULL; + else + nameURI = typeURI; + } + fprintf(stream, "/// Attribute reference %s.\n", attribute.ref); + document(attribute.attributePtr()->annotation); + fprintf(stream, attributeformat, pname(is_optional, typeprefix, typeURI, type), aname(nameprefix, nameURI, name)); // make sure no name - type clash + } + else if (name && type) + { fprintf(stream, "/// Attribute %s of type %s.\n", name, type); + fprintf(stream, attributeformat, pname(is_optional, NULL, URI, type), aname(nameprefix, nameURI, name)); // make sure no name - type clash + } + else if (name && attribute.simpleTypePtr()) + { fprintf(stream, "@"); + gen(URI, name, *attribute.simpleTypePtr(), true); + // 8/1/09 Changed (is_optional && !cflag && !sflag) to is_optional + fprintf(stream, is_optional ? pointerformat : elementformat, "", aname(nameprefix, nameURI, name)); + } + else if (attribute.ref) + { fprintf(stream, "/// Imported attribute reference %s.\n", attribute.ref); + fprintf(stream, attributeformat, pname(is_optional, "_", NULL, attribute.ref), aname(NULL, NULL, attribute.ref)); + } + else + { fprintf(stream, "/// Attribute '%s' has no type or ref: assuming string content.\n", name?name:""); + fprintf(stream, attributeformat, tname(NULL, NULL, "xs:string"), aname(NULL, nameURI, name)); + } + switch (attribute.use) + { case prohibited: + fprintf(stream, " 0:0"); + break; + case required: + fprintf(stream, " 1"); + break; + default: + fprintf(stream, " 0"); + break; + } + if (attribute.default_ + || (attribute.fixed && !is_optional)) + { const char *value, *QName; + if (attribute.default_) + { value = attribute.default_; + QName = attribute.default__; + } + else + { value = attribute.fixed; + QName = attribute.fixed_; + } + const char *t = NULL; + if (!type && attribute.simpleTypePtr()) + { if (attribute.simpleTypePtr()->restriction && attribute.simpleTypePtr()->restriction->base) + { if (!attribute.simpleTypePtr()->restriction->enumeration.empty()) + { const char *s; + if (is_integer(value)) + fprintf(stream, " = %s", value); + else if (!*value) + fprintf(stream, " = 0"); + else if ((s = enames[Pair(gname(URI, name),value)])) + fprintf(stream, " = %s", s); + } + else + { const char *baseURI = NULL; + if (attribute.simpleTypePtr()->restriction->simpleTypePtr() && attribute.simpleTypePtr()->restriction->simpleTypePtr()->schemaPtr()) + baseURI = attribute.simpleTypePtr()->restriction->simpleTypePtr()->schemaPtr()->targetNamespace; + t = tname(NULL, baseURI, attribute.simpleTypePtr()->restriction->base); + } + } + } + if (type && !t) + t = tname(NULL, typeURI?typeURI:URI, type); + if (t) + { if (!strncmp(t, "unsigned ", 9)) + t += 9; + else if (!strncmp(t, "xsd__unsigned", 13)) + t += 13; + else if (!strncmp(t, "xsd__", 5)) + t += 5; + if (!strcmp(t, "bool") + || !strcmp(t, "byte") + || !strcmp(t, "Byte") + || !strcmp(t, "char") + || !strcmp(t, "double") + || !strcmp(t, "float") + || !strcmp(t, "int") + || !strcmp(t, "Int") + || !strcmp(t, "long") + || !strcmp(t, "Long") + || !strcmp(t, "LONG64") + || !strcmp(t, "short") + || !strcmp(t, "Short") + || !strcmp(t, "ULONG64")) + fprintf(stream, " = %s", value); + else if (!strncmp(t, "enum ", 5)) + { const char *s; + if (is_integer(value)) + fprintf(stream, " = %s", value); + else if (!*value) + fprintf(stream, " = 0"); + else if ((s = enames[Pair(t + 5,value)])) + fprintf(stream, " = %s", s); + } + else if (!strcmp(t, "char*") + || !strcmp(t, "char *") // not elegant + || !strcmp(t, "std::string") + || !strcmp(t, "std::string*") + || !strcmp(t, "std::string *")) // not elegant + fprintf(stream, " = \"%s\"", cstring(value)); + else if (!strcmp(t, "xsd__QName") && QName) // QName + fprintf(stream, " = \"%s\"", cstring(QName)); + } + if (attribute.default_) + fprintf(stream, ";\t///< Default value=\"%s\".\n", value); + else + fprintf(stream, ";\t///< Fixed required value=\"%s\".\n", value); + } + else if (attribute.fixed) + fprintf(stream, ";\t///< Fixed optional value=\"%s\".\n", attribute.fixed); + else if (attribute.use == required) + fprintf(stream, ";\t///< Required attribute.\n"); + else if (attribute.use == prohibited) + fprintf(stream, ";\t///< Prohibited attribute.\n"); + else + fprintf(stream, ";\t///< Optional attribute.\n"); +} + +void Types::gen(const char *URI, const vector<xs__attributeGroup>& attributeGroups) +{ for (vector<xs__attributeGroup>::const_iterator attributeGroup = attributeGroups.begin(); attributeGroup != attributeGroups.end(); ++attributeGroup) + { const xs__attributeGroup *ag = &*attributeGroup; + if (ag->attributeGroupPtr()) // attributeGroup ref + ag = ag->attributeGroupPtr(); + fprintf(stream, "/// Begin attributeGroup %s.\n", ag->name?ag->name:ag->ref?ag->ref:""); + gen(URI, ag->attribute); + gen(URI, ag->attributeGroup); + if (ag->anyAttribute) + gen(URI, *ag->anyAttribute); + fprintf(stream, "/// End of attributeGroup %s.\n", ag->name?ag->name:ag->ref?ag->ref:""); + } +} + +void Types::gen(const char *URI, const vector<xs__all>& alls) +{ for (vector<xs__all>::const_iterator all = alls.begin(); all != alls.end(); ++all) + gen(URI, *all, NULL, NULL); +} + +void Types::gen(const char *URI, const xs__all& all, const char *minOccurs, const char *maxOccurs) +{ bool tmp_union1 = with_union; + bool tmp_union2 = fake_union; + with_union = false; + fake_union = false; + gen(URI, all.element, minOccurs, maxOccurs); + with_union = tmp_union1; + fake_union = tmp_union2; +} + +void Types::gen(const char *URI, const vector<xs__contents>& contents) +{ for (vector<xs__contents>::const_iterator content = contents.begin(); content != contents.end(); ++content) + { switch ((*content).__union) + { case SOAP_UNION_xs__union_content_element: + if ((*content).__content.element) + gen(URI, *(*content).__content.element, true, NULL, NULL); + break; + case SOAP_UNION_xs__union_content_group: + if ((*content).__content.group) + gen(URI, *(*content).__content.group, NULL, NULL); + break; + case SOAP_UNION_xs__union_content_choice: + if ((*content).__content.choice) + gen(URI, NULL, *(*content).__content.choice, NULL, NULL); + break; + case SOAP_UNION_xs__union_content_sequence: + if ((*content).__content.sequence) + gen(URI, *(*content).__content.sequence, NULL, NULL); + break; + case SOAP_UNION_xs__union_content_any: + if ((*content).__content.any) + gen(URI, *(*content).__content.any, NULL, NULL); + break; + } + } +} + +void Types::gen(const char *URI, const xs__seqchoice& sequence, const char *minOccurs, const char *maxOccurs) +{ const char *s = NULL; + char *t = NULL; + bool tmp_union = with_union; + with_union = false; + if (sequence.minOccurs) + minOccurs = sequence.minOccurs; + if (sequence.maxOccurs) + maxOccurs = sequence.maxOccurs; + if ((minOccurs && strcmp(minOccurs, "1")) + || (maxOccurs && strcmp(maxOccurs, "1"))) + { fprintf(stream, "/// SEQUENCE <xs:sequence"); + if (minOccurs) + fprintf(stream, " minOccurs=\"%s\"", minOccurs); + if (maxOccurs) + fprintf(stream, " maxOccurs=\"%s\"", maxOccurs); + fprintf(stream, ">\n"); + document(sequence.annotation); + s = sname(URI, "sequence"); + t = (char*)emalloc(strlen(s)+2); + strcpy(t, "_"); + strcat(t, s); + s = strstr(s, "__"); + if (!s) + s = t; + if (cflag || sflag || zflag == 2) + { fprintf(stream, sizeformat, "int", s + 1); + if (!fake_union && minOccurs) + fprintf(stream, " %s", minOccurs); + if (maxOccurs + && strcmp(maxOccurs, "1") + && is_integer(maxOccurs)) + fprintf(stream, ":%s", maxOccurs); + fprintf(stream, ";\n"); + } + else + { fprintf(stream, elementformat, "std::vector<", ""); + fprintf(stream, "\n"); + } + if (cflag) + fprintf(stream, " struct %s\n {\n", t); + else + fprintf(stream, " class %s\n {\n", t); + } + else + { if (fake_union) + fprintf(stream, "/// SEQUENCE <xs:sequence>\n"); + document(sequence.annotation); + } + gen(URI, sequence.__contents); + if (s) + { if (cflag || sflag || zflag == 2) + fprintf(stream, pointerformat, "}", s); + else + { fprintf(stream, elementformat, "}>", s); + if (!fake_union && minOccurs) + fprintf(stream, " %s", minOccurs); + if (maxOccurs + && strcmp(maxOccurs, "1") + && is_integer(maxOccurs)) + fprintf(stream, ":%s", maxOccurs); + } + fprintf(stream, ";\n"); + } + if (s || fake_union) + fprintf(stream, "// END OF SEQUENCE\n"); + with_union = tmp_union; +} + +void Types::gen(const char *URI, const vector<xs__element>& elements, const char *minOccurs, const char *maxOccurs) +{ for (vector<xs__element>::const_iterator element = elements.begin(); element != elements.end(); ++element) + gen(URI, *element, true, minOccurs, maxOccurs); +} + +void Types::gen(const char *URI, const xs__element& element, bool substok, const char *minOccurs, const char *maxOccurs) +{ const char *name, *type, *nameURI = NULL, *typeURI = NULL, *nameprefix = NULL, *typeprefix = NULL; + name = element.name; + type = element.type; + document(element.annotation); + if (!URI) + URI = element.schemaPtr()->targetNamespace; + if (element.minOccurs) + minOccurs = element.minOccurs; + if (element.maxOccurs) + maxOccurs = element.maxOccurs; + if (element.xmime__expectedContentTypes) + fprintf(stream, "/// MTOM attachment with content types %s.\n", element.xmime__expectedContentTypes); + if (element.form) + { if (*element.form == qualified) + nameURI = URI; + else + nameprefix = ":"; + } + if (element.elementPtr()) // element ref + { name = element.elementPtr()->name; + type = element.elementPtr()->type; + if (!type) + { type = name; + typeprefix = "_"; + } + if (element.elementPtr()->schemaPtr()) + { typeURI = element.elementPtr()->schemaPtr()->targetNamespace; + if (element.form && *element.form == unqualified) + nameprefix = ":"; + else if (zflag != 3 && zflag != 2 + && URI + && typeURI + && element.schemaPtr()->elementFormDefault == qualified + && !strcmp(URI, typeURI)) + nameprefix = NULL; + else if (zflag == 3 + && URI + && typeURI + && element.schemaPtr()->elementFormDefault == unqualified + && !strcmp(URI, typeURI)) + nameprefix = NULL; + else + nameURI = typeURI; + } + document(element.elementPtr()->annotation); + if (element.elementPtr()->xmime__expectedContentTypes) + fprintf(stream, "/// MTOM attachment with content types %s.\n", element.elementPtr()->xmime__expectedContentTypes); + if (substok && element.elementPtr()->abstract) + { fprintf(stream, "/// Reference %s to abstract element.\n", element.ref); + gen_substitutions(URI, element); + } + else if (substok + && element.elementPtr()->substitutionsPtr() + && !element.elementPtr()->substitutionsPtr()->empty()) + { if (vflag) + fprintf(stderr, "\nWarning: element ref '%s' stands as the head of a substitutionGroup but is not declared abstract\n", element.ref); + gen_substitutions(URI, element); + } + else if (maxOccurs && strcmp(maxOccurs, "1")) // maxOccurs != "1" + { const char *s = tnameptr(cflag && zflag != 1, typeprefix, typeURI, type); + if (cflag || sflag) + { fprintf(stream, "/// Size of the dynamic array of %s is %s..%s\n", s, minOccurs ? minOccurs : "1", maxOccurs); + fprintf(stream, sizeformat, "int", aname(NULL, NULL, name)); + fprintf(stream, " %s", fake_union ? "0" : minOccurs ? minOccurs : "1"); + if (is_integer(maxOccurs)) + fprintf(stream, ":%s", maxOccurs); + fprintf(stream, ";\n"); + if (cflag && zflag != 1) + { fprintf(stream, "/// Array %s of length %s..%s\n", s, minOccurs ? minOccurs : "1", maxOccurs); + fprintf(stream, elementformat, s, aname(nameprefix, nameURI, name)); + } + else + { fprintf(stream, "/// Pointer to array %s of length %s..%s\n", s, minOccurs ? minOccurs : "1", maxOccurs); + fprintf(stream, pointerformat, s, aname(nameprefix, nameURI, name)); + } + } + else + { fprintf(stream, "/// Vector of %s element refs with length %s..%s\n", s, minOccurs ? minOccurs : "1", maxOccurs); + if (with_union) + fprintf(stream, pointervectorformat, s, aname(nameprefix, nameURI, name)); + else + fprintf(stream, vectorformat, s, aname(nameprefix, nameURI, name)); + } + } + else + { fprintf(stream, "/// Element reference %s.\n", element.ref); + fprintf(stream, elementformat, pname((with_union && !cflag && !is_basetypeforunion(typeprefix, typeURI, type)) || fake_union || is_nillable(element), typeprefix, typeURI, type), aname(nameprefix, nameURI, name)); + } + } + else if (name && type) + { if (substok && element.abstract) + { fprintf(stream, "/// Abstract element %s of type %s.\n", name, type); + gen_substitutions(URI, element); + } + else if (substok + && element.substitutionsPtr() + && !element.substitutionsPtr()->empty()) + { if (vflag) + fprintf(stderr, "\nWarning: element '%s' stands as the head of a substitutionGroup but is not declared abstract\n", name); + gen_substitutions(URI, element); + } + else if (maxOccurs && strcmp(maxOccurs, "1")) // maxOccurs != "1" + { const char *s = tnameptr(cflag && zflag != 1, NULL, URI, type); + if (cflag || sflag) + { fprintf(stream, "/// Size of array of %s is %s..%s\n", s, minOccurs ? minOccurs : "1", maxOccurs); + fprintf(stream, sizeformat, "int", aname(NULL, NULL, name)); + fprintf(stream, " %s", fake_union ? "0" : minOccurs ? minOccurs : "1"); + if (is_integer(maxOccurs)) + fprintf(stream, ":%s", maxOccurs); + fprintf(stream, ";\n"); + if (cflag && zflag != 1) + { fprintf(stream, "/// Array %s of length %s..%s\n", s, minOccurs ? minOccurs : "1", maxOccurs); + fprintf(stream, elementformat, s, aname(nameprefix, nameURI, name)); + } + else + { fprintf(stream, "/// Pointer to array %s of length %s..%s\n", s, minOccurs ? minOccurs : "1", maxOccurs); + fprintf(stream, pointerformat, s, aname(nameprefix, nameURI, name)); + } + } + else + { fprintf(stream, "/// Vector of %s with length %s..%s\n", s, minOccurs ? minOccurs : "1", maxOccurs); + if (with_union) + fprintf(stream, pointervectorformat, s, aname(nameprefix, nameURI, name)); + else + fprintf(stream, vectorformat, s, aname(nameprefix, nameURI, name)); + } + } + else + { fprintf(stream, "/// Element %s of type %s.\n", name, type); + fprintf(stream, elementformat, pname((with_union && !cflag && !is_basetypeforunion(NULL, URI, type)) || (fake_union && !element.default_) || is_nillable(element), NULL, URI, type), aname(nameprefix, nameURI, name)); + } + } + else if (name && element.simpleTypePtr()) + { const char *s = ""; + document(element.simpleTypePtr()->annotation); + if (maxOccurs && strcmp(maxOccurs, "1")) // maxOccurs != "1" + { if (cflag || sflag) + { fprintf(stream, "/// Size of %s array is %s..%s\n", name, minOccurs ? minOccurs : "1", maxOccurs); + fprintf(stream, sizeformat, "int", aname(NULL, NULL, name)); + fprintf(stream, " %s", fake_union ? "0" : minOccurs ? minOccurs : "1"); + if (is_integer(maxOccurs)) + fprintf(stream, ":%s", maxOccurs); + fprintf(stream, ";\n"); + } + else + { s = ">"; + fprintf(stream, "/// Vector of %s with length %s..%s\n", name, minOccurs ? minOccurs : "1", maxOccurs); + fprintf(stream, vectorformat_open, "\n"); + } + } + gen(URI, name, *element.simpleTypePtr(), true); + if (is_nillable(element) + || ((cflag || sflag ) && maxOccurs && strcmp(maxOccurs, "1")) // maxOccurs != "1" + || (with_union && !cflag) + || (fake_union && !element.default_)) + fprintf(stream, pointerformat, s, aname(nameprefix, nameURI, name)); + else + fprintf(stream, elementformat, s, aname(nameprefix, nameURI, name)); + } + else if (name && element.complexTypePtr()) + { const char *s = "}"; + document(element.complexTypePtr()->annotation); + if (maxOccurs && strcmp(maxOccurs, "1")) // maxOccurs != "1" + { if (cflag || sflag) + { fprintf(stream, "/// Size of %s array is %s..%s\n", name, minOccurs ? minOccurs : "1", maxOccurs); + fprintf(stream, sizeformat, "int", aname(NULL, NULL, name)); + fprintf(stream, " %s", fake_union ? "0" : minOccurs ? minOccurs : "1"); + if (is_integer(maxOccurs)) + fprintf(stream, ":%s", maxOccurs); + fprintf(stream, ";\n"); + } + else + { s = "}>"; + fprintf(stream, "/// Vector of %s with length %s..%s\n", name, minOccurs ? minOccurs : "1", maxOccurs); + fprintf(stream, vectorformat_open, "\n"); + } + } + gen(URI, name, *element.complexTypePtr(), true); + if (is_nillable(element) + || ((cflag || sflag ) && maxOccurs && strcmp(maxOccurs, "1")) // maxOccurs != "1" + || (with_union && !cflag) + || (fake_union && !element.default_)) + fprintf(stream, pointerformat, s, aname(nameprefix, nameURI, name)); + else + fprintf(stream, elementformat, s, aname(nameprefix, nameURI, name)); + } + else if (element.ref) + { fprintf(stream, "/// Imported element reference %s.\n", element.ref); + if (maxOccurs && strcmp(maxOccurs, "1")) // maxOccurs != "1" + { if (cflag || sflag) + { fprintf(stream, "/// Size of %s array is %s..%s\n", element.ref, minOccurs ? minOccurs : "1", maxOccurs); + fprintf(stream, sizeformat, "int", aname(NULL, NULL, element.ref)); + fprintf(stream, " %s", fake_union ? "0" : minOccurs ? minOccurs : "1"); + if (is_integer(maxOccurs)) + fprintf(stream, ":%s", maxOccurs); + fprintf(stream, ";\n"); + fprintf(stream, pointerformat, pname(true, "_", NULL, element.ref), aname(nameprefix, nameURI, element.ref)); + } + else + { fprintf(stream, "/// Vector of %s with length %s..%s\n", element.ref, minOccurs ? minOccurs : "1", maxOccurs); + fprintf(stream, vectorformat, pname(false, "_", NULL, element.ref), aname(nameprefix, nameURI, element.ref)); + } + } + else + fprintf(stream, elementformat, pname((with_union && !cflag) || fake_union || is_nillable(element), "_", NULL, element.ref), aname(nameprefix, nameURI, element.ref)); + } + else if (name) + { fprintf(stream, "/// Element '%s' has no type or ref (empty or with XML content).\n", name?name:""); + if (maxOccurs && strcmp(maxOccurs, "1")) // maxOccurs != "1" + { if (cflag || sflag) + { fprintf(stream, sizeformat, "int", aname(NULL, NULL, name)); + fprintf(stream, " %s", fake_union ? "0" : minOccurs ? minOccurs : "1"); + if (is_integer(maxOccurs)) + fprintf(stream, ":%s", maxOccurs); + fprintf(stream, ";\n"); + fprintf(stream, "/// Pointer to array of XML.\n"); + fprintf(stream, pointerformat, "_XML", aname(NULL, nameURI, name)); + } + else + { fprintf(stream, "/// Vector of XML with length %s..%s\n", minOccurs ? minOccurs : "1", maxOccurs); + if (with_union) + fprintf(stream, pointervectorformat, "_XML", aname(NULL, nameURI, name)); + else + fprintf(stream, vectorformat, "_XML", aname(NULL, nameURI, name)); + } + } + else + fprintf(stream, elementformat, "_XML", aname(NULL, nameURI, name)); + } + else + fprintf(stream, "/// Element has no name, type, or ref."); + if (!substok + || ( !(element.elementPtr() && element.elementPtr()->abstract) + && !(element.substitutionsPtr() && !element.substitutionsPtr()->empty()) + && !(element.elementPtr() && element.elementPtr()->substitutionsPtr() && !element.elementPtr()->substitutionsPtr()->empty()) + )) + { if (!fake_union && !minOccurs && !element.nillable && !element.default_ && !element.abstract) + fprintf(stream, " 1"); + else if (!fake_union && minOccurs) + fprintf(stream, " %s", minOccurs); + if (maxOccurs && strcmp(maxOccurs, "1") && is_integer(maxOccurs)) + fprintf(stream, ":%s", maxOccurs); + if (element.default_ + || ( element.fixed + && !fake_union + && (!minOccurs || !strcmp(minOccurs, "1")) + && (!maxOccurs || !strcmp(maxOccurs, "1")) + )) + { // determine whether the element can be assigned a default value, this is dependent on the choice of mapping for primitive types + const char *value, *QName; + if (element.default_) + { value = element.default_; + QName = element.default__; + } + else + { value = element.fixed; + QName = element.fixed_; + } + if (type) + { const char *t = tname(NULL, typeURI?typeURI:URI, type); + if (!strncmp(t, "unsigned ", 9)) + t += 9; + else if (!strncmp(t, "xsd__unsigned", 13)) + t += 13; + else if (!strncmp(t, "xsd__", 5)) + t += 5; + if (!strcmp(t, "bool") + || !strcmp(t, "byte") + || !strcmp(t, "Byte") + || !strcmp(t, "char") + || !strcmp(t, "double") + || !strcmp(t, "float") + || !strcmp(t, "int") + || !strcmp(t, "Int") + || !strcmp(t, "long") + || !strcmp(t, "Long") + || !strcmp(t, "LONG64") + || !strcmp(t, "short") + || !strcmp(t, "Short") + || !strcmp(t, "ULONG64")) + fprintf(stream, " = %s", value); + else if (!strncmp(t, "enum ", 5)) + { const char *s; + if (is_integer(value)) + fprintf(stream, " = %s", value); + else if (!*value) + fprintf(stream, " = 0"); + else if ((s = enames[Pair(t + 5, value)])) + fprintf(stream, " = %s", s); + } + else if (!strcmp(t, "char*") + || !strcmp(t, "char *") // not elegant + || !strcmp(t, "std::string") + || !strcmp(t, "std::string*") + || !strcmp(t, "std::string *")) // not elegant + fprintf(stream, " = \"%s\"", cstring(value)); + else if (!strcmp(t, "xsd__QName") && QName) // QName + fprintf(stream, " = \"%s\"", cstring(QName)); + } + if (element.default_) + fprintf(stream, ";\t///< Default value=\"%s\".\n", value); + else + fprintf(stream, ";\t///< Fixed required value=\"%s\".\n", value); + } + else if (element.nillable) + fprintf(stream, ";\t///< Nillable pointer.\n"); + else if (!fake_union && (!minOccurs || !strcmp(minOccurs, "1")) && (!maxOccurs || !strcmp(maxOccurs, "1"))) + fprintf(stream, ";\t///< Required element.\n"); + else if (element.fixed) + fprintf(stream, ";\t///< Fixed optional value=\"%s\".\n", element.fixed); + else if (!fake_union && minOccurs && !strcmp(minOccurs, "0") && (!maxOccurs || !strcmp(maxOccurs, "1"))) + fprintf(stream, ";\t///< Optional element.\n"); + else + fprintf(stream, ";\n"); + } +} + +void Types::gen(const char *URI, const vector<xs__group>& groups) +{ for (vector<xs__group>::const_iterator group = groups.begin(); group != groups.end(); ++group) + gen(URI, *group, NULL, NULL); +} + +void Types::gen(const char *URI, const xs__group& group, const char *minOccurs, const char *maxOccurs) +{ if (group.minOccurs) + minOccurs = group.minOccurs; + if (group.maxOccurs) + maxOccurs = group.maxOccurs; + if (group.groupPtr()) + { if (group.schemaPtr() == group.groupPtr()->schemaPtr()) + gen(URI, *group.groupPtr(), minOccurs, maxOccurs); + else + gen(group.groupPtr()->schemaPtr()->targetNamespace, *group.groupPtr(), minOccurs, maxOccurs); + } + else + { fprintf(stream, "/// GROUP <xs:group name=\"%s\"", group.name ? group.name : ""); + if (minOccurs) + fprintf(stream, " minOccurs=\"%s\"", minOccurs); + if (maxOccurs) + fprintf(stream, " maxOccurs=\"%s\"", maxOccurs); + fprintf(stream, ">\n"); + document(group.annotation); + if (group.all) + gen(URI, *group.all, minOccurs, maxOccurs); + else if (group.choice) + gen(URI, NULL, *group.choice, minOccurs, maxOccurs); + else if (group.sequence) + gen(URI, *group.sequence, minOccurs, maxOccurs); + fprintf(stream, "// END OF GROUP\n"); + } +} + +void Types::gen(const char *URI, const char *name, const xs__seqchoice& choice, const char *minOccurs, const char *maxOccurs) +{ const char *r = NULL, *s = NULL, *t = NULL; + bool use_union = !uflag; + bool wrap_union = false; + bool tmp_union; + if (!URI && choice.schemaPtr()) + URI = choice.schemaPtr()->targetNamespace; + fprintf(stream, "/// CHOICE <xs:choice"); + if (choice.minOccurs) + minOccurs = choice.minOccurs; + if (choice.maxOccurs) + maxOccurs = choice.maxOccurs; + if (minOccurs) + fprintf(stream, " minOccurs=\"%s\"", minOccurs); + if (maxOccurs) + fprintf(stream, " maxOccurs=\"%s\"", maxOccurs); + fprintf(stream, ">\n"); + document(choice.annotation); + for (vector<xs__contents>::const_iterator c1 = choice.__contents.begin(); c1 != choice.__contents.end(); ++c1) + { if ((*c1).__union == SOAP_UNION_xs__union_content_group + || (*c1).__union == SOAP_UNION_xs__union_content_sequence) + { fprintf(stream, "/// Note: <xs:choice> with embedded <xs:sequence> or <xs:group> prevents the use of a union\n"); + use_union = false; + break; + } + } + if (use_union && (cflag || sflag)) + { for (vector<xs__contents>::const_iterator c2 = choice.__contents.begin(); c2 != choice.__contents.end(); ++c2) + { if ((*c2).__union == SOAP_UNION_xs__union_content_element + && (*c2).__content.element + && (*c2).__content.element->maxOccurs + && strcmp((*c2).__content.element->maxOccurs, "1")) + { fprintf(stream, "/// Note: <xs:choice> of element with maxOccurs>1 prevents the use of a union\n"); + use_union = false; + break; + } + } + } + t = uname(URI); + s = strstr(t, "__union"); + if (s) + r = s + 7; + if (!r || !*r) + { r = t; + s = "__union"; + } + if (maxOccurs && strcmp(maxOccurs, "1")) + { if (with_union) + { // Generate a wrapper when we need a union within a union + wrap_union = true; + fprintf(stream, " struct __%s\n {\n", t); + } + fprintf(stream, sizeformat, "int", r); + fprintf(stream, " %s", minOccurs ? minOccurs : "0"); + if (is_integer(maxOccurs)) + fprintf(stream, ":%s", maxOccurs); + fprintf(stream, ";\n"); + if (cflag) + fprintf(stream, " struct _%s\n {\n", t); + else + fprintf(stream, " class _%s\n {\n", t); + } + if (use_union) + { if (!with_union || wrap_union) + { fprintf(stream, choiceformat, "int", r); + if (minOccurs) + fprintf(stream, " %s", minOccurs); + fprintf(stream, ";\t///< Union %s selector: set to SOAP_UNION_%s_<fieldname>%s\n", t, t, minOccurs && !strcmp(minOccurs, "0") ? " or 0" : ""); + if (name) + fprintf(stream, "/// Union for choice in type %s\n", cname(NULL, URI, name)); + fprintf(stream, " union %s\n {\n", t); + } + tmp_union = with_union; + with_union = true; + } + else + { tmp_union = fake_union; + fake_union = true; + } + gen(URI, choice.__contents); + if (use_union) + { with_union = tmp_union; + if (!with_union || wrap_union) + fprintf(stream, elementformat, "}", s+2); + } + else + fake_union = tmp_union; + if (maxOccurs && strcmp(maxOccurs, "1")) + { if (use_union) + fprintf(stream, ";\n"); + fprintf(stream, pointerformat, "}", s); + } + fprintf(stream, ";\n"); + if (wrap_union) + { fprintf(stream, elementformat, "}", s); + fprintf(stream, ";\n"); + } + fprintf(stream, "// END OF CHOICE\n"); +} + +void Types::gen(const char *URI, const vector<xs__any>& anys) +{ for (vector<xs__any>::const_iterator any = anys.begin(); any != anys.end(); ++any) + gen(URI, *any, NULL, NULL); +} + +void Types::gen(const char *URI, const xs__any& any, const char *minOccurs, const char *maxOccurs) +{ fprintf(stream, "/// TODO: <any"); + if (any.namespace_) + fprintf(stream, " namespace=\"%s\"", any.namespace_); + if (any.minOccurs) + minOccurs = any.minOccurs; + if (any.maxOccurs) + maxOccurs = any.maxOccurs; + if (minOccurs) + fprintf(stream, " minOccurs=\"%s\"", minOccurs); + if (maxOccurs) + fprintf(stream, " maxOccurs=\"%s\"", maxOccurs); + 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"); + if (!xflag) + { if (maxOccurs && strcmp(maxOccurs, "1")) + { fprintf(stream, "/// Size of the array of XML or DOM nodes is %s..%s\n", minOccurs ? minOccurs : "1", maxOccurs); + if (cflag || sflag) + { if (!with_union) + { fprintf(stream, sizeformat, "int", ""); + fprintf(stream, "0;\n"); + fprintf(stream, elementformat, pname(true, NULL, NULL, "xsd:any"), "__any"); + } + else + fprintf(stream, elementformat, tname(NULL, NULL, "xsd:any"), "__any"); + } + else if (with_union) + fprintf(stream, pointervectorformat, tname(NULL, NULL, "xsd:any"), "__any"); + else + fprintf(stream, vectorformat, tname(NULL, NULL, "xsd:any"), "__any"); + } + else + fprintf(stream, elementformat, pname(with_union, NULL, NULL, "xsd:any"), "__any"); + if (dflag) + fprintf(stream, "0;\t///< Catch any element content in DOM.\n"); + else + fprintf(stream, "0;\t///< Catch any element content in XML string.\n"); + } +} + +void Types::gen(const char *URI, const xs__anyAttribute& anyAttribute) +{ if (anyAttribute.namespace_) + fprintf(stream, "/// <anyAttribute namespace=\"%s\">\n", anyAttribute.namespace_); + 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"); + if (!xflag) + { const char *t = tname(NULL, NULL, "xsd:anyAttribute"); + fprintf(stream, attributeformat, t, "__anyAttribute"); + if (dflag) + fprintf(stream, ";\t///< Store anyAttribute content in DOM soap_dom_attribute linked node structure.\n"); + else + fprintf(stream, ";\t///< A placeholder that has no effect: please see comment.\n"); + } +} + +void Types::gen_inh(const char *URI, const xs__complexType *complexType, bool anonymous) +{ const xs__complexType *p = complexType; + if (!p) + return; + const char *pURI; + if (p->schemaPtr()) + pURI = p->schemaPtr()->targetNamespace; + else + pURI = URI; + const char *b = cname(NULL, pURI, p->name); + if (p->complexContent && p->complexContent->extension) + gen_inh(URI, p->complexContent->extension->complexTypePtr(), anonymous); + if (cflag || fflag || anonymous) + fprintf(stream, "/// INHERITED FROM %s:\n", b); + else if (comment_nest == 0) + fprintf(stream, "/* INHERITED FROM %s:\n", b); + else + fprintf(stream, " INHERITED FROM %s:\n", b); + comment_nest++; + if (cflag || fflag) + pURI = URI; // if base ns != derived ns then qualify elts + if (p->complexContent && p->complexContent->extension) + { if (p->complexContent->extension->group) + gen(pURI, *p->complexContent->extension->group, NULL, NULL); + if (p->complexContent->extension->all) + gen(pURI, *p->complexContent->extension->all, NULL, NULL); + if (p->complexContent->extension->sequence) + gen(pURI, *p->complexContent->extension->sequence, NULL, NULL); + if (p->complexContent->extension->choice) + gen(pURI, p->name, *p->complexContent->extension->choice, NULL, NULL); + gen(pURI, p->complexContent->extension->attribute); + gen(pURI, p->complexContent->extension->attributeGroup); + if (p->complexContent->extension->anyAttribute) + gen(pURI, *p->complexContent->extension->anyAttribute); + } + else + { if (p->all) + gen(pURI, p->all->element, NULL, NULL); + else if (p->all) + gen(pURI, *p->all, NULL, NULL); + else if (p->choice) + gen(pURI, p->name, *p->choice, NULL, NULL); + else if (p->sequence) + gen(pURI, *p->sequence, NULL, NULL); + else if (p->any) + gen(pURI, *p->any, NULL, NULL); + gen(pURI, p->attribute); + gen(pURI, p->attributeGroup); + if (p->anyAttribute) + gen(pURI, *p->anyAttribute); + } + modify(b); + comment_nest--; + if (cflag || fflag || anonymous) + fprintf(stream, "// END OF INHERITED FROM %s\n", b); + else if (comment_nest == 0) + fprintf(stream, " END OF INHERITED FROM %s */\n", b); + else + fprintf(stream, " END OF INHERITED FROM %s\n", b); +} + +void Types::gen_soap_array(const char *name, const char *t, const char *item, const char *type) +{ char *tmp = NULL, *dims = NULL, size[8]; + if (type) + { tmp = (char*)emalloc(strlen(type) + 1); + strcpy(tmp, type); + } + *size = '\0'; + if (tmp) + dims = strrchr(tmp, '['); + if (dims) + *dims++ = '\0'; + fprintf(stream, "/// SOAP encoded array of %s\n", tmp ? tmp : "xs:anyType"); + if (cflag) + fprintf(stream, "struct %s\n{\n", t); + else if (pflag) + fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", t); + else + fprintf(stream, "class %s\n{ public:\n", t); + if (dims) + { char *s = strchr(dims, ']'); + if (s && s != dims) + sprintf(size, "[%d]", (int)(s - dims + 1)); + } + if (tmp) + { if (strchr(tmp, '[') != NULL) + { gen_soap_array(NULL, "", item, tmp); + fprintf(stream, arrayformat, "}", item ? aname(NULL, NULL, item) : ""); + fprintf(stream, ";\n"); + } + else + { const char *s = pname(!is_basetype(NULL, NULL, tmp), NULL, NULL, tmp); + fprintf(stream, "/// Pointer to array of %s.\n", s); + fprintf(stream, arrayformat, s, item ? aname(NULL, NULL, item) : ""); + fprintf(stream, ";\n"); + } + if (*size) + fprintf(stream, "/// Size of the multidimensional dynamic array with dimensions=%s\n", size); + else + fprintf(stream, "/// Size of the dynamic array.\n"); + fprintf(stream, arraysizeformat, "int", size); + fprintf(stream, ";\n/// Offset for partially transmitted arrays (uncomment only when required).\n"); + fprintf(stream, arrayoffsetformat, "int", size); + fprintf(stream, ";\n"); + } + else + { // TODO: how to handle generic SOAP array? E.g. as an array of anyType? + fprintf(stream, "// TODO: add declarations to handle generic SOAP-ENC:Array (array of anyType)\n"); + } +} + +void Types::gen_substitutions(const char *URI, const xs__element &element) +{ const std::vector<xs__element*> *substitutions; + const char *name; + const char *r = NULL, *s = NULL; + bool use_union = !uflag; + bool wrap_union = false; + bool tmp_union; + bool abstract = false; + if (!URI && element.schemaPtr()) + URI = element.schemaPtr()->targetNamespace; + if (element.elementPtr()) + { name = element.elementPtr()->name; + substitutions = element.elementPtr()->substitutionsPtr(); + abstract = element.elementPtr()->abstract; + if (!abstract && element.elementPtr()->complexTypePtr()) + abstract = element.elementPtr()->complexTypePtr()->abstract; + } + else + { name = element.name; + substitutions = element.substitutionsPtr(); + abstract = element.abstract; + if (!abstract && element.complexTypePtr()) + abstract = element.complexTypePtr()->abstract; + } + fprintf(stream, "/// CHOICE OF SUBSTITUTIONS <xs:element substitutionGroup=\"%s\"", name); + if (element.minOccurs) + fprintf(stream, " minOccurs=\"%s\"", element.minOccurs); + if (element.maxOccurs) + fprintf(stream, " maxOccurs=\"%s\"", element.maxOccurs); + fprintf(stream, "> with elements"); + for (std::vector<xs__element*>::const_iterator i1 = substitutions->begin(); i1 != substitutions->end(); ++i1) + fprintf(stream, " <%s>", (*i1)->name); + fprintf(stream, "\n"); + if (use_union) + { const char *t = uname(URI); + // TODO: could reuse the union instead of generating a new one each time! + s = strstr(t, "__union"); + if (!s) + s = "__union"; + r = aname(NULL, NULL, name); + if (element.maxOccurs && strcmp(element.maxOccurs, "1")) + { if (with_union) + { // Generate a wrapper when we need a union within a union + wrap_union = true; + fprintf(stream, " struct __%s\n {\n", t); + } + fprintf(stream, sizeformat, "int", r); + fprintf(stream, " %s", element.minOccurs ? element.minOccurs : "0"); + if (is_integer(element.maxOccurs)) + fprintf(stream, ":%s", element.maxOccurs); + fprintf(stream, ";\n"); + if (cflag) + fprintf(stream, " struct _%s\n {\n", t); + else + fprintf(stream, " class _%s\n {\n", t); + } + if (!with_union || wrap_union) + { fprintf(stream, choiceformat, "int", r); + fprintf(stream, " %s", element.minOccurs ? element.minOccurs : "0"); + fprintf(stream, ";\t///< Union %s selector: set to SOAP_UNION_%s_<fieldname>%s\n", t, t, element.minOccurs && !strcmp(element.minOccurs, "0") ? " or 0" : ""); + fprintf(stream, "/// Union for substitutionGroup=\"%s\"\n", name); + fprintf(stream, " union %s\n {\n", t); + } + tmp_union = with_union; + with_union = true; + } + else + { tmp_union = fake_union; + fake_union = true; + } + if (!abstract) + gen(URI, element, false, NULL, NULL); + for (vector<xs__element*>::const_iterator i2 = substitutions->begin(); i2 != substitutions->end(); ++i2) + gen(URI, *(*i2), true, NULL, NULL); // substitutions are recursive? + if (use_union) + { with_union = tmp_union; + if (!with_union || wrap_union) + { fprintf(stream, elementformat, "}", s); + fprintf(stream, ";\n"); + } + if (element.maxOccurs && strcmp(element.maxOccurs, "1")) + { fprintf(stream, ";\n"); + fprintf(stream, pointerformat, "}", s); + fprintf(stream, ";\n"); + } + if (wrap_union) + { fprintf(stream, elementformat, "}", s); + fprintf(stream, ";\n"); + } + } + else + fake_union = tmp_union; + fprintf(stream, "// END OF CHOICE OF SUBSTITUTIONS\n"); +} + +void Types::document(const xs__annotation *annotation) +{ if (annotation && annotation->documentation) + { fprintf(stream, "/// @brief"); + documentation(annotation->documentation); + } +} + +void Types::modify(const char *name) +{ // TODO: consider support removal of elements/attributes with ns__X = $- Y + const char *s = modtypemap[name]; + if (s) + { while (*s) + { if (*s++ == '$') + fprintf(stream, "/// Member declared in %s\n ", mapfile); + s = format(s); + } + } +} + +const char* Types::format(const char *text) +{ const char *s = text; + if (!s) + return NULL; + while (*s && *s != '$') + { if (*s == '\\') + { switch (s[1]) + { case 'n': + fputc('\n', stream); + break; + case 't': + fputc('\t', stream); + break; + default: + fputc(s[1], stream); + } + s++; + } + else + fputc(*s, stream); + s++; + } + fputc('\n', stream); + return s; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// Type map file parsing +// +//////////////////////////////////////////////////////////////////////////////// + +static char *getline(char *s, size_t n, FILE *fd) +{ int c; + char *t = s; + if (n) + n--; + for (;;) + { c = fgetc(fd); + if (c == '\r') + continue; + if (c == '\\') + { c = fgetc(fd); + if (c == '\r') + c = fgetc(fd); + if (c < ' ') + continue; + if (n) + { *t++ = '\\'; + n--; + } + } + if (c == '\n' || c == EOF) + break; + if (n) + { *t++ = c; + n--; + } + } + *t++ = '\0'; + if (!*s && c == EOF) + return NULL; + return s; +} + +static const char *nonblank(const char *s) +{ while (*s && isspace(*s)) + s++; + return s; +} + +static const char *fill(char *t, int n, const char *s, int e) +{ int i = n; + s = nonblank(s); + while (*s && *s != e && --i) + *t++ = *s++; + while (*s && *s != e) + s++; + if (*s) + s++; + i = n - i; + if (i == 0) + *t = '\0'; + else + { while (isspace(*--t) && i--) + ; + t[1] = '\0'; + } + return s; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// Miscellaneous +// +//////////////////////////////////////////////////////////////////////////////// + +static const char *utf8(char *t, const char *s) +{ unsigned int c = 0; + unsigned int c1, c2, c3, c4; + c = (unsigned char)*s; + if (c >= 0x80) + { c1 = (unsigned char)*++s; + if (c1 < 0x80) + s--; + else + { c1 &= 0x3F; + if (c < 0xE0) + c = ((c & 0x1F) << 6) | c1; + else + { c2 = (unsigned char)*++s & 0x3F; + if (c < 0xF0) + c = ((c & 0x0F) << 12) | (c1 << 6) | c2; + else + { c3 = (unsigned char)*++s & 0x3F; + if (c < 0xF8) + c = ((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3; + else + { c4 = (unsigned char)*++s & 0x3F; + if (c < 0xFC) + c = ((c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4; + else + c = ((c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (*++s & 0x3F); + } + } + } + } + } + sprintf(t, "_x%.4x", c); + return s; +} + +static const char *cstring(const char *s) +{ size_t n; + char *t; + const char *r; + for (n = 0, r = s; *r; n++, r++) + if (*r == '"' || *r == '\\') + n++; + else if (*r < 32) + n += 3; + r = t = (char*)emalloc(n + 1); + for (; *s; s++) + { if (*s == '"' || *s == '\\') + { *t++ = '\\'; + *t++ = *s; + } + else if (*s < 32) + { sprintf(t, "\\%03o", (unsigned int)(unsigned char)*s); + t += 4; + } + else + *t++ = *s; + } + *t = '\0'; + return r; +} + +static const char *xstring(const char *s) +{ size_t n; + char *t; + const char *r; + for (n = 0, r = s; *r; n++, r++) + { if (*r < 32 || *r >= 127) + n += 4; + else if (*r == '<' || *r == '>') + n += 3; + else if (*r == '&') + n += 4; + else if (*r == '"') + n += 5; + else if (*r == '\\') + n += 1; + } + r = t = (char*)emalloc(n + 1); + for (; *s; s++) + { if (*s < 32 || *s >= 127) + { sprintf(t, "&#%.2x;", (unsigned char)*s); + t += 5; + } + else if (*s == '<') + { strcpy(t, "<"); + t += 4; + } + else if (*s == '>') + { strcpy(t, ">"); + t += 4; + } + else if (*s == '&') + { strcpy(t, "&"); + t += 5; + } + else if (*s == '"') + { strcpy(t, """); + t += 6; + } + else if (*s == '\\') + { strcpy(t, "\\\\"); + t += 2; + } + else + *t++ = *s; + } + *t = '\0'; + return r; +} + +static LONG64 to_integer(const char *s) +{ LONG64 n; +#ifdef HAVE_STRTOLL + char *r; + n = soap_strtoll(s, &r, 10); +#else +# ifdef HAVE_SSCANF + sscanf(s, SOAP_LONG_FORMAT, &n); +# endif +#endif + return n; +} + +static bool is_integer(const char *s) +{ if ((*s == '-' || *s == '+') && s[1]) + s++; + if (!*s || strlen(s) > 20) + return false; + while (*s && isdigit(*s)) + s++; + return *s == '\0'; +} + +static void documentation(const char *text) +{ const char *s = text; + bool flag = true; + if (!s) + return; + while (*s) + { switch (*s) + { case '\n': + case '\t': + case ' ': + flag = true; + break; + default: + if (*s > 32) + { if (flag) + { fputc(' ', stream); + flag = false; + } + fputc(*s, stream); + } + } + s++; + } + fputc('\n', stream); +} + +static void operations(const char *t) +{ if (!cflag) + fprintf(stream, "/// class %s operations:\n/// - soap_new_%s(soap*) allocate\n/// - soap_new_%s(soap*, int num) allocate array\n/// - soap_new_req_%s(soap*, ...) allocate, set required members\n/// - soap_new_set_%s(soap*, ...) allocate, set all public members\n/// - int soap_read_%s(soap*, %s*) deserialize from a stream\n/// - int soap_write_%s(soap, %s*) serialize to a stream\n", t, t, t, t, t, t, t, t, t); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// Allocation +// +//////////////////////////////////////////////////////////////////////////////// + +void *emalloc(size_t size) +{ void *p = malloc(size); + if (!p) + { fprintf(stderr, "\nError: Malloc failed\n"); + exit(1); + } + return p; +} + +char *estrdup(const char *s) +{ char *t = (char*)emalloc(strlen(s) + 1); + strcpy(t, s); + return t; +} + +char *estrdupf(const char *s) +{ char *t = (char*)emalloc(strlen(s) + 1); + char *p; + for (p = t; *s; s++) + { if (s[0] == '/' && s[1] == '*') + { for (s += 2; s[0] && s[1]; s++) + { if (s[0] == '*' && s[1] == '/') + { s++; + break; + } + } + continue; + } + *p++ = *s; + } + *p = '\0'; + return t; +}