git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@4426 626c5289-ae23-0410-ae9c-e8d60b6d4f22
2073 lines
55 KiB
C++
2073 lines
55 KiB
C++
/********************************************************************
|
|
* CHICKEN module for SWIG
|
|
*
|
|
* Author : Jonah Beckford
|
|
*
|
|
* Modified from mzscheme.cxx, guile.cxx and python.cxx : David
|
|
* Beazley
|
|
*
|
|
* Please read the file LICENSE for the copyright and terms by which
|
|
* SWIG can be used and distributed.
|
|
*
|
|
********************************************************************/
|
|
|
|
char cvsroot_chicken_cxx[] = "$Header$";
|
|
|
|
/***********************************************************************
|
|
* $Header$
|
|
*
|
|
* chicken.cxx
|
|
*
|
|
* Definitions for adding functions to CHICKEN
|
|
***********************************************************************/
|
|
|
|
#include "swigmod.h"
|
|
|
|
#ifndef MACSWIG
|
|
#include "swigconfig.h"
|
|
#endif
|
|
|
|
#include <ctype.h>
|
|
|
|
static const char *chicken_usage = (char*)"\
|
|
\
|
|
CHICKEN Options (available with -chicken)\n\
|
|
-help - Print this help.\n\
|
|
-prefix name - Set a prefix to be prepended to all names.\n\
|
|
Defaults to the name of the module.\n\
|
|
-noprefix - Don't use a prefix.\n\
|
|
-mixed - Convert mixed case (ex. aMethodName) into \n\
|
|
dash seperated, lower case (ex. a-method-name).\n\
|
|
-noclos - Don't generate clos TinyCLOS code.\n\
|
|
-nogeneric - Don't generate (make-generic) definitions.\n\
|
|
-ldflags - Print runtime libraries to link with.\n\
|
|
\n"
|
|
;
|
|
|
|
#define SCMCLOS_MEMBER 0x2
|
|
#define SCMCLOS_STATIC_MEMBER 0x4
|
|
|
|
static String *prefix=0;
|
|
static int noprefix=0;
|
|
static String *module=0;
|
|
static char *chicken_path=(char*)"chicken";
|
|
static int clos = 1;
|
|
static int generic = 1;
|
|
static int mixed = 0;
|
|
static int num_methods = 0;
|
|
|
|
static File *f_runtime = 0;
|
|
static File *f_header = 0;
|
|
static File *f_wrappers = 0;
|
|
static File *f_init_helper = 0;
|
|
static File *f_sym_size = 0;
|
|
static File *f_init = 0;
|
|
static File *f_scm = 0;
|
|
static File *f_scm_stubs = 0;
|
|
static File *f_clos = 0;
|
|
static File *f_generic = 0;
|
|
|
|
static String *clos_indent = 0;
|
|
|
|
/* C++ Support + Clos Classes */
|
|
static int in_class = 0;
|
|
static int classic = 0;
|
|
static int have_constructor;
|
|
|
|
static String *class_name = 0;
|
|
static String *short_class_name = 0;
|
|
static String *real_classname;
|
|
|
|
static Hash *known_classes = 0;
|
|
|
|
class CHICKEN : public Language {
|
|
public:
|
|
|
|
virtual void main(int argc, char *argv[]);
|
|
virtual int top(Node *n);
|
|
virtual int importDirective(Node *n);
|
|
virtual int insertDirective(Node *n);
|
|
virtual int functionWrapper(Node *n);
|
|
/* ------------------------------------------------------------
|
|
* variableWrapper()
|
|
*
|
|
* Create a link to a C variable. This creates a single function
|
|
* _wrap_swig_var_varname(). This function takes a single optional
|
|
* argument. If supplied, it means we are setting this variable to
|
|
* some value. If omitted, it means we are simply evaluating this
|
|
* variable. Either way, we return the variables value.
|
|
* ------------------------------------------------------------ */
|
|
virtual int variableWrapper(Node *n);
|
|
virtual int constantWrapper(Node *n);
|
|
virtual int classDeclaration(Node *n);
|
|
virtual int classHandler(Node *n);
|
|
virtual int memberfunctionHandler(Node *n);
|
|
virtual int membervariableHandler(Node *n);
|
|
virtual int memberconstantHandler(Node *n);
|
|
virtual int staticmemberfunctionHandler(Node *n);
|
|
virtual int staticmembervariableHandler(Node *n);
|
|
virtual int destructorHandler(Node *n);
|
|
virtual int constructorHandler(Node *n);
|
|
virtual int validIdentifier(String *s);
|
|
|
|
protected:
|
|
void addMethod(String *, String *scheme_name, String *function);
|
|
void throwUnhandledChickenTypeError(SwigType *d);
|
|
/* Return true iff T is a pointer type */
|
|
int isPointer(SwigType *t);
|
|
void dispatchFunction(Node *n);
|
|
/* Output CHICKEN code into the clos file */
|
|
String* chickenCode(String *code, const String *indent);
|
|
void namify(String *scmname);
|
|
/* search for a typemap("TYPEMAP") SEARCHCLASS */
|
|
String* singleSearch(const char *typemap, char *argname,
|
|
SwigType *searchClass);
|
|
/* do a recursive search for a typemap("TYPEMAP") SEARCHCLASS.
|
|
example: typename can be "in" or "out"; argname can be "result"
|
|
for output typemaps or Getattr(parm, "name") for an input
|
|
parameter, and 'n' may be a class definition or anything else. */
|
|
String* recurseSearch(const char *typemap, char *argname, Node *n);
|
|
void selectOutOneOrMany(String *tm, int is_many);
|
|
};
|
|
|
|
/* -----------------------------------------------------------------------
|
|
* swig_chicken() - Instantiate module
|
|
* ----------------------------------------------------------------------- */
|
|
|
|
extern "C" Language *
|
|
swig_chicken(void) {
|
|
return new CHICKEN();
|
|
}
|
|
|
|
void
|
|
CHICKEN::main(int argc, char *argv[])
|
|
{
|
|
int i;
|
|
|
|
SWIG_library_directory(chicken_path);
|
|
|
|
// Look for certain command line options
|
|
for (i = 1; i < argc; i++) {
|
|
if (argv[i]) {
|
|
if (strcmp(argv[i], "-help") == 0) {
|
|
fputs(chicken_usage, stderr);
|
|
SWIG_exit(0);
|
|
}
|
|
else if (strcmp(argv[i], "-prefix") == 0) {
|
|
if (argv[i + 1]) {
|
|
prefix = NewString(argv [i + 1]);
|
|
Swig_mark_arg(i);
|
|
Swig_mark_arg(i + 1);
|
|
i++;
|
|
}
|
|
else {
|
|
Swig_arg_error();
|
|
}
|
|
}
|
|
else if (strcmp(argv[i],"-noprefix") == 0) {
|
|
noprefix = 1;
|
|
Swig_mark_arg(i);
|
|
}
|
|
else if (strcmp(argv[i],"-mixed") == 0) {
|
|
mixed = 1;
|
|
Swig_mark_arg(i);
|
|
}
|
|
else if (strcmp(argv[i],"-noclos") == 0) {
|
|
clos = 0;
|
|
Swig_mark_arg(i);
|
|
}
|
|
else if (strcmp(argv[i],"-nogeneric") == 0) {
|
|
generic = 0;
|
|
Swig_mark_arg(i);
|
|
}
|
|
else if (strcmp(argv[i], "-ldflags") == 0) {
|
|
printf("%s\n", SWIG_CHICKEN_RUNTIME);
|
|
SWIG_exit(EXIT_SUCCESS);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add a symbol for this module
|
|
|
|
Preprocessor_define("SWIGCHICKEN 1",0);
|
|
|
|
// Set name of typemaps
|
|
|
|
SWIG_typemap_lang("chicken");
|
|
|
|
// Read in default typemaps */
|
|
SWIG_config_file("chicken.swg");
|
|
allow_overloading();
|
|
}
|
|
|
|
int
|
|
CHICKEN::top(Node *n)
|
|
{
|
|
if (!CPlusPlus) {
|
|
clos = 0;
|
|
generic = 0;
|
|
}
|
|
|
|
known_classes = NewHash();
|
|
|
|
/* Initialize all of the output files */
|
|
String *outfile = Getattr(n,"outfile");
|
|
|
|
f_runtime = NewFile(outfile,"w");
|
|
if (!f_runtime) {
|
|
Printf(stderr,"*** Can't open '%s'\n", outfile);
|
|
SWIG_exit(EXIT_FAILURE);
|
|
}
|
|
f_sym_size = NewString("");
|
|
f_init_helper = NewString("\n");
|
|
f_init = NewString("");
|
|
f_header = NewString("");
|
|
f_wrappers = NewString("");
|
|
|
|
/* Register file targets with the SWIG file handler */
|
|
Swig_register_filebyname("header",f_header);
|
|
Swig_register_filebyname("wrapper",f_wrappers);
|
|
Swig_register_filebyname("runtime",f_runtime);
|
|
Swig_register_filebyname("init_helper",f_init_helper);
|
|
Swig_register_filebyname("init",f_init);
|
|
|
|
Printf(f_runtime, "/* -*- buffer-read-only: t -*- vi: set ro: */\n");
|
|
Swig_banner(f_runtime);
|
|
|
|
if (NoInclude) {
|
|
Printf(f_runtime, "#define SWIG_NOINCLUDE\n");
|
|
}
|
|
|
|
/* Set module name */
|
|
module = Copy(Getattr(n,"name"));
|
|
|
|
/* Set prefix. If a prefix has been specified make sure it ends
|
|
in a '-' */
|
|
if (noprefix) {
|
|
prefix = NewString("");
|
|
}
|
|
else {
|
|
if (!prefix) {
|
|
prefix = Copy(module);
|
|
}
|
|
if (Len(prefix) && ((Char(prefix)) [Len(prefix) - 1] != ':')) {
|
|
Append(prefix, ":");
|
|
}
|
|
}
|
|
|
|
char filen[256];
|
|
|
|
sprintf(filen,"%s%s.scm", Swig_file_dirname(outfile), Char(module));
|
|
if ((f_scm = NewFile(filen,"w")) == 0) {
|
|
Printf(stderr,"Unable to open %s\n", filen);
|
|
SWIG_exit(EXIT_FAILURE);
|
|
}
|
|
f_scm_stubs = NewString("");
|
|
|
|
Swig_register_filebyname("chicken",f_scm);
|
|
|
|
Printv(f_scm,
|
|
";; -*- buffer-read-only: t -*- vi: set ro:\n",
|
|
";; This file was created automatically by SWIG.\n",
|
|
";; Don't modify this file, modify the SWIG interface instead.\n",
|
|
NIL);
|
|
Printv(f_scm,"(cond-expand ((or chicken-compile-shared shared)) (else (declare (unit ", module, "))))\n\n", NIL);
|
|
#ifdef JONAH_IS_CRAZY
|
|
Printv(f_scm,"(declare \n",
|
|
tab4, "(foreign-declare \"void* ", module,
|
|
"_swig_get_type(char*);\"))\n", NIL);
|
|
#endif
|
|
#ifndef INIT_BINDING
|
|
Printv(f_scm,"(declare \n",
|
|
tab4, "(hide swig-init)\n",
|
|
tab4, "(foreign-declare \"C_extern void ", module,
|
|
"_swig_init(int,C_word,C_word) C_noret;\"))\n", NIL);
|
|
Printv(f_scm,"(define swig-init (##core#primitive \"", module,
|
|
"_swig_init\"))\n", NIL);
|
|
Printv(f_scm,"(swig-init)\n\n", NIL);
|
|
#endif
|
|
#ifdef JONAH_IS_CRAZY
|
|
Printv(f_scm,"(define-record swig-",prefix,"tag class name ptr str)\n",
|
|
"(define-record-printer (swig-",prefix,"tag tag out)\n",
|
|
tab4, "(fprintf out \"#<tag ~S>(~A)\" (swig-",prefix,
|
|
"tag-str tag)\n",
|
|
tab8, "(swig-",prefix,"tag-ptr tag)))\n", NIL);
|
|
#endif
|
|
|
|
// Include some information in the code
|
|
Printf(f_header,"\n/*-----------------------------------------------\n @(target):= %s.so\n\
|
|
------------------------------------------------*/\n", module);
|
|
|
|
|
|
if (generic) {
|
|
sprintf(filen,"%s%s_generic.scm", Swig_file_dirname(outfile),
|
|
Char(module));
|
|
if ((f_generic = NewFile(filen,"w")) == 0) {
|
|
Printf(stderr,"Unable to open %s\n", filen);
|
|
SWIG_exit (EXIT_FAILURE);
|
|
}
|
|
|
|
Swig_register_filebyname("generic",f_generic);
|
|
|
|
Printv(f_generic,
|
|
";; -*- buffer-read-only: t -*- vi: set ro:\n",
|
|
";; This file was created automatically by SWIG.\n",
|
|
";; Don't modify this file, modify the SWIG interface instead.\n",
|
|
NIL);
|
|
}
|
|
|
|
if (clos) {
|
|
sprintf(filen,"%s%s_clos.scm", Swig_file_dirname(outfile),
|
|
Char(module));
|
|
if ((f_clos = NewFile(filen,"w")) == 0) {
|
|
Printf(stderr,"Unable to open %s\n", filen);
|
|
SWIG_exit (EXIT_FAILURE);
|
|
}
|
|
|
|
Swig_register_filebyname("clos",f_clos);
|
|
|
|
Printv(f_clos,
|
|
";; -*- buffer-read-only: t -*- vi: set ro:\n",
|
|
";; This file was created automatically by SWIG.\n",
|
|
";; Don't modify this file, modify the SWIG interface instead.\n",
|
|
NIL);
|
|
Printf (f_clos, "(declare (uses extras))\n");
|
|
}
|
|
|
|
Printf(f_header,"#define SWIG_name \"%s\"\n", module);
|
|
|
|
Printf(f_wrappers,"#ifdef __cplusplus\n");
|
|
Printf(f_wrappers,"extern \"C\" {\n");
|
|
Printf(f_wrappers,"#endif\n\n");
|
|
|
|
#ifdef JONAH_IS_CRAZY
|
|
Printv(f_init_helper,
|
|
"#ifdef __cplusplus\n",
|
|
"extern \"C\"\n",
|
|
"#endif\n",
|
|
"SWIGEXPORT(void *) ", module, "_swig_get_type (char *type) {\n",
|
|
"int i;\n",
|
|
"for (i = 0; swig_types_initial[i]; i++) {\n",
|
|
"if (strcmp (type, swig_types[i]->name) == 0) ",
|
|
"return swig_types[i];\n",
|
|
"}\n",
|
|
"return NULL;\n",
|
|
"}\n\n",
|
|
NIL);
|
|
#endif
|
|
Printf(f_init_helper,
|
|
"static void swig_init_helper (C_word continuation) C_noret;\n");
|
|
Printf(f_init_helper,
|
|
"static void swig_init_helper (C_word continuation) {\n");
|
|
Printf(f_init_helper, "C_word sym;\n");
|
|
Printf(f_init_helper, "C_word tmp;\n");
|
|
Printf(f_init_helper, "C_word *a = C_alloc (2*$nummethods$symsize);\n");
|
|
|
|
#ifdef INIT_BINDING
|
|
{
|
|
String *tmp = NewString("");
|
|
String *tmp2 = NewString("swig-init");
|
|
Printv(tmp, module, "_swig_init", NIL);
|
|
addMethod(tmp, tmp2, tmp);
|
|
Delete(tmp);
|
|
Delete(tmp2);
|
|
}
|
|
#endif
|
|
|
|
/* emit code */
|
|
Language::top(n);
|
|
|
|
/* Close language module */
|
|
|
|
SwigType_emit_type_table(f_runtime, f_wrappers);
|
|
|
|
Printf(f_wrappers,"#ifdef __cplusplus\n");
|
|
Printf(f_wrappers,"}\n");
|
|
Printf(f_wrappers,"#endif\n");
|
|
|
|
Printf(f_init_helper, "C_kontinue (continuation, C_SCHEME_TRUE);\n");
|
|
Printf(f_init_helper, "}\n");
|
|
char buftmp[20];
|
|
sprintf(buftmp, "%d", num_methods);
|
|
Replaceall(f_init_helper, "$nummethods", buftmp);
|
|
Replaceall(f_init_helper, "$symsize", f_sym_size);
|
|
|
|
Printv(f_scm, f_scm_stubs, "\n",NIL);
|
|
Close(f_scm);
|
|
Delete(f_scm);
|
|
|
|
if (clos) {
|
|
Close(f_clos);
|
|
Delete(f_clos);
|
|
}
|
|
|
|
if (generic) {
|
|
Close(f_generic);
|
|
Delete(f_generic);
|
|
}
|
|
|
|
Delete(prefix);
|
|
Delete(known_classes);
|
|
|
|
/* Close all of the files */
|
|
Dump(f_header,f_runtime);
|
|
Dump(f_wrappers,f_runtime);
|
|
Wrapper_pretty_print(f_init_helper,f_runtime);
|
|
Wrapper_pretty_print(f_init,f_runtime);
|
|
Delete(f_header);
|
|
Delete(f_wrappers);
|
|
Delete(f_sym_size);
|
|
Delete(f_init_helper);
|
|
Delete(f_init);
|
|
Close(f_runtime);
|
|
Delete(f_runtime);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
int
|
|
CHICKEN::importDirective(Node *n)
|
|
{
|
|
String *modname = Getattr(n,"module");
|
|
if (modname) {
|
|
Printf(f_scm,"(declare (uses %s))\n", modname);
|
|
}
|
|
return Language::importDirective(n);
|
|
}
|
|
|
|
int
|
|
CHICKEN::insertDirective(Node *n)
|
|
{
|
|
String *code = Getattr(n,"code");
|
|
Replaceall(code, "$module", module);
|
|
return Language::insertDirective(n);
|
|
}
|
|
|
|
int
|
|
CHICKEN::functionWrapper(Node *n)
|
|
{
|
|
|
|
String *name = Getattr(n,"name");
|
|
String *iname = Getattr(n,"sym:name");
|
|
SwigType *d = Getattr(n,"type");
|
|
ParmList *l = Getattr(n,"parms");
|
|
|
|
Parm *p;
|
|
int i;
|
|
String *wname;
|
|
char source[64];
|
|
Wrapper *f;
|
|
String *mangle = NewString("");
|
|
String *known_alloca;
|
|
String *known_alloca_plus;
|
|
String *get_pointers;
|
|
String *cleanup;
|
|
String *outarg;
|
|
String *tm;
|
|
String *am;
|
|
String *overname = 0;
|
|
String *declfunc = 0;
|
|
String *scmname;
|
|
String *closparam;
|
|
String *closargs;
|
|
String *closwrapargs;
|
|
|
|
int num_required;
|
|
int num_arguments;
|
|
|
|
Printf(mangle, "\"%s\"", SwigType_manglestr(d));
|
|
|
|
if (Getattr(n,"sym:overloaded")) {
|
|
overname = Getattr(n,"sym:overname");
|
|
} else {
|
|
if (!addSymbol(iname,n)) return SWIG_ERROR;
|
|
}
|
|
|
|
f = NewWrapper();
|
|
wname = NewString("");
|
|
known_alloca = NewString("");
|
|
known_alloca_plus = NewString("");
|
|
get_pointers = NewString("");
|
|
cleanup = NewString("");
|
|
outarg = NewString("");
|
|
declfunc = NewString("");
|
|
closargs = NewString("");
|
|
closwrapargs = NewString("");
|
|
scmname = NewString(iname);
|
|
namify(scmname);
|
|
|
|
/* Local vars */
|
|
Wrapper_add_local(f,"resultobj", "C_word resultobj");
|
|
|
|
/* Write code to extract function parameters. */
|
|
emit_args(d, l, f);
|
|
|
|
/* Attach the standard typemaps */
|
|
emit_attach_parmmaps(l,f);
|
|
Setattr(n,"wrap:parms",l);
|
|
|
|
/* Get number of required and total arguments */
|
|
num_arguments = emit_num_arguments(l);
|
|
num_required = emit_num_required(l);
|
|
|
|
Append(wname, module);
|
|
Append(wname, Swig_name_wrapper(iname));
|
|
if (overname) {
|
|
Append(wname, overname);
|
|
}
|
|
|
|
// Check for interrupts
|
|
Printv (f->code, "C_check_for_interrupt;\n",
|
|
"C_trace(\"",scmname,"\");\n", NIL);
|
|
|
|
Printv(f->def,
|
|
#ifndef BINDING
|
|
"static ",
|
|
#endif
|
|
"void ", wname,
|
|
" (int argc, C_word closure, C_word continuation",
|
|
NIL);
|
|
Printv(declfunc,
|
|
"void ", wname,
|
|
"(int,C_word,C_word",
|
|
NIL);
|
|
|
|
/* Calculate fixed alloca code */
|
|
int result_list_len = 0;
|
|
int has_void_return = 0;
|
|
int will_alloca = 0;
|
|
for (p = l; p;) {
|
|
if ((tm = Getattr(p,"tmap:argout:chicken_words"))) {
|
|
Replaceall(tm,"$typename", mangle);
|
|
if (strcmp(Char(tm), "void") == 0) continue;
|
|
if (strcmp(Char(tm), "0") != 0) will_alloca = 1;
|
|
if (result_list_len) {
|
|
Printf(known_alloca_plus, " + ");
|
|
} else {
|
|
Printf(known_alloca, "%s /*%s*/", tm, Getattr(p,"lname"));
|
|
}
|
|
Printf(known_alloca_plus, "3+%s /*%s*/", tm, Getattr(p,"lname"));
|
|
result_list_len++;
|
|
p = Getattr(p,"tmap:argout:next");
|
|
} else {
|
|
p = nextSibling(p);
|
|
}
|
|
}
|
|
if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) {
|
|
if ((am = Getattr(n,"tmap:out:chicken_words"))) {
|
|
Replaceall(am,"$typename", mangle);
|
|
if (strcmp(Char(am), "void") == 0) {
|
|
has_void_return = 1;
|
|
}
|
|
else {
|
|
if (strcmp(Char(am), "0") != 0) will_alloca = 1;
|
|
if (result_list_len) {
|
|
Printf(known_alloca_plus, " + ");
|
|
} else {
|
|
Printf(known_alloca, "%s /*result*/", am);
|
|
}
|
|
Printf(known_alloca_plus, "3+%s /*result*/", am);
|
|
result_list_len++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Generate known_space code */
|
|
if (result_list_len > 1 || (will_alloca && result_list_len == 1)) {
|
|
if (result_list_len == 1) {
|
|
Wrapper_add_local(f,"known_space", "C_word *known_space");
|
|
Printf(f->code, " known_space = C_alloc (%s);\n",
|
|
known_alloca);
|
|
}
|
|
else {
|
|
Wrapper_add_local(f,"known_space", "C_word *known_space");
|
|
Printf(f->code, " /* allocate space for fixed-size scheme objects "
|
|
"used for output */\n");
|
|
Printf(f->code, " known_space = C_alloc (%s); "
|
|
"/* The '3' in 3+... is to alloc a C_pair "
|
|
"in the Scheme list 'resultobj' */ \n",
|
|
known_alloca_plus);
|
|
}
|
|
}
|
|
|
|
/* Generate code for argument marshalling */
|
|
for (i = 0, p=l; i < num_arguments; i++) {
|
|
|
|
while (checkAttribute(p,"tmap:in:numinputs","0")) {
|
|
p = Getattr(p,"tmap:in:next");
|
|
}
|
|
|
|
SwigType *pt = Getattr(p,"type");
|
|
String *pn = Getattr(p,"name");
|
|
String *ln = Getattr(p,"lname");
|
|
SwigType *pb = SwigType_base(pt);
|
|
|
|
sprintf(source,"scm%d",i+1);
|
|
|
|
Printf(f->def, ", C_word scm%d", i+1);
|
|
Printf(declfunc,",C_word");
|
|
|
|
closparam = NewString("");
|
|
Printf(closparam, "%%%d", i+1);
|
|
Printv(closargs, " ", closparam, NIL);
|
|
|
|
/* Look for an clos input conversion */
|
|
int gotwrap = 0;
|
|
Node *search;
|
|
String *tm = 0;
|
|
if ((search = Getattr(known_classes, pb)) ||
|
|
(tm = singleSearch("clos_in", Char(pn), pb))) {
|
|
/* search for typemap("clos_in") CLASS_OR_BASE_CLASS */
|
|
if (tm || (tm = recurseSearch("clos_in", Char(pn), search))) {
|
|
String *cn = NewString("");
|
|
Printv(cn, "<", prefix, pb, ">", NIL);
|
|
namify(cn);
|
|
|
|
Replaceall(tm, "$class", cn);
|
|
Replaceall(tm, "$input", closparam);
|
|
|
|
Printv(closwrapargs, " ", tm, NIL);
|
|
|
|
gotwrap = 1;
|
|
Delete(cn);
|
|
}
|
|
else {
|
|
Swig_warning(WARN_TYPEMAP_UNDEF, input_file, line_number,
|
|
"Unable to find \"%%typemap(clos_in) %s *\" "
|
|
"or typemaps for any superclasses.\n",
|
|
SwigType_str(pb,0));
|
|
}
|
|
}
|
|
if (!gotwrap) {
|
|
Printv(closwrapargs, " ", closparam, NIL);
|
|
}
|
|
Delete(closparam);
|
|
|
|
/* Look for an input typemap */
|
|
if ((tm = Getattr(p,"tmap:in"))) {
|
|
String *parse = Getattr(p,"tmap:in:parse");
|
|
if (!parse) {
|
|
Replaceall(tm,"$source",source);
|
|
Replaceall(tm,"$target",ln);
|
|
Replaceall(tm,"$input", source);
|
|
Setattr(p,"emit:input", source); /* Save the location of
|
|
the object */
|
|
|
|
if (Getattr(p,"wrap:disown") || (Getattr(p,"tmap:in:disown"))) {
|
|
Replaceall(tm,"$disown","SWIG_POINTER_DISOWN");
|
|
} else {
|
|
Replaceall(tm,"$disown","0");
|
|
}
|
|
|
|
if (i >= num_required)
|
|
Printv(get_pointers, "if (", source, ") {\n", NIL);
|
|
Printv(get_pointers,tm,"\n", NIL);
|
|
if (i >= num_required)
|
|
Printv(get_pointers, "}\n", NIL);
|
|
|
|
} else {
|
|
}
|
|
p = Getattr(p,"tmap:in:next");
|
|
continue;
|
|
} else {
|
|
Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number,
|
|
"Unable to use type %s as a function argument.\n",
|
|
SwigType_str(pt,0));
|
|
break;
|
|
}
|
|
p = nextSibling(p);
|
|
}
|
|
|
|
/* finish argument marshalling */
|
|
|
|
Printf(f->def, ") {");
|
|
Printf(declfunc, ")");
|
|
|
|
/* Now piece together the first part of the wrapper function */
|
|
Printv(f->code, get_pointers, NIL);
|
|
|
|
/* Insert constraint checking code */
|
|
for (p = l; p;) {
|
|
if ((tm = Getattr(p,"tmap:check"))) {
|
|
Replaceall(tm,"$target",Getattr(p,"lname"));
|
|
Printv(f->code,tm,"\n",NIL);
|
|
p = Getattr(p,"tmap:check:next");
|
|
} else {
|
|
p = nextSibling(p);
|
|
}
|
|
}
|
|
|
|
/* Insert cleanup code */
|
|
for (p = l; p;) {
|
|
if ((tm = Getattr(p,"tmap:freearg"))) {
|
|
Replaceall(tm,"$source",Getattr(p,"lname"));
|
|
Printv(cleanup,tm,"\n",NIL);
|
|
p = Getattr(p,"tmap:freearg:next");
|
|
} else {
|
|
p = nextSibling(p);
|
|
}
|
|
}
|
|
|
|
/* Want outputs done in reverse order */
|
|
List *l_out = NewList();
|
|
|
|
/* Return the function value */
|
|
if (has_void_return && result_list_len == 1) {
|
|
/* do absolutely nothing since result will be initted elsewhere
|
|
by one argout */
|
|
}
|
|
else if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) {
|
|
Replaceall(tm,"$source", "result");
|
|
Replaceall(tm,"$target", "resultobj");
|
|
Replaceall(tm,"$result", "resultobj");
|
|
if (Getattr(n,"feature:new")) {
|
|
Replaceall(tm,"$owner","1");
|
|
} else {
|
|
Replaceall(tm,"$owner","0");
|
|
}
|
|
selectOutOneOrMany(tm, result_list_len > 1);
|
|
Append(l_out, tm);
|
|
} else {
|
|
Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number,
|
|
"Unable to use return type %s in function %s.\n",
|
|
SwigType_str(d,0), name);
|
|
}
|
|
|
|
/* Insert argument output code */
|
|
for (p = l; p;) {
|
|
if ((tm = Getattr(p,"tmap:argout"))) {
|
|
Replaceall(tm,"$source",Getattr(p,"lname"));
|
|
Replaceall(tm,"$target","resultobj");
|
|
Replaceall(tm,"$arg",Getattr(p,"emit:input"));
|
|
Replaceall(tm,"$input",Getattr(p,"emit:input"));
|
|
selectOutOneOrMany(tm, result_list_len > 1);
|
|
Append(l_out, tm);
|
|
p = Getattr(p,"tmp:argout:next");
|
|
} else {
|
|
p = nextSibling(p);
|
|
}
|
|
}
|
|
|
|
/* Emit the function call */
|
|
emit_action(n,f);
|
|
|
|
/* Output argument output code */
|
|
int i_out;
|
|
if (result_list_len > 1) {
|
|
Printv(f->code, "resultobj = C_SCHEME_UNDEFINED;\n", NIL);
|
|
}
|
|
for (i_out = Len(l_out); i_out > 0; ) {
|
|
Printv(f->code, (String *) Getitem(l_out, --i_out), "\n", NIL);
|
|
}
|
|
|
|
/* Output cleanup code */
|
|
Printv(f->code,cleanup,NIL);
|
|
|
|
/* Look to see if there is any newfree cleanup code */
|
|
if (Getattr(n,"feature:new")) {
|
|
if ((tm = Swig_typemap_lookup_new("newfree",n,"result",0))) {
|
|
Replaceall(tm,"$source","result");
|
|
Printf(f->code,"%s\n",tm);
|
|
}
|
|
}
|
|
|
|
/* See if there is any return cleanup code */
|
|
if ((tm = Swig_typemap_lookup_new("ret", n, "result", 0))) {
|
|
Replaceall(tm,"$source","result");
|
|
Printf(f->code,"%s\n",tm);
|
|
}
|
|
|
|
Printf(f->code," C_kontinue (continuation, resultobj);\n");
|
|
|
|
/* Error handling code */
|
|
#ifdef USE_FAIL
|
|
Printf(f->code,"fail:\n");
|
|
Printv(f->code,cleanup,NIL);
|
|
Printf(f->code,"swig_panic (\"failure in "
|
|
"'$symname' SWIG function wrapper\");\n");
|
|
#endif
|
|
Printf(f->code,"}\n");
|
|
|
|
/* Substitute the cleanup code */
|
|
Replaceall(f->code,"$cleanup",cleanup);
|
|
|
|
/* Substitute the function name */
|
|
Replaceall(f->code,"$symname",iname);
|
|
Replaceall(f->code,"$result","resultobj");
|
|
|
|
/* Dump the function out */
|
|
Printv(f_wrappers,
|
|
#ifndef BINDING
|
|
"static ",
|
|
#endif
|
|
declfunc, " C_noret;\n", NIL);
|
|
Wrapper_print(f,f_wrappers);
|
|
|
|
Setattr(n,"wrap:name", wname);
|
|
|
|
/* Now register the function with the interpreter. */
|
|
if (!Getattr(n,"sym:overloaded")) {
|
|
addMethod(iname, scmname, wname);
|
|
|
|
/* Create a binding for this function */
|
|
#ifdef BINDING
|
|
Printv(f_scm, "(declare (foreign-declare \"C_extern ",
|
|
declfunc, " C_noret;\"))\n", NIL);
|
|
Printv(f_scm, "(define ", prefix, scmname,
|
|
" (##core#primitive \"", module, "_wrap_", iname,
|
|
"\"))\n\n", NIL);
|
|
#endif
|
|
}
|
|
else {
|
|
if (!Getattr(n,"sym:nextSibling")) {
|
|
dispatchFunction(n);
|
|
}
|
|
}
|
|
|
|
/* Look for typemap(clos_out) */
|
|
closparam = NewString("");
|
|
Printv(closparam, "(", prefix, scmname, closwrapargs, ")", NIL);
|
|
Node *search;
|
|
String *pb = SwigType_base(d);
|
|
tm = 0;
|
|
if ((search = Getattr(known_classes, pb)) ||
|
|
(tm = singleSearch("clos_out", Char(closparam), pb))) {
|
|
/* search for typemap("clos_out") CLASS_OR_BASE_CLASS */
|
|
if (tm || (tm = recurseSearch("clos_out", Char(closparam), search))) {
|
|
String *cn = NewString("");
|
|
Printv(cn, "<", prefix, pb, ">", NIL);
|
|
namify(cn);
|
|
|
|
Replaceall(tm, "$class", cn);
|
|
|
|
Delete(closparam);
|
|
Delete(cn);
|
|
|
|
closparam = Copy(tm);
|
|
}
|
|
else {
|
|
Swig_warning(WARN_TYPEMAP_UNDEF, input_file, line_number,
|
|
"Unable to find \"%%typemap(clos_out) %s *\" "
|
|
"or typemaps for any superclasses.\n",
|
|
SwigType_str(pb,0));
|
|
}
|
|
}
|
|
|
|
/* Dump clos code if enabled and not in a non-static member function */
|
|
if (!Getattr(n,"sym:overloaded")) {
|
|
if (clos &&
|
|
(!(clos & SCMCLOS_MEMBER) || (clos & SCMCLOS_STATIC_MEMBER))) {
|
|
Printv(f_clos, "(define (+", prefix, scmname, "+", closargs, ")\n",
|
|
tab4, closparam, ")\n", NIL);
|
|
}
|
|
}
|
|
Delete(closparam);
|
|
|
|
Delete(wname);
|
|
Delete(l_out);
|
|
Delete(known_alloca);
|
|
Delete(known_alloca_plus);
|
|
Delete(get_pointers);
|
|
Delete(cleanup);
|
|
Delete(outarg);
|
|
Delete(declfunc);
|
|
Delete(mangle);
|
|
Delete(closwrapargs);
|
|
Delete(closargs);
|
|
DelWrapper(f);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
int
|
|
CHICKEN::variableWrapper(Node *n) {
|
|
char *name = GetChar(n,"name");
|
|
char *iname = GetChar(n,"sym:name");
|
|
SwigType *t = Getattr(n,"type");
|
|
SwigType *pb = SwigType_base(t);
|
|
ParmList *l = Getattr(n,"parms");
|
|
|
|
String *proc_name = NewString("");
|
|
char var_name[256];
|
|
String *wname = NewString("");
|
|
String *mangle = NewString("");
|
|
String *tm;
|
|
String *am;
|
|
String *tm2 = NewString("");;
|
|
String *argnum = NewString("0");
|
|
String *arg = NewString("argv[0]");
|
|
String *known_alloca = NewString("");
|
|
Wrapper *f;
|
|
String *overname = 0;
|
|
String *scmname;
|
|
String *closparam;
|
|
String *closargs;
|
|
String *closwrapargs;
|
|
|
|
int num_required;
|
|
int num_arguments;
|
|
|
|
scmname = NewString(iname);
|
|
namify(scmname);
|
|
|
|
Printf(mangle, "\"%s\"", SwigType_manglestr(t));
|
|
|
|
if (Getattr(n,"sym:overloaded")) {
|
|
overname = Getattr(n,"sym:overname");
|
|
} else {
|
|
if (!addSymbol(iname,n)) return SWIG_ERROR;
|
|
}
|
|
|
|
f = NewWrapper();
|
|
|
|
/* Attach the standard typemaps */
|
|
emit_attach_parmmaps(l,f);
|
|
Setattr(n,"wrap:parms",l);
|
|
|
|
/* Get number of required and total arguments */
|
|
num_arguments = emit_num_arguments(l);
|
|
num_required = emit_num_required(l);
|
|
|
|
// evaluation function names
|
|
Append(wname, module);
|
|
Append(wname, Swig_name_wrapper(iname));
|
|
if (overname) {
|
|
Append(wname, overname);
|
|
}
|
|
|
|
strcpy(var_name, Char(Swig_name_wrapper(iname)));
|
|
|
|
// Build the name for scheme.
|
|
Printv(proc_name, iname,NIL);
|
|
namify(proc_name);
|
|
|
|
// Check for interrupts
|
|
Printv (f->code, "C_check_for_interrupt;\n",
|
|
"C_trace(\"",scmname,"\");\n", NIL);
|
|
|
|
closargs = NewString("");
|
|
closwrapargs = NewString("");
|
|
|
|
if (1 || (SwigType_type(t) != T_USER) || (isPointer(t))) {
|
|
|
|
closparam = NewString("(car %value)");
|
|
Printv(closargs, " . %value", NIL);
|
|
|
|
Printv(f->def,
|
|
#ifndef BINDING
|
|
"static ",
|
|
#endif
|
|
"void ",wname,"(int, C_word, C_word, C_word) C_noret;\n",
|
|
NIL);
|
|
Printv(f->def,
|
|
#ifndef BINDING
|
|
"static "
|
|
#endif
|
|
"void ",wname,"(int argc, C_word closure, "
|
|
"C_word continuation, C_word value) {\n",
|
|
NIL);
|
|
|
|
Wrapper_add_local(f, "resultobj", "C_word resultobj");
|
|
|
|
/* Check for a setting of the variable value */
|
|
if (!Getattr(n,"feature:immutable")) {
|
|
Printf(f->code, "if (argc > 2) {\n");
|
|
if ((tm = Swig_typemap_lookup_new("varin",n,name,0))) {
|
|
Replaceall(tm,"$source","value");
|
|
Replaceall(tm,"$target",name);
|
|
Replaceall(tm,"$input","value");
|
|
Printv(f->code, tm, "\n",NIL);
|
|
}
|
|
else {
|
|
Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number,
|
|
"Unable to set variable of type %s.\n",
|
|
SwigType_str(t,0));
|
|
}
|
|
Printf(f->code, "}\n");
|
|
}
|
|
|
|
/* Look for an clos input conversion */
|
|
int gotwrap = 0;
|
|
Node *search;
|
|
String *tm = 0;
|
|
if ((search = Getattr(known_classes, pb)) ||
|
|
(tm = singleSearch("clos_in", Char(name), pb))) {
|
|
/* search for typemap("clos_in") CLASS_OR_BASE_CLASS */
|
|
if (tm || (tm = recurseSearch("clos_in", Char(name), search))) {
|
|
String *cn = NewString("");
|
|
Printv(cn, "<", prefix, pb, ">", NIL);
|
|
namify(cn);
|
|
|
|
Replaceall(tm, "$class", cn);
|
|
Replaceall(tm, "$input", closparam);
|
|
|
|
Printv(closwrapargs, " ", tm, NIL);
|
|
|
|
gotwrap = 1;
|
|
Delete(cn);
|
|
}
|
|
else {
|
|
Swig_warning(WARN_TYPEMAP_UNDEF, input_file, line_number,
|
|
"Unable to find \"%%typemap(clos_in) %s *\" "
|
|
"or typemaps for any superclasses.\n",
|
|
SwigType_str(pb,0));
|
|
}
|
|
}
|
|
if (!gotwrap) {
|
|
Printv(closwrapargs, " ", closparam, NIL);
|
|
}
|
|
Delete(closparam);
|
|
|
|
// Now return the value of the variable - regardless
|
|
// of evaluating or setting.
|
|
if ((tm = Swig_typemap_lookup_new("varout",n,name,0))) {
|
|
/* Calculate fixed alloca code */
|
|
if ((am = Getattr(n,"tmap:varout:chicken_words"))) {
|
|
Replaceall(am,"$typename", mangle);
|
|
if (strcmp(Char(am), "0") != 0) {
|
|
Wrapper_add_local(f,"known_space", "C_word *known_space");
|
|
|
|
Printf(f->code,
|
|
" known_space = C_alloc (%s);\n",
|
|
am);
|
|
}
|
|
}
|
|
|
|
selectOutOneOrMany(tm, 0);
|
|
Replaceall(tm,"$source",name);
|
|
Replaceall(tm,"$varname",name);
|
|
Replaceall(tm,"$target","resultobj");
|
|
Replaceall(tm,"$result","resultobj");
|
|
Printf(f->code, "%s\n", tm);
|
|
}
|
|
else {
|
|
Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number,
|
|
"Can't find varout with type %s\n", SwigType_str(t,0));
|
|
}
|
|
Printf(f->code,"\nC_kontinue (continuation, resultobj);\n");
|
|
|
|
/* Error handling code */
|
|
#ifdef USE_FAIL
|
|
Printf(f->code,"fail:\n");
|
|
Printf(f->code,"swig_panic (\"failure in "
|
|
"'%s' SWIG wrapper\");\n", proc_name);
|
|
#endif
|
|
Printf(f->code,"}\n");
|
|
|
|
Wrapper_print(f, f_wrappers);
|
|
|
|
/* Now register the variable with the interpreter. */
|
|
addMethod(iname, scmname, wname);
|
|
|
|
/* Look for typemap(clos_out) */
|
|
closparam = NewString("");
|
|
Printv(closparam, "(if (= (length %value) 0)\n",
|
|
tab4, "(", prefix, scmname, ")\n",
|
|
tab4, "(", prefix, scmname, closwrapargs, "))", NIL);
|
|
tm = 0;
|
|
if ((search = Getattr(known_classes, pb)) ||
|
|
(tm = singleSearch("clos_out", Char(closparam), pb))) {
|
|
/* search for typemap("clos_out") CLASS_OR_BASE_CLASS */
|
|
if (tm || (tm = recurseSearch("clos_out",
|
|
Char(closparam), search))) {
|
|
String *cn = NewString("");
|
|
Printv(cn, "<", prefix, pb, ">", NIL);
|
|
namify(cn);
|
|
|
|
Replaceall(tm, "$class", cn);
|
|
|
|
Delete(closparam);
|
|
Delete(cn);
|
|
|
|
closparam = Copy(tm);
|
|
}
|
|
else {
|
|
Swig_warning(WARN_TYPEMAP_UNDEF, input_file, line_number,
|
|
"Unable to find \"%%typemap(clos_out) %s *\" "
|
|
"or typemaps for any superclasses.\n",
|
|
SwigType_str(pb,0));
|
|
}
|
|
}
|
|
|
|
/* Create a binding for this variable */
|
|
#ifdef BINDING
|
|
Printv(f_scm, "(declare (foreign-declare \"C_extern ",
|
|
wname, "(int,C_word,C_word,C_word)"
|
|
" C_noret;\"))\n", NIL);
|
|
Printv(f_scm, "(define ", prefix, scmname,
|
|
" (##core#primitive \"", module, "_wrap_", iname,
|
|
"\"))\n\n", NIL);
|
|
#endif
|
|
|
|
/* Create a clos for this variable (if enabled and not in a
|
|
non-static member variable) */
|
|
if (clos &&
|
|
(!(clos & SCMCLOS_MEMBER) || (clos & SCMCLOS_STATIC_MEMBER))) {
|
|
Printv(f_clos, "(define (+", prefix, scmname, "+", closargs, ")\n",
|
|
tab4, closparam, ")\n", NIL);
|
|
}
|
|
Delete(closparam);
|
|
} else {
|
|
Swig_warning(WARN_TYPEMAP_VAR_UNDEF, input_file, line_number,
|
|
"Unsupported variable type %s (ignored).\n",
|
|
SwigType_str(t,0));
|
|
}
|
|
|
|
Delete(wname);
|
|
Delete(known_alloca);
|
|
Delete(proc_name);
|
|
Delete(argnum);
|
|
Delete(arg);
|
|
Delete(tm2);
|
|
Delete(mangle);
|
|
Delete(closwrapargs);
|
|
Delete(closargs);
|
|
DelWrapper(f);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* ------------------------------------------------------------
|
|
* constantWrapper()
|
|
* ------------------------------------------------------------ */
|
|
|
|
int
|
|
CHICKEN::constantWrapper(Node *n)
|
|
{
|
|
|
|
char *name = GetChar(n,"name");
|
|
char *iname = GetChar(n,"sym:name");
|
|
SwigType *t = Getattr(n,"type");
|
|
ParmList *l = Getattr(n,"parms");
|
|
String *value = Getattr(n,"value");
|
|
|
|
String *proc_name = NewString("");
|
|
char var_name[256];
|
|
String *wname = NewString("");
|
|
String *mangle = NewString("");
|
|
String *tm;
|
|
String *am;
|
|
String *tm2 = NewString("");
|
|
String *source = NewString("");
|
|
String *argnum = NewString("0");
|
|
String *arg = NewString("argv[0]");
|
|
String *known_alloca = NewString("");
|
|
Wrapper *f;
|
|
String *overname = 0;
|
|
String *scmname;
|
|
|
|
int num_required;
|
|
int num_arguments;
|
|
|
|
scmname = NewString(iname);
|
|
namify(scmname);
|
|
|
|
Printf(mangle, "\"%s\"", SwigType_manglestr(t));
|
|
Printf(source, "swig_const_%s", name);
|
|
Replaceall(source, "::", "__");
|
|
|
|
if (Getattr(n,"sym:overloaded")) {
|
|
overname = Getattr(n,"sym:overname");
|
|
} else {
|
|
if (!addSymbol(iname,n)) return SWIG_ERROR;
|
|
}
|
|
|
|
Append(wname, module);
|
|
Append(wname, Swig_name_wrapper(iname));
|
|
if (overname) {
|
|
Append(wname, overname);
|
|
}
|
|
|
|
/* Special hook for member pointer */
|
|
if (SwigType_type(t) == T_MPOINTER) {
|
|
Printf(f_header, "static %s = %s;\n", SwigType_str(t,wname), value);
|
|
value = wname;
|
|
}
|
|
if ((tm = Swig_typemap_lookup_new("constcode", n, name, 0))) {
|
|
Replaceall(tm,"$source",value);
|
|
Replaceall(tm,"$target",source);
|
|
Replaceall(tm,"$result",source);
|
|
Replaceall(tm,"$value",value);
|
|
Printf(f_header, "%s\n", tm);
|
|
}
|
|
else {
|
|
Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number,
|
|
"Unsupported constant value.\n");
|
|
return SWIG_NOWRAP;
|
|
}
|
|
|
|
f = NewWrapper();
|
|
|
|
/* Attach the standard typemaps */
|
|
emit_attach_parmmaps(l,f);
|
|
Setattr(n,"wrap:parms",l);
|
|
|
|
/* Get number of required and total arguments */
|
|
num_arguments = emit_num_arguments(l);
|
|
num_required = emit_num_required(l);
|
|
|
|
// evaluation function names
|
|
|
|
strcpy(var_name, Char(Swig_name_wrapper(iname)));
|
|
|
|
// Build the name for scheme.
|
|
Printv(proc_name, iname,NIL);
|
|
namify(proc_name);
|
|
|
|
// Check for interrupts
|
|
Printv (f->code, "C_check_for_interrupt;\n",
|
|
"C_trace(\"",scmname,"\");\n", NIL);
|
|
|
|
if (1 || (SwigType_type(t) != T_USER) || (isPointer(t))) {
|
|
|
|
Printv(f->def,
|
|
#ifndef BINDING
|
|
"static ",
|
|
#endif
|
|
"void ",wname,"(int, C_word, C_word) C_noret;\n",
|
|
NIL);
|
|
|
|
Printv(f->def,
|
|
#ifndef BINDING
|
|
"static ",
|
|
#endif
|
|
"void ",wname,"(int argc, C_word closure, "
|
|
"C_word continuation) {\n",
|
|
NIL);
|
|
|
|
Wrapper_add_local(f, "resultobj", "C_word resultobj");
|
|
|
|
// Return the value of the variable
|
|
if ((tm = Swig_typemap_lookup_new("varout",n,name,0))) {
|
|
/* Calculate fixed alloca code */
|
|
if ((am = Getattr(n,"tmap:varout:chicken_words"))) {
|
|
Replaceall(am,"$typename", mangle);
|
|
if (strcmp(Char(am), "0") != 0) {
|
|
Wrapper_add_local(f,"known_space", "C_word *known_space");
|
|
|
|
Printf(f->code,
|
|
" known_space = C_alloc (%s);\n",
|
|
am);
|
|
}
|
|
}
|
|
|
|
selectOutOneOrMany(tm, 0);
|
|
Replaceall(tm,"$source",source);
|
|
Replaceall(tm,"$varname",source);
|
|
Replaceall(tm,"$target","resultobj");
|
|
Replaceall(tm,"$result","resultobj");
|
|
Printf(f->code, "%s\n", tm);
|
|
}
|
|
else {
|
|
Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number,
|
|
"Can't find varout with type %s\n", SwigType_str(t,0));
|
|
}
|
|
Printf(f->code,"\nC_kontinue (continuation, resultobj);\n");
|
|
|
|
/* Error handling code */
|
|
#ifdef USE_FAIL
|
|
Printf(f->code,"fail:\n");
|
|
Printf(f->code,"swig_panic (\"failure in "
|
|
"'%s' SWIG wrapper\");\n", proc_name);
|
|
#endif
|
|
Printf(f->code,"}\n");
|
|
|
|
Wrapper_print(f, f_wrappers);
|
|
|
|
/* Now register the variable with the interpreter. */
|
|
addMethod(iname, scmname, wname);
|
|
|
|
/* Create a binding for this variable */
|
|
#ifdef BINDING
|
|
Printv(f_scm, "(declare (foreign-declare \"C_extern ",
|
|
wname, "(int argc, C_word closure, C_word continuation, "
|
|
"C_word value)"
|
|
" C_noret;\"))\n", NIL);
|
|
Printv(f_scm, "(define ", prefix, scmname,
|
|
" (##core#primitive \"", module, "_wrap_", iname,
|
|
"\"))\n\n", NIL);
|
|
#endif
|
|
|
|
} else {
|
|
Swig_warning(WARN_TYPEMAP_VAR_UNDEF, input_file, line_number,
|
|
"Unsupported variable type %s (ignored).\n",
|
|
SwigType_str(t,0));
|
|
}
|
|
|
|
Delete(wname);
|
|
Delete(known_alloca);
|
|
Delete(proc_name);
|
|
Delete(argnum);
|
|
Delete(arg);
|
|
Delete(tm2);
|
|
Delete(mangle);
|
|
Delete(source);
|
|
DelWrapper(f);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
int
|
|
CHICKEN::classDeclaration(Node *n)
|
|
{
|
|
String *importname;
|
|
Node *mod;
|
|
if (clos) {
|
|
mod = Getattr(n,"module");
|
|
if (mod) {
|
|
String *iname = Getattr(n, "sym:name");
|
|
importname = NewString(prefix);
|
|
Printv(importname, iname, NIL);
|
|
Setattr(n,"chicken:proxy",importname);
|
|
Setattr(known_classes, iname, n);
|
|
}
|
|
}
|
|
return Language::classDeclaration(n);
|
|
}
|
|
|
|
int
|
|
CHICKEN::classHandler(Node *n)
|
|
{
|
|
int oldclassic = classic;
|
|
|
|
/* Create new strings for building up a wrapper function */
|
|
have_constructor = 0;
|
|
|
|
if (Getattr(n,"cplus:exceptionclass")) {
|
|
classic = 1;
|
|
}
|
|
|
|
clos_indent = (String *) tab4;
|
|
|
|
class_name = NewString("");
|
|
short_class_name = NewString("");
|
|
Printv(class_name, "<", prefix, Getattr(n,"sym:name"), ">", NIL);
|
|
namify(class_name);
|
|
Printv(short_class_name, Getattr(n,"sym:name"), NIL);
|
|
namify(short_class_name);
|
|
real_classname = Getattr(n,"name");
|
|
|
|
if (!addSymbol(class_name,n)) return SWIG_ERROR;
|
|
|
|
#ifdef JONAH_IS_CRAZY
|
|
Printv(f_scm,"(set! swig-",prefix,"tag:",Getattr(n,"sym:name"),"\n",
|
|
tab4,"(make-swig-",prefix,"tag ",
|
|
"1000 \"_p_",Getattr(n,"sym:name"),"\"\n",
|
|
tab8,"((foreign-lambda* c-pointer ()\n",
|
|
tab8, tab4, "\"return (",module,
|
|
"_swig_get_type (\\\"_p_",Getattr(n,"sym:name"),"\\\"));\"))\n",
|
|
tab8, "\"",Getattr(n,"sym:name")," *\"))\n", NIL);
|
|
#endif
|
|
|
|
if (clos) {
|
|
|
|
/* Handle inheritance */
|
|
String *base_class = NewString("<");
|
|
List *baselist = Getattr(n,"bases");
|
|
if (baselist && Len(baselist)) {
|
|
Node *base = Firstitem(baselist);
|
|
while (base) {
|
|
String *bname = Copy(Getattr(base, "chicken:proxy"));
|
|
if (!bname) {
|
|
base = Nextitem(baselist);
|
|
continue;
|
|
}
|
|
namify(bname);
|
|
Printv(base_class,bname,NIL);
|
|
Delete(bname);
|
|
base = Nextitem(baselist);
|
|
if (base) {
|
|
Printf(base_class, "> <");
|
|
}
|
|
}
|
|
}
|
|
Printf(base_class, ">");
|
|
|
|
Printv(f_clos,"\n(define-class ", class_name, " ", NIL);
|
|
|
|
if (Len(base_class) > 2) {
|
|
Printv(f_clos,"(", base_class, ") ())\n", NIL);
|
|
} else {
|
|
Printv(f_clos,"(<object>) (this))\n", NIL);
|
|
}
|
|
|
|
}
|
|
|
|
/* Emit all of the members */
|
|
|
|
in_class = 1;
|
|
Language::classHandler(n);
|
|
in_class = 0;
|
|
|
|
if (clos) {
|
|
char apply[] = "apply ";
|
|
|
|
if (have_constructor) {
|
|
Printv(f_clos, "(define-method (initialize (obj ", class_name,
|
|
") initargs)\n",
|
|
tab4, "(call-next-method)\n",
|
|
tab4, "(if (and (list? initargs) (= (length initargs) 2) (eq? (car initargs) (quote this)))\n",
|
|
tab8, "(slot-set! obj (quote this) (cadr initargs))\n",
|
|
tab8, "(begin\n",
|
|
tab8, tab4, "(slot-set! obj (quote this) (", apply, prefix, "new-", short_class_name, "\n",
|
|
tab8, tab8, " (map (lambda (arg) (if (instance? arg) (slot-ref arg (quote this)) arg)) initargs)))\n",
|
|
tab8, tab4, "(set-finalizer! obj\n",
|
|
tab8, tab8, "(lambda (deadobj) (", prefix, "delete-", short_class_name,
|
|
" (slot-ref deadobj (quote this))))))))\n",
|
|
NIL);
|
|
}
|
|
else {
|
|
Printv(f_clos, "(define-method (initialize (obj ", class_name,
|
|
") initargs)\n",
|
|
tab4, "(call-next-method)\n",
|
|
tab4, "(if (and (list? initargs) (= (length initargs) 2) (eq? (car initargs) (quote this)))\n",
|
|
tab8, "(slot-set! obj (quote this) (cadr initargs))\n",
|
|
tab8, "(slot-set! obj (quote this) #f)))\n",
|
|
NIL);
|
|
}
|
|
}
|
|
|
|
Delete(class_name);
|
|
Delete(short_class_name);
|
|
class_name = 0;
|
|
short_class_name = 0;
|
|
|
|
classic = oldclassic;
|
|
return SWIG_OK;
|
|
}
|
|
|
|
int
|
|
CHICKEN::memberfunctionHandler(Node *n)
|
|
{
|
|
String *iname = Getattr(n,"sym:name");
|
|
SwigType *d = Getattr(n,"type");
|
|
ParmList *l = Getattr(n,"parms");
|
|
int oldclos;
|
|
String *scmname;
|
|
String *args;
|
|
String *wrapargs;
|
|
String *closparam;
|
|
int i;
|
|
Parm *p;
|
|
String *tm;
|
|
|
|
scmname = NewString(iname);
|
|
namify(scmname);
|
|
|
|
/* input arguments */
|
|
args = NewString("");
|
|
wrapargs = NewString("");
|
|
for (i=0, p=l; p; i++) {
|
|
while (checkAttribute(p,"tmap:in:numinputs","0")) {
|
|
p = Getattr(p,"tmap:in:next");
|
|
}
|
|
|
|
SwigType *pt = Getattr(p,"type");
|
|
String *pn = Getattr(p,"name");
|
|
SwigType *pb = SwigType_base(pt);
|
|
|
|
if (strcmp("void", Char(pt)) != 0) {
|
|
String *arg = NewString("");
|
|
|
|
/* make name of argument */
|
|
if (pn && Len(pn)) {
|
|
Printf(arg, "%%%s", pn);
|
|
}
|
|
else {
|
|
Printf(arg, "%%%d", i+1);
|
|
}
|
|
|
|
Printv(args, " ", arg, NIL);
|
|
|
|
/* do input conversion */
|
|
int gotwrap = 0;
|
|
Node *search;
|
|
String *tm = 0;
|
|
if ((search = Getattr(known_classes, pb)) ||
|
|
(tm = singleSearch("clos_in", Char(pn), pb))) {
|
|
/* search for typemap("clos_in") CLASS_OR_BASE_CLASS */
|
|
if (tm || (tm = recurseSearch("clos_in", Char(pn), search))) {
|
|
String *cn = NewString("");
|
|
Printv(cn, "<", prefix, pb, ">", NIL);
|
|
namify(cn);
|
|
|
|
Replaceall(tm, "$class", cn);
|
|
Replaceall(tm, "$input", arg);
|
|
|
|
Printv(wrapargs, " ", tm, NIL);
|
|
|
|
gotwrap = 1;
|
|
Delete(cn);
|
|
}
|
|
else {
|
|
Swig_warning(WARN_TYPEMAP_UNDEF, input_file, line_number,
|
|
"Unable to find \"%%typemap(clos_in) %s *\" "
|
|
"or typemaps for any superclasses.\n",
|
|
SwigType_str(pb,0));
|
|
}
|
|
}
|
|
if (!gotwrap) {
|
|
Printv(wrapargs, " ", arg, NIL);
|
|
}
|
|
|
|
Delete(arg);
|
|
}
|
|
|
|
p = nextSibling(p);
|
|
}
|
|
|
|
/* Create the default member function */
|
|
oldclos = clos; /* Disable clos'ing when wrapping member
|
|
functions */
|
|
if (clos) clos = clos | SCMCLOS_MEMBER;
|
|
Language::memberfunctionHandler(n);
|
|
clos = oldclos;
|
|
|
|
/* return value */
|
|
closparam = NewString("");
|
|
if (Getattr(n,"sym:overloaded")) {
|
|
Printv(closparam, "(apply ", prefix, short_class_name, "-", scmname, "\n",
|
|
tab8, "(cons (slot-ref obj (quote this))\n",
|
|
tab8, tab4, "(map (lambda (arg) (if (instance? arg) (slot-ref arg (quote this)) arg)) args)))", NIL);
|
|
}
|
|
else {
|
|
Printv(closparam, "(", prefix, short_class_name, "-", scmname,
|
|
" (slot-ref obj (quote this))", wrapargs, ")", NIL);
|
|
}
|
|
Node *search;
|
|
String *pb = SwigType_base(d);
|
|
tm = 0;
|
|
if ((search = Getattr(known_classes, pb)) ||
|
|
(tm = singleSearch("clos_out", Char(closparam), pb))) {
|
|
/* search for typemap("clos_out") CLASS_OR_BASE_CLASS */
|
|
if (tm || (tm = recurseSearch("clos_out", Char(closparam), search))) {
|
|
String *cn = NewString("");
|
|
Printv(cn, "<", prefix, pb, ">", NIL);
|
|
namify(cn);
|
|
|
|
Replaceall(tm, "$class", cn);
|
|
|
|
Delete(closparam);
|
|
Delete(cn);
|
|
|
|
closparam = Copy(tm);
|
|
}
|
|
else {
|
|
Swig_warning(WARN_TYPEMAP_UNDEF, input_file, line_number,
|
|
"Unable to find \"%%typemap(clos_out) %s *\" "
|
|
"or typemaps for any superclasses.\n",
|
|
SwigType_str(pb,0));
|
|
}
|
|
}
|
|
|
|
/* print */
|
|
if (!Getattr(n,"sym:nextSibling")) {
|
|
if (clos) {
|
|
if (Getattr(n,"feature:clos")) {
|
|
String *scmcode = chickenCode(Getattr(n,"feature:clos"),tab4);
|
|
Printv(f_clos,scmcode,"\n",NIL);
|
|
}
|
|
else if (Getattr(n,"sym:overloaded")) {
|
|
Printv(f_clos, "(define-method (-", iname,
|
|
"- (obj ", class_name, ") . args)\n",
|
|
tab4, closparam, ")\n", NIL);
|
|
}
|
|
else {
|
|
Printv(f_clos, "(define-method (-", iname,
|
|
"- (obj ", class_name, ")", args, ")\n",
|
|
tab4, closparam, ")\n", NIL);
|
|
}
|
|
}
|
|
if (generic) {
|
|
Printv(f_generic, "(define -", iname,
|
|
"- (make-generic \"", iname, "\")) ;; class ",
|
|
class_name, "\n", NIL);
|
|
}
|
|
}
|
|
|
|
Delete(closparam);
|
|
Delete(wrapargs);
|
|
Delete(args);
|
|
Delete(scmname);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
int
|
|
CHICKEN::membervariableHandler(Node *n)
|
|
{
|
|
String *iname = Getattr(n,"sym:name");
|
|
|
|
int oldclos = clos;
|
|
if (clos) clos = clos | SCMCLOS_MEMBER;
|
|
Language::membervariableHandler(n);
|
|
clos = oldclos;
|
|
|
|
if (clos) {
|
|
int immutable = 0;
|
|
if (!Getattr(n,"feature:immutable")) {
|
|
Printv(f_clos, "(define-method (-set-", iname,
|
|
"!- (obj ", class_name, ") %value)\n",
|
|
tab4, "(", prefix, real_classname, "-", iname,
|
|
"-set (slot-ref obj (quote this)) %value))\n", NIL);
|
|
if (generic) {
|
|
Printv(f_generic, "(define -set-", iname,
|
|
"!- (make-generic \"set-", iname, "!\")) ;; class ",
|
|
class_name, "\n", NIL);
|
|
}
|
|
} else {
|
|
immutable = 1;
|
|
}
|
|
Printv(f_clos, "(define-method (-get-", iname,
|
|
"- (obj ", class_name, "))\n",
|
|
tab4, "(", prefix, real_classname, "-", iname,
|
|
"-get (slot-ref obj (quote this))))\n", NIL);
|
|
if (generic) {
|
|
Printv(f_generic, "(define -get-", iname,
|
|
"- (make-generic \"get-", iname, "\")) ;; class ",
|
|
class_name, "\n", NIL);
|
|
}
|
|
}
|
|
return SWIG_OK;
|
|
}
|
|
|
|
int
|
|
CHICKEN::memberconstantHandler(Node *n)
|
|
{
|
|
int oldclos = clos;
|
|
if (clos) clos = clos | SCMCLOS_MEMBER;
|
|
Language::memberconstantHandler(n);
|
|
clos = oldclos;
|
|
|
|
return SWIG_OK;
|
|
}
|
|
|
|
int
|
|
CHICKEN::staticmemberfunctionHandler(Node *n)
|
|
{
|
|
int oldclos = clos;
|
|
if (clos) clos = clos | SCMCLOS_STATIC_MEMBER;
|
|
Language::staticmemberfunctionHandler(n);
|
|
clos = oldclos;
|
|
|
|
return SWIG_OK;
|
|
}
|
|
|
|
int
|
|
CHICKEN::staticmembervariableHandler(Node *n)
|
|
{
|
|
int oldclos = clos;
|
|
if (clos) clos = clos | SCMCLOS_STATIC_MEMBER;
|
|
Language::staticmembervariableHandler(n);
|
|
clos = oldclos;
|
|
|
|
return SWIG_OK;
|
|
|
|
}
|
|
|
|
int
|
|
CHICKEN::destructorHandler(Node *n)
|
|
{
|
|
int oldclos = clos;
|
|
|
|
if (clos) clos = clos | SCMCLOS_MEMBER;
|
|
Language::destructorHandler(n);
|
|
clos = oldclos;
|
|
|
|
return SWIG_OK;
|
|
}
|
|
|
|
int
|
|
CHICKEN::constructorHandler(Node *n)
|
|
{
|
|
int oldclos = clos;
|
|
|
|
if (clos) clos = clos | SCMCLOS_MEMBER;
|
|
Language::constructorHandler(n);
|
|
clos = oldclos;
|
|
|
|
if (clos) {
|
|
have_constructor = 1;
|
|
}
|
|
|
|
return SWIG_OK;
|
|
}
|
|
|
|
void
|
|
CHICKEN::dispatchFunction(Node *n)
|
|
{
|
|
/* Last node in overloaded chain */
|
|
|
|
int maxargs;
|
|
String *tmp = NewString("");
|
|
String *dispatch =
|
|
Swig_overload_dispatch(n,"%s (2+argc,closure,"
|
|
"continuation$commaargs);", &maxargs);
|
|
|
|
/* Generate a dispatch wrapper for all overloaded functions */
|
|
|
|
Wrapper *f = NewWrapper();
|
|
String *iname = Getattr(n,"sym:name");
|
|
String *wname = NewString("");
|
|
String *scmname = NewString(iname);
|
|
|
|
namify(scmname);
|
|
Append(wname, module);
|
|
Append(wname, Swig_name_wrapper(iname));
|
|
|
|
#ifndef BINDING
|
|
Printv(f->def, "static void real_", wname,
|
|
"(int, C_word, C_word, C_word) C_noret;\n", NIL);
|
|
#endif
|
|
|
|
Printv(f->def,
|
|
#ifdef BINDING
|
|
"void ",
|
|
#else
|
|
"static void real_",
|
|
#endif
|
|
wname,
|
|
"(int, C_word closure, C_word continuation, C_word args) {",
|
|
NIL);
|
|
|
|
Wrapper_add_local(f,"argc","int argc");
|
|
Printf(tmp,"C_word argv[%d]", maxargs+1);
|
|
Wrapper_add_local(f,"argv",tmp);
|
|
Wrapper_add_local(f,"ii","int ii");
|
|
Wrapper_add_local(f,"t","C_word t = args");
|
|
Printf(f->code,"if (!C_swig_is_list (args)) {\n");
|
|
Printf(f->code," swig_barf (SWIG_BARF1_BAD_ARGUMENT_TYPE, "
|
|
"\"Argument #1 must be a list of overloaded arguments\");\n");
|
|
Printf(f->code,"}\n");
|
|
Printf(f->code,"argc = C_unfix (C_i_length (args));\n");
|
|
Printf(f->code,"for (ii = 0; (ii < argc) && (ii < %d); ii++, t = C_block_item (t, 1)) {\n",maxargs);
|
|
Printf(f->code,"argv[ii] = C_block_item (t, 0);\n");
|
|
Printf(f->code,"}\n");
|
|
|
|
Printv(f->code,dispatch,"\n",NIL);
|
|
Printf(f->code,"swig_barf (SWIG_BARF1_BAD_ARGUMENT_TYPE,"
|
|
"\"No matching function for overloaded '%s'\");\n", iname);
|
|
Printv(f->code,"}\n",NIL);
|
|
Wrapper_print(f,f_wrappers);
|
|
addMethod(iname,scmname, wname);
|
|
|
|
/* Create a binding for this function */
|
|
#ifdef BINDING
|
|
Printv(f_scm, "(declare (foreign-declare \"C_extern ",
|
|
module, wname, "(int, C_word, C_word, C_word) C_noret;\"))\n", NIL);
|
|
Printv(f_scm, "(define swig-", prefix, scmname,
|
|
"-prim (##core#primitive \"", module, "_wrap_", iname,
|
|
"\"))\n", NIL);
|
|
Printv(f_scm, "(define (", prefix, scmname,
|
|
" . args) (swig-", prefix, scmname, "-prim args))\n\n", NIL);
|
|
#else
|
|
|
|
DelWrapper(f);
|
|
f = NewWrapper();
|
|
|
|
/* varargs */
|
|
Printv(f->def, "void ", wname,
|
|
"(int, C_word, C_word, ...) C_noret;\n", NIL);
|
|
Printv(f->def, "void ", wname,
|
|
"(int c, C_word t0, C_word t1, ...) {",
|
|
NIL);
|
|
Printv(f->code,
|
|
"C_word t2;\n",
|
|
"va_list v;\n",
|
|
"C_word *a, c2 = c;\n",
|
|
"C_save_rest (t1, c2, 2);\n",
|
|
"C_check_for_interrupt;\n",
|
|
"if (!C_demand (c*C_SIZEOF_PAIR+0)) {\n",
|
|
"C_save_and_reclaim((void*)swig_tr2r, (void*)real_", wname, ", 2, t0, t1);\n",
|
|
"}\n",
|
|
"else {\n",
|
|
"a = C_alloc((c-2)*3);\n",
|
|
"t2 = C_restore_rest (a, C_rest_count (0));\n",
|
|
"real_", wname, " (3, t0, t1, t2);\n",
|
|
"}\n", NIL);
|
|
Printv(f->code,"}\n",NIL);
|
|
Wrapper_print(f,f_wrappers);
|
|
#endif
|
|
|
|
/* Create a clos for this function (if enabled and not in a
|
|
non-static member function) */
|
|
if (clos &&
|
|
(!(clos & SCMCLOS_MEMBER) || (clos & SCMCLOS_STATIC_MEMBER))) {
|
|
Printv(f_clos, "(define (+", prefix, scmname, "+ . args)\n",
|
|
tab4, "(apply ", prefix, scmname, " args))\n", NIL);
|
|
}
|
|
DelWrapper(f);
|
|
Delete(dispatch);
|
|
Delete(tmp);
|
|
Delete(wname);
|
|
}
|
|
|
|
void
|
|
CHICKEN::throwUnhandledChickenTypeError(SwigType *d)
|
|
{
|
|
Swig_warning(WARN_TYPEMAP_UNDEF, input_file, line_number,
|
|
"Unable to handle type %s.\n", SwigType_str(d,0));
|
|
}
|
|
|
|
int
|
|
CHICKEN::isPointer(SwigType *t)
|
|
{
|
|
return SwigType_ispointer(SwigType_typedef_resolve_all(t));
|
|
}
|
|
|
|
void
|
|
CHICKEN::addMethod(String *, String *scheme_name, String *function)
|
|
{
|
|
#ifndef BINDING
|
|
/* unless Chicken is run in case-sensitive mode, all symbols need
|
|
to be lowercase. Also, the symbols need the prefix. */
|
|
String *sym = NewString(prefix);
|
|
Append(sym, scheme_name);
|
|
char *s = Char(sym);
|
|
const int L = Len(sym);
|
|
for (int i=0; i < L; i++, s++) {
|
|
*s = tolower(*s);
|
|
}
|
|
|
|
/* add symbol to Chicken internal symbol table */
|
|
Printf(f_sym_size, "+C_SIZEOF_INTERNED_SYMBOL(%d)", Len(sym));
|
|
Printf(f_init_helper, "sym = C_intern (&a, %d, \"%s\");\n",
|
|
Len(sym), sym);
|
|
Printv(f_init_helper,
|
|
"C_mutate ((C_word*)sym+1, (*a=C_CLOSURE_TYPE|1, a[1]=(C_word)",
|
|
function, ", tmp=(C_word)a, a+=2, tmp));\n", NIL);
|
|
num_methods++;
|
|
Delete(sym);
|
|
#endif
|
|
}
|
|
|
|
int
|
|
CHICKEN::validIdentifier(String *s)
|
|
{
|
|
char *c = Char(s);
|
|
/* Check whether we have an R5RS identifier.*/
|
|
/* <identifier> --> <initial> <subsequent>* | <peculiar identifier> */
|
|
/* <initial> --> <letter> | <special initial> */
|
|
if (!(isalpha(*c) || (*c == '!') || (*c == '$') || (*c == '%')
|
|
|| (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':')
|
|
|| (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?')
|
|
|| (*c == '^') || (*c == '_') || (*c == '~'))) {
|
|
/* <peculiar identifier> --> + | - | ... */
|
|
if ((strcmp(c, "+") == 0)
|
|
|| strcmp(c, "-") == 0
|
|
|| strcmp(c, "...") == 0) return 1;
|
|
else return 0;
|
|
}
|
|
/* <subsequent> --> <initial> | <digit> | <special subsequent> */
|
|
while (*c) {
|
|
if (!(isalnum(*c) || (*c == '!') || (*c == '$') || (*c == '%')
|
|
|| (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':')
|
|
|| (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?')
|
|
|| (*c == '^') || (*c == '_') || (*c == '~') || (*c == '+')
|
|
|| (*c == '-') || (*c == '.') || (*c == '@'))) return 0;
|
|
c++;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
String *
|
|
CHICKEN::chickenCode(String *code, const String *indent) {
|
|
String *out = NewString("");
|
|
String *temp;
|
|
if (!indent) indent = "";
|
|
|
|
temp = NewString(code);
|
|
|
|
/* Split the input text into lines */
|
|
List *clist = DohSplit(temp,'\n',-1);
|
|
Delete(temp);
|
|
int initial = 0;
|
|
String *s;
|
|
|
|
/* Get the initial indentation */
|
|
for (s = Firstitem(clist); s; s = Nextitem(clist)) {
|
|
if (Len(s)) {
|
|
char *c = Char(s);
|
|
while (*c) {
|
|
if (!isspace(*c)) break;
|
|
initial++;
|
|
c++;
|
|
}
|
|
if (*c && !isspace(*c)) break;
|
|
else {
|
|
initial = 0;
|
|
}
|
|
}
|
|
}
|
|
while (s) {
|
|
if (Len(s) > initial) {
|
|
char *c = Char(s);
|
|
c += initial;
|
|
Printv(out,indent,c,"\n",NIL);
|
|
} else {
|
|
Printv(out,"\n",NIL);
|
|
}
|
|
s = Nextitem(clist);
|
|
}
|
|
Delete(clist);
|
|
return out;
|
|
}
|
|
|
|
String *
|
|
CHICKEN::singleSearch(const char *typemap, char *argname,
|
|
SwigType *searchClass)
|
|
{
|
|
String *tm;
|
|
char *source = "$input";
|
|
char *target = "$1";
|
|
/* search for search-class typemap */
|
|
SwigType *type = Copy(searchClass);
|
|
SwigType_add_pointer(type);
|
|
tm = Swig_typemap_lookup(typemap, type, argname, argname,
|
|
source, target, 0);
|
|
Delete(type);
|
|
|
|
return tm;
|
|
}
|
|
|
|
String *
|
|
CHICKEN::recurseSearch(const char *typemap, char *argname, Node *n)
|
|
{
|
|
String *tm;
|
|
tm = singleSearch(typemap, argname, Getattr(n, "name"));
|
|
if (tm) {
|
|
return tm;
|
|
}
|
|
|
|
/* recurse through base classes */
|
|
List *baselist = Getattr(n,"bases");
|
|
if (baselist && Len(baselist)) {
|
|
Node *base = Firstitem(baselist);
|
|
while (base) {
|
|
tm = recurseSearch(typemap, argname, base);
|
|
if (tm) break;
|
|
base = Nextitem(baselist);
|
|
}
|
|
}
|
|
return tm;
|
|
}
|
|
|
|
void
|
|
CHICKEN::namify(String *scmname)
|
|
{
|
|
Replaceall(scmname,"_to_", "->");
|
|
Replaceall(scmname,"_", "-");
|
|
|
|
/* Convert mixed-case to lower case with dashes */
|
|
if (mixed) {
|
|
int changedcase;
|
|
int i;
|
|
|
|
/* insert "-" in all places with switches in case, and lowercase
|
|
any upcase chars */
|
|
do {
|
|
char *s = Char(scmname);
|
|
const int l = Len(scmname);
|
|
int case_is_set = 0;
|
|
int was_uppercase = 0;
|
|
int pseudo_first = 0;
|
|
|
|
changedcase = 0;
|
|
for (i=0; i < l; ++i, ++s) {
|
|
int is_uppercase = -1; /* -1 = neither, 0 = lower, 1 = upper */
|
|
if (isalpha(*s) && !isdigit(*s)) {
|
|
is_uppercase = ((*s) >= 'A' && (*s) <= 'Z') ? 1 : 0;
|
|
}
|
|
if (i == 0 || !isalpha(*s) || isdigit(*s)) {
|
|
case_is_set = 0;
|
|
pseudo_first = 1;
|
|
}
|
|
if (case_is_set) {
|
|
if (is_uppercase >= 0 && was_uppercase != is_uppercase) {
|
|
*s = tolower(*s);
|
|
Insert(scmname, i, "-");
|
|
changedcase = 1;
|
|
break;
|
|
}
|
|
}
|
|
else if (is_uppercase >= 0) {
|
|
/* use currentcase, or lowercase if first char */
|
|
if (pseudo_first) {
|
|
pseudo_first = 0;
|
|
/* only if first two chars are upper case will we say that
|
|
the first char is upper case (like JavaBean property
|
|
naming rules) */
|
|
was_uppercase = 0;
|
|
const char *t = s + 1;
|
|
if (l >= i+2 && isalpha(*t) && !isdigit(*t) &&
|
|
((*t) >= 'A' && (*t) <= 'Z')) {
|
|
was_uppercase = 1;
|
|
}
|
|
}
|
|
else {
|
|
was_uppercase = is_uppercase;
|
|
}
|
|
case_is_set = 1;
|
|
}
|
|
if (is_uppercase == 1) {
|
|
*s = tolower(*s);
|
|
}
|
|
}
|
|
}
|
|
while (changedcase);
|
|
}
|
|
}
|
|
|
|
void
|
|
CHICKEN::selectOutOneOrMany(String *tm, int is_many)
|
|
{
|
|
char *s = Char(tm);
|
|
const char IFMANY[] = "/*if MANY*/";
|
|
const char IFONE[] = "/*if ONE*/";
|
|
const char ELSE[] = "/*else*/";
|
|
const char ENDIF[] = "/*endif*/";
|
|
enum { NONE, ONE, MANY } mode = NONE;
|
|
|
|
while (s) {
|
|
int displayline = 1;
|
|
|
|
/* set nextline */
|
|
char * nextline = strstr(s, "\n");
|
|
if (nextline) nextline += strlen("\n");
|
|
|
|
/* set displayline if necessary */
|
|
if (is_many && mode == ONE) displayline = 0;
|
|
if (!is_many && mode == MANY) displayline = 0;
|
|
|
|
/* which control line are we on? */
|
|
if (strncmp(s, IFMANY, sizeof(IFMANY) - 1) == 0) {
|
|
mode = MANY;
|
|
displayline = 0;
|
|
}
|
|
else if (strncmp(s, IFONE, sizeof(IFONE) - 1) == 0) {
|
|
mode = ONE;
|
|
displayline = 0;
|
|
}
|
|
else if (strncmp(s, ELSE, sizeof(ELSE) - 1) == 0) {
|
|
if (mode == ONE) mode = MANY;
|
|
else if (mode == MANY) mode = ONE;
|
|
displayline = 0;
|
|
}
|
|
else if (strncmp (s, ENDIF, sizeof(ENDIF) - 1) == 0) {
|
|
mode = NONE;
|
|
displayline = 0;
|
|
}
|
|
|
|
/* display line */
|
|
if (displayline) {
|
|
/* advance to next line */
|
|
s = nextline;
|
|
}
|
|
/* or don't display line */
|
|
else {
|
|
if (!nextline) {
|
|
memset(s, ' ', strlen(s)); /* truncate this (last) line */
|
|
s = 0;
|
|
}
|
|
else {
|
|
memset(s, ' ', nextline - s); /* remove this line */
|
|
s = nextline;
|
|
}
|
|
}
|
|
};
|
|
};
|