123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 |
- /* -----------------------------------------------------------------------------
- * This file is part of SWIG, which is licensed as a whole under version 3
- * (or any later version) of the GNU General Public License. Some additional
- * terms also apply to certain portions of SWIG. The full details of the SWIG
- * license and copyrights can be found in the LICENSE and COPYRIGHT files
- * included with the SWIG source code as distributed by the SWIG developers
- * and at https://www.swig.org/legal.html.
- *
- * nested.cxx
- *
- * Nested structs support
- * ----------------------------------------------------------------------------- */
- #include "swigmod.h"
- #include "cparse.h"
- // Nested classes processing section
- static Hash *classhash = 0;
- static String *make_name(Node *n, String *name, SwigType *decl) {
- int destructor = name && (*(Char(name)) == '~');
- if (String *yyrename = Getattr(n, "class_rename")) {
- String *s = NewString(yyrename);
- Delattr(n, "class_rename");
- if (destructor && (*(Char(s)) != '~')) {
- Insert(s, 0, "~");
- }
- return s;
- }
- if (!name)
- return 0;
- return Swig_name_make(n, 0, name, decl, 0);
- }
- // C version of add_symbols()
- static void add_symbols_c(Node *n) {
- String *decl;
- String *wrn = 0;
- String *symname = 0;
- int iscdecl = Cmp(nodeType(n), "cdecl") == 0;
- Setattr(n, "ismember", "1");
- Setattr(n, "access", "public");
- if (Getattr(n, "sym:name"))
- return;
- decl = Getattr(n, "decl");
- if (!SwigType_isfunction(decl)) {
- String *name = Getattr(n, "name");
- String *makename = Getattr(n, "parser:makename");
- if (iscdecl) {
- String *storage = Getattr(n, "storage");
- if (Cmp(storage, "typedef") == 0) {
- Setattr(n, "kind", "typedef");
- } else {
- SwigType *type = Getattr(n, "type");
- String *value = Getattr(n, "value");
- Setattr(n, "kind", "variable");
- if (value && Len(value)) {
- Setattr(n, "hasvalue", "1");
- }
- if (type) {
- SwigType *ty;
- SwigType *tmp = 0;
- if (decl) {
- ty = tmp = Copy(type);
- SwigType_push(ty, decl);
- } else {
- ty = type;
- }
- if (!SwigType_ismutable(ty)) {
- SetFlag(n, "hasconsttype");
- SetFlag(n, "feature:immutable");
- }
- if (tmp)
- Delete(tmp);
- }
- if (!type) {
- Printf(stderr, "notype name %s\n", name);
- }
- }
- }
- Swig_features_get(Swig_cparse_features(), 0, name, 0, n);
- if (makename) {
- symname = make_name(n, makename, 0);
- Delattr(n, "parser:makename"); /* temporary information, don't leave it hanging around */
- } else {
- makename = name;
- symname = make_name(n, makename, 0);
- }
- if (!symname) {
- symname = Copy(Getattr(n, "unnamed"));
- }
- if (symname) {
- wrn = Swig_name_warning(n, 0, symname, 0);
- }
- } else {
- String *name = Getattr(n, "name");
- SwigType *fdecl = Copy(decl);
- SwigType *fun = SwigType_pop_function(fdecl);
- if (iscdecl) {
- Setattr(n, "kind", "function");
- }
- Swig_features_get(Swig_cparse_features(), 0, name, fun, n);
- symname = make_name(n, name, fun);
- wrn = Swig_name_warning(n, 0, symname, fun);
- Delete(fdecl);
- Delete(fun);
- }
- if (!symname)
- return;
- if (GetFlag(n, "feature:ignore")) {
- /* Only add to C symbol table and continue */
- Swig_symbol_add(0, n);
- } else if (strncmp(Char(symname), "$ignore", 7) == 0) {
- char *c = Char(symname) + 7;
- SetFlag(n, "feature:ignore");
- if (strlen(c)) {
- SWIG_WARN_NODE_BEGIN(n);
- Swig_warning(0, Getfile(n), Getline(n), "%s\n", c + 1);
- SWIG_WARN_NODE_END(n);
- }
- Swig_symbol_add(0, n);
- } else {
- Node *c;
- if ((wrn) && (Len(wrn))) {
- String *metaname = symname;
- if (!Getmeta(metaname, "already_warned")) {
- SWIG_WARN_NODE_BEGIN(n);
- Swig_warning(0, Getfile(n), Getline(n), "%s\n", wrn);
- SWIG_WARN_NODE_END(n);
- Setmeta(metaname, "already_warned", "1");
- }
- }
- c = Swig_symbol_add(symname, n);
- if (c != n) {
- /* symbol conflict attempting to add in the new symbol */
- if (Getattr(n, "sym:weak")) {
- Setattr(n, "sym:name", symname);
- } else {
- String *e = NewStringEmpty();
- String *en = NewStringEmpty();
- String *ec = NewStringEmpty();
- int redefined = Swig_need_redefined_warn(n, c, true);
- if (redefined) {
- Printf(en, "Identifier '%s' redefined (ignored)", symname);
- Printf(ec, "previous definition of '%s'", symname);
- } else {
- Printf(en, "Redundant redeclaration of '%s'", symname);
- Printf(ec, "previous declaration of '%s'", symname);
- }
- if (Cmp(symname, Getattr(n, "name"))) {
- Printf(en, " (Renamed from '%s')", SwigType_namestr(Getattr(n, "name")));
- }
- Printf(en, ",");
- if (Cmp(symname, Getattr(c, "name"))) {
- Printf(ec, " (Renamed from '%s')", SwigType_namestr(Getattr(c, "name")));
- }
- Printf(ec, ".");
- SWIG_WARN_NODE_BEGIN(n);
- if (redefined) {
- Swig_warning(WARN_PARSE_REDEFINED, Getfile(n), Getline(n), "%s\n", en);
- Swig_warning(WARN_PARSE_REDEFINED, Getfile(c), Getline(c), "%s\n", ec);
- } else {
- Swig_warning(WARN_PARSE_REDUNDANT, Getfile(n), Getline(n), "%s\n", en);
- Swig_warning(WARN_PARSE_REDUNDANT, Getfile(c), Getline(c), "%s\n", ec);
- }
- SWIG_WARN_NODE_END(n);
- Printf(e, "%s:%d:%s\n%s:%d:%s\n", Getfile(n), Getline(n), en, Getfile(c), Getline(c), ec);
- Setattr(n, "error", e);
- Delete(e);
- Delete(en);
- Delete(ec);
- }
- }
- }
- Delete(symname);
- }
- /* Strips C-style and C++-style comments from string in-place. */
- static void strip_comments(char *string) {
- int state = 0;
- /*
- * 0 - not in comment
- * 1 - in c-style comment
- * 2 - in c++-style comment
- * 3 - in string
- * 4 - after reading / not in comments
- * 5 - after reading * in c-style comments
- * 6 - after reading \ in strings
- */
- char *c = string;
- while (*c) {
- switch (state) {
- case 0:
- if (*c == '\"')
- state = 3;
- else if (*c == '/')
- state = 4;
- break;
- case 1:
- if (*c == '*')
- state = 5;
- *c = ' ';
- break;
- case 2:
- if (*c == '\n')
- state = 0;
- else
- *c = ' ';
- break;
- case 3:
- if (*c == '\"')
- state = 0;
- else if (*c == '\\')
- state = 6;
- break;
- case 4:
- if (*c == '/') {
- *(c - 1) = ' ';
- *c = ' ';
- state = 2;
- } else if (*c == '*') {
- *(c - 1) = ' ';
- *c = ' ';
- state = 1;
- } else
- state = 0;
- break;
- case 5:
- if (*c == '/')
- state = 0;
- else
- state = 1;
- *c = ' ';
- break;
- case 6:
- state = 3;
- break;
- }
- ++c;
- }
- }
- // Create a %insert with a typedef to make a new name visible to C
- static Node *create_insert(Node *n, bool noTypedef = false) {
- // format a typedef
- String *ccode = Getattr(n, "code");
- Push(ccode, " ");
- if (noTypedef) {
- Push(ccode, Getattr(n, "name"));
- Push(ccode, " ");
- Push(ccode, Getattr(n, "kind"));
- } else {
- Push(ccode, Getattr(n, "kind"));
- Push(ccode, "typedef ");
- Append(ccode, " ");
- Append(ccode, Getattr(n, "tdname"));
- }
- Append(ccode, ";");
- /* Strip comments - further code may break in presence of comments. */
- strip_comments(Char(ccode));
- /* Make all SWIG created typedef structs/unions/classes unnamed else
- redefinition errors occur - nasty hack alert. */
- if (!noTypedef) {
- const char *types_array[3] = { "struct", "union", "class" };
- for (int i = 0; i < 3; i++) {
- char *code_ptr = Char(ccode);
- while (code_ptr) {
- /* Replace struct name (as in 'struct name {...}' ) with whitespace
- name will be between struct and opening brace */
- code_ptr = strstr(code_ptr, types_array[i]);
- if (code_ptr) {
- char *open_bracket_pos;
- code_ptr += strlen(types_array[i]);
- open_bracket_pos = strchr(code_ptr, '{');
- if (open_bracket_pos) {
- /* Make sure we don't have something like struct A a; */
- char *semi_colon_pos = strchr(code_ptr, ';');
- if (!(semi_colon_pos && (semi_colon_pos < open_bracket_pos)))
- while (code_ptr < open_bracket_pos)
- *code_ptr++ = ' ';
- }
- }
- }
- }
- }
- {
- /* Remove SWIG directive %constant which may be left in the SWIG created typedefs */
- char *code_ptr = Char(ccode);
- while (code_ptr) {
- code_ptr = strstr(code_ptr, "%constant");
- if (code_ptr) {
- char *directive_end_pos = strchr(code_ptr, ';');
- if (directive_end_pos) {
- while (code_ptr <= directive_end_pos)
- *code_ptr++ = ' ';
- }
- }
- }
- }
- Node *newnode = NewHash();
- set_nodeType(newnode, "insert");
- Setfile(newnode, Getfile(n));
- Setline(newnode, Getline(n));
- String *code = NewStringEmpty();
- Wrapper_pretty_print(ccode, code);
- Setattr(newnode, "code", code);
- Delete(code);
- Delattr(n, "code");
- return newnode;
- }
- static void insertNodeAfter(Node *n, Node *c) {
- Node *g = parentNode(n);
- set_parentNode(c, g);
- Node *ns = nextSibling(n);
- if (Node *outer = Getattr(c, "nested:outer")) {
- while (ns && outer == Getattr(ns, "nested:outer")) {
- n = ns;
- ns = nextSibling(n);
- }
- }
- if (!ns) {
- set_lastChild(g, c);
- } else {
- set_nextSibling(c, ns);
- set_previousSibling(ns, c);
- }
- set_nextSibling(n, c);
- set_previousSibling(c, n);
- }
- void Swig_nested_name_unnamed_c_structs(Node *n) {
- if (!n)
- return;
- if (!classhash)
- classhash = Getattr(n, "classes");
- Node *c = firstChild(n);
- while (c) {
- Node *next = nextSibling(c);
- if (String *declName = Getattr(c, "nested:unnamed")) {
- if (Node *outer = Getattr(c, "nested:outer")) {
- // generate a name
- String *name = NewStringf("%s_%s", Getattr(outer, "name"), declName);
- Delattr(c, "nested:unnamed");
- // set the name to the class and symbol table
- Setattr(c, "tdname", name);
- Setattr(c, "name", name);
- Swig_symbol_setscope(Getattr(c, "symtab"));
- Swig_symbol_setscopename(name);
- // now that we have a name - gather base symbols
- if (List *publicBases = Getattr(c, "baselist")) {
- List *bases = Swig_make_inherit_list(name, publicBases, 0);
- Swig_inherit_base_symbols(bases);
- Delete(bases);
- }
- Setattr(classhash, name, c);
- // Merge the extension into the symbol table
- if (Node *am = Getattr(Swig_extend_hash(), name)) {
- Swig_extend_merge(c, am);
- Swig_extend_append_previous(c, am);
- Delattr(Swig_extend_hash(), name);
- }
- Swig_symbol_popscope();
- // process declarations following this type (assign correct new type)
- SwigType *ty = Copy(name);
- Node *decl = nextSibling(c);
- List *declList = NewList();
- while (decl && Getattr(decl, "nested:unnamedtype") == c) {
- Setattr(decl, "type", ty);
- Append(declList, decl);
- Delattr(decl, "nested:unnamedtype");
- SetFlag(decl, "feature:immutable");
- add_symbols_c(decl);
- decl = nextSibling(decl);
- }
- Delete(ty);
- Swig_symbol_setscope(Swig_symbol_global_scope());
- add_symbols_c(c);
- Node *ins = create_insert(c);
- insertNodeAfter(c, ins);
- removeNode(c);
- insertNodeAfter(n, c);
- Delete(ins);
- Delattr(c, "nested:outer");
- } else {
- // global unnamed struct - ignore it and its instances
- SetFlag(c, "feature:ignore");
- while (next && Getattr(next, "nested:unnamedtype") == c) {
- SetFlag(next, "feature:ignore");
- next = nextSibling(next);
- }
- c = next;
- continue;
- }
- } else if (cparse_cplusplusout) {
- if (Getattr(c, "nested:outer")) {
- Node *ins = create_insert(c, true);
- insertNodeAfter(c, ins);
- Delete(ins);
- Delattr(c, "nested:outer");
- }
- }
- // process children
- Swig_nested_name_unnamed_c_structs(c);
- c = next;
- }
- }
- static void remove_outer_class_reference(Node *n) {
- for (Node *c = firstChild(n); c; c = nextSibling(c)) {
- if (GetFlag(c, "feature:flatnested") || Language::instance()->nestedClassesSupport() == Language::NCS_None) {
- Delattr(c, "nested:outer");
- remove_outer_class_reference(c);
- }
- }
- }
- void Swig_nested_process_classes(Node *n) {
- if (!n)
- return;
- Node *c = firstChild(n);
- while (c) {
- Node *next = nextSibling(c);
- if (!Getattr(c, "templatetype")) {
- if (GetFlag(c, "nested") && (GetFlag(c, "feature:flatnested") || Language::instance()->nestedClassesSupport() == Language::NCS_None)) {
- removeNode(c);
- if (!checkAttribute(c, "access", "public"))
- SetFlag(c, "feature:ignore");
- else if (Strcmp(nodeType(n),"extend") == 0 && Strcmp(nodeType(parentNode(n)),"class") == 0)
- insertNodeAfter(parentNode(n), c);
- else
- insertNodeAfter(n, c);
- }
- Swig_nested_process_classes(c);
- }
- c = next;
- }
- remove_outer_class_reference(n);
- }
|