Mercurial > repos > ktnyt > gembassy
view 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 source
/* 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; }