swig/Source/Modules/test.c

645 lines
15 KiB
C

/* -----------------------------------------------------------------------------
* test.c
*
* This module implements a SWIG module in the new tag-based parser.
* This is work in progress.
* ----------------------------------------------------------------------------- */
#include "swig.h"
#include "preprocessor.h"
#include "lparse.h"
/* -------- Module variables ------- */
#define CPLUS_PUBLIC 1
#define CPLUS_PRIVATE 2
#define CPLUS_PROTECTED 3
static DOHFile *runtime = 0;
static DOHFile *headers = 0;
static DOHFile *wrappers = 0;
static DOHFile *init = 0;
static DOH *config_top = 0;
static int ExternMode = 0;
static int ImportMode = 0;
static int ReadOnly = 0;
static int CPlusMode = CPLUS_PUBLIC;
static int NewMode = 0;
static DOHString *ModuleName = 0;
static int NativeMode = 0;
static DOHString *NewName = 0;
static DOHHash *RenameHash = 0;
static DOHHash *Rules = 0;
/* Object oriented flags */
static int InClass = 0;
static DOHString *ClassType = 0;
static DOHString *ClassName = 0;
static DOHString *ClassRename = 0;
static int AddMethods = 0;
/* -------- File inclusion directions -------- */
static int
emit_includefile(DOH *obj, void *clientdata) {
DOH *c;
c = Getattr(obj,"child");
if (c) {
Swig_emit(c,clientdata);
}
}
static int
emit_externfile(DOH *obj, void *clientdata) {
DOH *c;
int oldem = ExternMode;
ExternMode = 1;
c = Getattr(obj,"child");
if (c) {
Swig_emit(c,clientdata);
}
ExternMode = oldem;
}
static int
emit_importfile(DOH *obj, void *clientdata) {
DOH *c;
int oldem = ExternMode;
ExternMode = 1;
ImportMode = 1;
c = Getattr(obj,"child");
if (c) {
Swig_emit(c,clientdata);
}
ExternMode = oldem;
ImportMode = 0;
}
static int
emit_scope(DOH *obj, void *clientdata) {
DOH *c;
c = Getattr(obj,"child");
if (c) {
Swig_emit(c,clientdata);
}
return 0;
}
/* -------- Code blocks -------- */
/* %{ ... %} directive */
static int
emit_headerblock(DOH *obj, void *clientdata) {
Dump(Getattr(obj,"code"),headers);
return 0;
}
/* %wrapper %{ ... %} directive */
static int
emit_wrapperblock(DOH *obj, void *clientdata) {
Dump(Getattr(obj,"code"),wrappers);
return 0;
}
/* %init %{ ... %} directive */
static int
emit_initblock(DOH *obj, void *clientdata) {
Dump(Getattr(obj,"code"),init);
return 0;
}
/* %runtime %{ ... %} directive */
static int
emit_runtimeblock(DOH *obj, void *clientdata) {
Dump(Getattr(obj,"code"),runtime);
return 0;
}
/* ------ Basic C declarations ----- */
/* -----------------------------------------------------------------------------
* function
* ----------------------------------------------------------------------------- */
static int
emit_function(DOH *obj, void *clientdata) {
DOHString *name, *scriptname, *type, *storage;
DOHList *parms;
DOHHash *p;
Wrapper *wf;
int numarg = 0, numopt = 0;
int i, pn;
if (ExternMode) return 0;
name = Getattr(obj,"name"); /* Name of the function */
type = Getattr(obj,"type"); /* Return type */
parms = Getattr(obj,"parms"); /* Parameters */
storage = Getattr(obj,"storage"); /* Storage class */
/* See if the function is being renamed */
if (NewName) scriptname = NewName;
else scriptname = name;
/* Is this a member function? */
if (InClass) {
/* Handle member functions */
/* goto function_exit; */
}
wf = NewWrapper();
Printv(wf->def,
"static PyObject *", Swig_name_wrapper(scriptname), "(PyObject *self, PyObject *args) {\n",
0);
/* Loop over all of the function arguments and build pieces of the wrapper function */
{
DOHString *parsestr; /* Format string for parsing arguments */
DOHString *argstr; /* List of arguments */
DOHString *inputstr;
DOHString *checkstr;
DOHString *initstr;
DOHString *targetstr;
parsestr = NewString("");
argstr = NewString("");
inputstr = NewString("");
checkstr = NewString("");
initstr = NewString("");
targetstr = NewString("");
p = parms;
pn = 0;
while (p) {
int nmatch = 0;
DOHHash *map;
DOHHash *rules;
char suffix[32];
sprintf(suffix,"_%d", pn);
map = Swig_map_match(Rules, "argument", p, &nmatch);
if (!map) {
Printf(stderr,"%s:%d. No argument rule for %S\n", Getfile(p),Getline(p),SwigType_cstr(Getattr(p,"type"),Getattr(p,"name")));
return;
}
/* Pull out the rules */
rules = Getattr(map,"rules");
if (rules) {
DOH *linit;
DOH *lparse;
DOH *linput;
DOH *lcheck;
DOH *largstr;
DOH *ltarget;
linit = Copy(Getattr(rules,"init"));
lparse = Copy(Getattr(rules,"parse"));
linput = Copy(Getattr(rules,"input"));
lcheck = Copy(Getattr(rules,"check"));
ltarget = Copy(Getattr(rules,"target"));
largstr = 0;
/* Construct the parse and argument strings */
if (lparse) {
DOHList *sp;
DOHString *pstr;
int i;
Seek(lparse,0,SEEK_SET);
sp = DohSplit(lparse,",",-1);
pstr = Getitem(sp,0);
if (pstr) {
char *c = Char(pstr);
while (*c && (*c != '\"')) c++;
c++;
while (*c && (*c != '\"')) {
Putc(*c, parsestr);
c++;
}
}
largstr = NewString("");
for (i = 1; i < Len(sp); i++) {
Printf(largstr,",%s",Getitem(sp,i));
}
Delete(sp);
}
/* Variable substitution. We're going to walk down the map's children and perform variable name
replacements */
{
DOH *c = Getattr(map,"child");
while (c) {
if (Cmp(Getattr(c,"tag"),"variable") == 0) {
DOH *vname;
DOH *rname;
DOH *vtype;
DOH *vvalue;
DOH *storage;
DOH *local;
storage = Getattr(c,"storage");
vname = Getattr(c,"name");
vtype = Getattr(c,"type");
vvalue = Getattr(c,"value");
rname = NewStringf("%s_%d",vname,pn);
if (largstr) Replace(largstr,vname,rname,DOH_REPLACE_ID | DOH_REPLACE_NOQUOTE);
if (linit) Replace(linit,vname,rname,DOH_REPLACE_ID | DOH_REPLACE_NOQUOTE);
if (linput) Replace(linput,vname,rname,DOH_REPLACE_ID | DOH_REPLACE_NOQUOTE);
if (lcheck) Replace(lcheck,vname,rname,DOH_REPLACE_ID | DOH_REPLACE_NOQUOTE);
if (ltarget) Replace(ltarget,vname,rname, DOH_REPLACE_ID | DOH_REPLACE_NOQUOTE);
/* Declare as local to wrapper function */
local = NewString("");
Printf(local,"%S", SwigType_cstr(vtype,rname));
if (vvalue) {
Printf(local," = %s", vvalue);
}
Wrapper_add_local(wf,rname,local);
Delete(local);
Delete(rname);
}
c = Swig_next(c);
}
}
if (largstr) Append(argstr, largstr);
if (linput) Append(inputstr,linput);
if (lcheck) Append(checkstr,lcheck);
if (linit) Append(initstr,linit);
if (ltarget) Printf(targetstr,"%s,", ltarget);
Delete(largstr);
Delete(linput);
Delete(lcheck);
Delete(linit);
Delete(ltarget);
}
while (nmatch > 0) {
p = Swig_next(p);
nmatch--;
pn++;
}
}
/* Dump out the wrapper code */
if (pn > 0)
Delitem(targetstr,DOH_END);
Printv(wf->code,
initstr,
"if (PyParse_Args(\"", parsestr, "\"", argstr, ") == NULL) return NULL;\n",
inputstr,
checkstr,
"result = ", name, "(", targetstr, ");\n",
0);
}
Printf(wf->code,"}\n");
Wrapper_print(wf,wrappers);
function_exit:
Delete(NewName);
NewName = 0;
return 0;
}
/* -----------------------------------------------------------------------------
* variable
* ----------------------------------------------------------------------------- */
static int
emit_variable(DOH *obj, void *clientdata) {
Printf(stdout,"variable\n");
return 0;
}
/* -----------------------------------------------------------------------------
* constant
* ----------------------------------------------------------------------------- */
static int
emit_constant(DOH *obj, void *clientdata) {
Printf(stdout,"constant\n");
return 0;
}
static int
emit_typedef(DOH *obj, void *clientdata) {
Printf(stdout,"typedef\n");
return 0;
}
static int
emit_enum(DOH *obj, void *clientdata) {
DOH *c;
Printf(stdout,"enum\n");
c = Getattr(obj,"child");
if (c) {
Swig_emit(c,clientdata);
}
return 0;
}
static int
emit_enumvalue(DOH *obj, void *clientdata) {
Printf(stdout,"enumvalue\n");
return 0;
}
/* ------ C++ stuff ------ */
static int
emit_class(DOH *obj, void *clientdata) {
DOH *c;
Printf(stdout,"class\n");
c = Getattr(obj, "child");
if (c) {
int ic = InClass;
InClass = 1;
Swig_emit(c,clientdata);
InClass = ic;
}
return 0;
}
static int
emit_destructor(DOH *obj, void *clientdata) {
Printf(stdout,"destructor\n");
return 0;
}
static int
emit_classdecl(DOH *obj, void *clientdata) {
Printf(stdout,"classdecl\n");
return 0;
}
static int
emit_private(DOH *obj, void *clientdata) {
CPlusMode = CPLUS_PRIVATE;
return 0;
}
static int
emit_protected(DOH *obj, void *clientdata) {
CPlusMode = CPLUS_PROTECTED;
return 0;
}
static int
emit_public(DOH *obj, void *clientdata) {
CPlusMode = CPLUS_PUBLIC;
return 0;
}
static int
emit_addmethods(DOH *obj, void *clientdata) {
DOH *c;
Printf(stdout,"addmethods\n");
c = Getattr(obj, "child");
if (c) {
Swig_emit(c,clientdata);
}
return 0;
}
/* ------ SWIG directives ------ */
static int
emit_moduledirective(DOH *obj, void *clientdata) {
if (!ModuleName) {
ModuleName = Getattr(obj,"name");
DohIncref(ModuleName);
}
return 0;
}
static int
emit_renamedirective(DOH *obj, void *clientdata) {
DOHString *name, *rename;
name = Getattr(obj,"oldname");
rename = Getattr(obj,"newname");
if (name && rename)
Setattr(RenameHash,name,rename);
return 0;
}
static int
emit_readonlydirective(DOH *obj, void *clientdata) {
ReadOnly = 1;
return 0;
}
static int
emit_readwritedirective(DOH *obj, void *clientdata) {
ReadOnly = 0;
return 0;
}
static int
emit_namedirective(DOH *obj, void *clientdata) {
if (NewName) Delete(NewName);
NewName = Getattr(obj,"name");
if (NewName) DohIncref(NewName);
return 0;
}
static int
emit_newdirective(DOH *obj, void *clientdata) {
NewMode = 1;
return 0;
}
static int
emit_exceptiondirective(DOH *obj, void *clientdata) {
Printf(stdout,"exceptiondirective\n");
return 0;
}
static int
emit_pragmadirective(DOH *obj, void *clientdata) {
Printf(stdout,"pragmadirective\n");
return 0;
}
static int
emit_nativedirective(DOH *obj, void *clientdata) {
DOH *c;
int oldnative = NativeMode;
NativeMode = 1;
c = Getattr(obj, "child");
if (c) {
Swig_emit(c,clientdata);
}
NativeMode = oldnative;
return 0;
}
static int
emit_typemap(DOH *obj, void *clientdata) {
Printf(stdout,"typemap\n");
return 0;
}
static int
emit_typemapcopy(DOH *obj, void *clientdata) {
Printf(stdout,"typemapcopy\n");
return 0;
}
static int
emit_applydirective(DOH *obj, void *clientdata) {
Printf(stdout,"applydirective\n");
return 0;
}
static int
emit_cleardirective(DOH *obj, void *clientdata) {
Printf(stdout,"cleardirective\n");
return 0;
}
static int
emit_map(DOH *obj, void *clientdata) {
DOH *parms;
DOH *rulename;
DOH *rules;
rulename = Getattr(obj,"name");
parms = Getattr(obj,"parms");
rules = Getattr(obj,"child");
Swig_map_add(Rules,rulename,parms,obj);
}
/* -------- Entry point -------- */
static char *runtime_banner = "\n\
/* ----------------------------------------------------------------------------- \n\
Runtime\n\
----------------------------------------------------------------------------- */\n";
static char *header_banner = "\n\
/* ----------------------------------------------------------------------------- \n\
Headers\n\
----------------------------------------------------------------------------- */\n";
static char *wrapper_banner = "\n\
/* ----------------------------------------------------------------------------- \n\
Wrappers\n\
----------------------------------------------------------------------------- */\n";
static char *init_banner = "\n\
/* ----------------------------------------------------------------------------- \n\
Initialization\n\
----------------------------------------------------------------------------- */\n";
void test_emit(DOH *top, void *clientdata) {
/* Initialization */
runtime = NewString(runtime_banner);
headers = NewString(header_banner);
wrappers = NewString(wrapper_banner);
init = NewString(init_banner);
Rules = NewHash();
RenameHash = NewHash();
if (config_top)
Swig_emit(config_top, clientdata);
Swig_emit(top, clientdata);
Swig_banner(stdout);
Dump(runtime,stdout);
Dump(headers,stdout);
Dump(wrappers,stdout);
Dump(init, stdout);
Delete(runtime);
Delete(headers);
Delete(wrappers);
Delete(init);
Delete(RenameHash);
}
static SwigRule rules[] = {
"includefile", emit_includefile,
"externfile", emit_externfile,
"importfile", emit_importfile,
"headerblock", emit_headerblock,
"wrapperblock", emit_wrapperblock,
"initblock", emit_initblock,
"runtimeblock", emit_runtimeblock,
"scope", emit_scope,
"function", emit_function,
"variable", emit_variable,
"constant", emit_constant,
"typedef", emit_typedef,
"class", emit_class,
"destructor", emit_destructor,
"enum", emit_enum,
"enumvalue", emit_enumvalue,
"classdecl", emit_classdecl,
"private", emit_private,
"protected", emit_protected,
"public", emit_public,
"addmethods", emit_addmethods,
"moduledirective", emit_moduledirective,
"renamedirective", emit_renamedirective,
"readonlydirective", emit_readonlydirective,
"readwritedirective", emit_readwritedirective,
"namedirective", emit_namedirective,
"newdirective", emit_newdirective,
"exceptiondirective", emit_exceptiondirective,
"pragmadirective", emit_pragmadirective,
"nativedirective", emit_nativedirective,
"typemap", emit_typemap,
"typemapcopy", emit_typemapcopy,
"applydirective", emit_applydirective,
"cleardirective", emit_cleardirective,
"map", emit_map,
NULL, NULL
};
/* Initialize the module */
void test_init() {
DOHString *config;
DOHString *pconfig;
Swig_add_rules(rules);
/* Try to get the language specific configuration */
config = Swig_include("pyconf.swg");
if (!config) {
Printf(stderr,"*** Fatal error. Unable to find pyconf.swg\n");
exit(0);
}
/* Run the preprocessor on the configuration file and parse it */
Seek(config,0,SEEK_SET);
Setline(config,1);
pconfig = Preprocessor_parse(config);
Seek(pconfig,0,SEEK_SET);
config_top = LParse_parse(pconfig);
}