diff options
author | robot-piglet <[email protected]> | 2025-08-28 14:27:58 +0300 |
---|---|---|
committer | robot-piglet <[email protected]> | 2025-08-28 14:57:06 +0300 |
commit | 81d828c32c8d5477cb2f0ce5da06a1a8d9392ca3 (patch) | |
tree | 3081d566f0d5158d76e9093261344f6406fd09f7 /contrib/tools/swig/Source/Swig/fragment.c | |
parent | 77ea11423f959e51795cc3ef36a48d808b4ffb98 (diff) |
Intermediate changes
commit_hash:d5b1af16dbe9030537a04c27eb410c88c2f496cd
Diffstat (limited to 'contrib/tools/swig/Source/Swig/fragment.c')
-rw-r--r-- | contrib/tools/swig/Source/Swig/fragment.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/contrib/tools/swig/Source/Swig/fragment.c b/contrib/tools/swig/Source/Swig/fragment.c new file mode 100644 index 00000000000..84731f52ffa --- /dev/null +++ b/contrib/tools/swig/Source/Swig/fragment.c @@ -0,0 +1,188 @@ +/* ----------------------------------------------------------------------------- + * 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. + * + * fragment.c + * + * This file manages named code fragments. Code fragments are typically + * used to hold helper-code that may or may not be included in the wrapper + * file (depending on what features are actually used in the interface). + * + * By using fragments, it's possible to greatly reduce the amount of + * wrapper code and to generate cleaner wrapper files. + * ----------------------------------------------------------------------------- */ + +#include "swig.h" +#include "swigwarn.h" +#include "cparse.h" + +static Hash *fragments = 0; +static Hash *looking_fragments = 0; +static int debug = 0; + + +/* ----------------------------------------------------------------------------- + * Swig_fragment_register() + * + * Add a fragment. Use the original Node*, so, if something needs to be + * changed, lang.cxx doesn't need to be touched again. + * ----------------------------------------------------------------------------- */ + +void Swig_fragment_register(Node *fragment) { + if (Getattr(fragment, "emitonly")) { + Swig_fragment_emit(fragment); + return; + } else { + String *name = Copy(Getattr(fragment, "value")); + String *type = Getattr(fragment, "type"); + if (type) { + SwigType *rtype = SwigType_typedef_resolve_all(type); + String *mangle = Swig_name_mangle_type(type); + Append(name, mangle); + Delete(mangle); + Delete(rtype); + if (debug) + Printf(stdout, "register fragment %s %s\n", name, type); + } + if (!fragments) { + fragments = NewHash(); + } + if (!Getattr(fragments, name)) { + String *section = Copy(Getattr(fragment, "section")); + String *ccode = Copy(Getattr(fragment, "code")); + Hash *kwargs = Getattr(fragment, "kwargs"); + Setmeta(ccode, "section", section); + if (kwargs) { + Setmeta(ccode, "kwargs", kwargs); + } + Setfile(ccode, Getfile(fragment)); + Setline(ccode, Getline(fragment)); + /* Replace $descriptor() macros */ + Swig_cparse_replace_descriptor(ccode); + Setattr(fragments, name, ccode); + if (debug) + Printf(stdout, "registering fragment %s %s\n", name, section); + Delete(section); + Delete(ccode); + } + Delete(name); + } +} + +/* ----------------------------------------------------------------------------- + * Swig_fragment_emit() + * + * Emit a fragment + * ----------------------------------------------------------------------------- */ + +static +char *char_index(char *str, char c) { + while (*str && (c != *str)) + ++str; + return (c == *str) ? str : 0; +} + +void Swig_fragment_emit(Node *n) { + String *code; + char *pc, *tok; + String *t; + String *mangle = 0; + String *name = 0; + String *type = 0; + + name = Getattr(n, "value"); + if (!name) { + name = n; + } + + if (!fragments) { + Swig_warning(WARN_FRAGMENT_NOT_FOUND, Getfile(n), Getline(n), "Fragment '%s' not found.\n", name); + return; + } + + type = Getattr(n, "type"); + if (type) { + mangle = Swig_name_mangle_type(type); + } + + if (debug) + Printf(stdout, "looking fragment %s %s\n", name, type); + t = Copy(name); + tok = Char(t); + pc = char_index(tok, ','); + if (pc) + *pc = 0; + while (tok) { + String *name = NewString(tok); + if (mangle) + Append(name, mangle); + if (looking_fragments && Getattr(looking_fragments, name)) { + return; + } + code = Getattr(fragments, name); + if (debug) + Printf(stdout, "looking subfragment %s\n", name); + if (code && (Strcmp(code, "ignore") != 0)) { + String *section = Getmeta(code, "section"); + Hash *nn = Getmeta(code, "kwargs"); + if (!looking_fragments) + looking_fragments = NewHash(); + Setattr(looking_fragments, name, "1"); + while (nn) { + if (Equal(Getattr(nn, "name"), "fragment")) { + if (debug) + Printf(stdout, "emitting fragment %s %s\n", nn, type); + Setfile(nn, Getfile(n)); + Setline(nn, Getline(n)); + Swig_fragment_emit(nn); + } + nn = nextSibling(nn); + } + if (section) { + File *f = Swig_filebyname(section); + if (!f) { + Swig_error(Getfile(code), Getline(code), "Bad section '%s' in %%fragment declaration for code fragment '%s'\n", section, name); + } else { + if (debug) + Printf(stdout, "emitting subfragment %s %s\n", name, section); + if (debug) + Printf(f, "/* begin fragment %s */\n", name); + Printf(f, "%s\n", code); + if (debug) + Printf(f, "/* end fragment %s */\n\n", name); + Setattr(fragments, name, "ignore"); + Delattr(looking_fragments, name); + } + } + } else if (!code && type) { + SwigType *rtype = SwigType_typedef_resolve_all(type); + if (!Equal(type, rtype)) { + String *name = Copy(Getattr(n, "value")); + String *mangle = Swig_name_mangle_type(type); + Append(name, mangle); + Setfile(name, Getfile(n)); + Setline(name, Getline(n)); + Swig_fragment_emit(name); + Delete(mangle); + Delete(name); + } + Delete(rtype); + } + + if (!code) { + Swig_warning(WARN_FRAGMENT_NOT_FOUND, Getfile(n), Getline(n), "Fragment '%s' not found.\n", name); + } + tok = pc ? pc + 1 : 0; + if (tok) { + pc = char_index(tok, ','); + if (pc) + *pc = 0; + } + Delete(name); + } + Delete(t); +} |