A lot of work on the type system. Experimental language module.

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@516 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Dave Beazley 2000-07-05 04:04:17 +00:00
commit 765ad025b9
8 changed files with 609 additions and 96 deletions

View file

@ -427,7 +427,8 @@ yylex1(void) {
if (strcmp(yytext,"%apply") == 0) return(APPLY);
if (strcmp(yytext,"%clear") == 0) return(CLEAR);
if (strcmp(yytext,"%doconly") == 0) return(DOCONLY);
if (strcmp(yytext,"%map") == 0) return(MAP);
/* Have an unknown identifier, as a last step, we'll */
/* do a typedef lookup on it. */
yylval.tok.text = NewString(yytext);

View file

@ -35,7 +35,8 @@ static DOH *top = 0;
static DOH *ATTR_TAG = 0;
static DOH *ATTR_CHILD = 0;
static DOH *ATTR_PARENT = 0;
static DOH *ATTR_SIBLING = 0;
static DOH *ATTR_NEXT = 0;
static DOH *ATTR_PREV = 0;
static DOH *ATTR_NAME = 0;
static DOH *ATTR_VALUE = 0;
static DOH *ATTR_TYPE = 0;
@ -52,7 +53,24 @@ static DOH *TAG_VARIABLE = 0;
o = child;
while (o) {
Setattr(o,ATTR_PARENT,parent);
o = Getattr(o,ATTR_SIBLING);
o = Getattr(o,ATTR_NEXT);
}
}
/* Create all back links so we get a doubly-linked lists */
static void create_backlinks(DOH *top) {
DOH *prev = 0;
DOH *obj;
if (!top) return;
obj = top;
while (obj) {
if (prev) {
Setattr(obj,ATTR_PREV,prev);
}
create_backlinks(Getattr(obj,ATTR_CHILD));
prev = obj;
obj = Getattr(obj,ATTR_NEXT);
}
}
@ -61,11 +79,13 @@ static DOH *TAG_VARIABLE = 0;
int yyparse();
DOH *tp;
if (!ATTR_SIBLING) {
if (!ATTR_NEXT) {
ATTR_PARENT = NewString("parent");
DohIntern(ATTR_PARENT);
ATTR_SIBLING = NewString("sibling");
DohIntern(ATTR_SIBLING);
ATTR_NEXT = NewString("next");
DohIntern(ATTR_NEXT);
ATTR_PREV = NewString("prev");
DohIntern(ATTR_PREV);
ATTR_CHILD = NewString("child");
DohIntern(ATTR_CHILD);
ATTR_TAG = NewString("tag");
@ -76,7 +96,7 @@ static DOH *TAG_VARIABLE = 0;
DohIntern(ATTR_VALUE);
ATTR_TYPE = NewString("type");
DohIntern(ATTR_TYPE);
ATTR_PARMS = NewString("parameters");
ATTR_PARMS = NewString("parms");
DohIntern(ATTR_PARMS);
ATTR_PARM = NewString("parm");
DohIntern(ATTR_PARM);
@ -98,6 +118,7 @@ static DOH *TAG_VARIABLE = 0;
yyparse();
Setattr(tp, ATTR_CHILD, top);
setparent(tp,top);
create_backlinks(tp);
return tp;
}
@ -114,15 +135,17 @@ static DOH *TAG_VARIABLE = 0;
static DOH *parmstotype(DOH *parms) {
int i, l;
DOH *p, *r;
r = NewString("(");
DOHList *ty;
ty = NewList();
p = parms;
while (p) {
Append(r,Getattr(p,ATTR_TYPE));
p = Getattr(p,ATTR_SIBLING);
if (p)
Append(r,",");
Append(ty,Getattr(p,ATTR_TYPE));
p = Getattr(p,ATTR_NEXT);
}
Append(r,")");
r = NewString("");
SwigType_add_function(r,ty);
Delete(ty);
return r;
}
@ -212,7 +235,7 @@ static int promote(int t1, int t2) {
%token <tok> ADDMETHODS ALPHA_MODE APPLY CHECKOUT CLEAR CONSTANT DOCONLY DOC_DISABLE DOC_ENABLE ECHO EXCEPT
%token <tok> ILLEGAL IMPORT INCLUDE INIT INLINE LOCALSTYLE MACRO MODULE NAME NATIVE NEW PRAGMA
%token <tok> RAW_MODE READONLY READWRITE RENAME SECTION STYLE SUBSECTION SUBSUBSECTION TEXT TITLE
%token <tok> TYPE TYPEMAP USERDIRECTIVE WEXTERN WRAPPER
%token <tok> TYPE TYPEMAP USERDIRECTIVE WEXTERN WRAPPER MAP
/* Operators */
%left <tok> LOR
@ -237,8 +260,8 @@ static int promote(int t1, int t2) {
%type <tmname> tm_name
%type <tok> tm_method
%type <node> statement swig_directive c_declaration
%type <node> file_include code_block doc_directive except_directive pragma_directive modifier_directive native_directive typemap_directive
%type <node> variable_decl function_decl enum_decl typedef_decl stail edecl typedeflist
%type <node> file_include code_block doc_directive except_directive pragma_directive modifier_directive native_directive typemap_directive map_directive
%type <node> variable_decl function_decl enum_decl typedef_decl stail edecl typedeflist map_element
%type <nodelist> enumlist interface
%type <node> inherit base_list
%type <tok> base_specifier access_specifier cpp_end ctor_end opt_id
@ -261,21 +284,21 @@ interface : interface statement {
o = $2;
while (o) {
o2 = o;
o = Getattr(o,ATTR_SIBLING);
o = Getattr(o,ATTR_NEXT);
}
$$.last = o2;
} else {
if ($2) {
o = $1.last;
if (o) {
Setattr(o,ATTR_SIBLING,$2);
Setattr(o,ATTR_NEXT,$2);
} else {
Setattr($1.node,ATTR_SIBLING,$2);
Setattr($1.node,ATTR_NEXT,$2);
}
o = $2;
while (o) {
o2 = o;
o = Getattr(o,ATTR_SIBLING);
o = Getattr(o,ATTR_NEXT);
}
$1.last = o2;
}
@ -369,6 +392,7 @@ swig_directive : MODULE idstring {
| modifier_directive { $$ = $1; }
| native_directive { $$ = $1; }
| typemap_directive { $$ = $1; }
| map_directive { $$ = $1; }
| TYPE ID idlist SEMI { $$ = 0; }
;
@ -412,20 +436,20 @@ modifier_directive : READONLY { $$ = new_node("readonlydirective",$1.filename, $
code_block : HBLOCK {
$$ = new_node("headerblock",$1.filename,$1.line);
Setattr($$,"text", $1.text);
Setattr($$,"code", $1.text);
}
| WRAPPER HBLOCK {
$$ = new_node("wrapperblock",$2.filename,$2.line);
Setattr($$,"text",$2.text);
Setattr($$,"code",$2.text);
}
| INIT HBLOCK {
$$ = new_node("initblock",$2.filename,$2.line);
Setattr($$,"text",$2.text);
Setattr($$,"code",$2.text);
}
| INLINE HBLOCK {
DOH *pp;
$$ = new_node("headerblock",$2.filename,$2.line);
Setattr($$,"text", $2.text);
Setattr($$,"code", $2.text);
Seek($2.text,0,SEEK_SET);
pp = Preprocessor_parse($2.text);
Seek(pp,0,SEEK_SET);
@ -569,7 +593,7 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE {
Setattr(o,ATTR_PARMS,Getattr(l,ATTR_PARMS));
if (!$$) $$ = o;
if (prev) {
Setattr(prev,ATTR_SIBLING,o);
Setattr(prev,ATTR_NEXT,o);
}
prev = o;
}
@ -590,7 +614,7 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE {
Setattr(o,ATTR_TYPE,Getattr(l,ATTR_TYPE));
Setattr(o,ATTR_PARMS,Getattr(l,ATTR_PARMS));
if (!$$) $$ = o;
if (prev) Setattr(prev,ATTR_SIBLING,o);
if (prev) Setattr(prev,ATTR_NEXT,o);
prev = o;
}
}
@ -609,7 +633,7 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE {
Setattr(o,ATTR_NAME,Getattr(l,ATTR_NAME));
Setattr(o,ATTR_TYPE,Getattr(l,ATTR_TYPE));
if (!$$) $$ = o;
if (prev) Setattr(prev,ATTR_SIBLING,o);
if (prev) Setattr(prev,ATTR_NEXT,o);
prev = o;
}
}
@ -627,7 +651,7 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE {
Setattr(o,ATTR_NAME,Getattr(l,ATTR_NAME));
Setattr(o,ATTR_TYPE,Getattr(l,ATTR_TYPE));
if (!$$) $$ = o;
if (prev) Setattr(prev,ATTR_SIBLING,o);
if (prev) Setattr(prev,ATTR_NEXT,o);
prev = o;
}
}
@ -649,7 +673,7 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE {
Setattr(o,"srcname",Getattr($9,ATTR_NAME));
Setattr(o,"srctype",Getattr($9,ATTR_TYPE));
if (!$$) $$ = o;
if (prev) Setattr(prev,ATTR_SIBLING,o);
if (prev) Setattr(prev,ATTR_NEXT,o);
prev = o;
}
}
@ -670,7 +694,7 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE {
Setattr(o,"srcname",Getattr($7,ATTR_NAME));
Setattr(o,"srctype",Getattr($7,ATTR_TYPE));
if (!$$) $$ = o;
if (prev) Setattr(prev,ATTR_SIBLING,o);
if (prev) Setattr(prev,ATTR_NEXT,o);
prev = o;
}
}
@ -782,6 +806,52 @@ tm_args : LPAREN parms RPAREN {
;
map_directive : MAP ID LPAREN parms RPAREN LBRACE map_element RBRACE {
$$ = new_node("map", $1.filename, $1.line);
Setattr($$,ATTR_NAME,$2.text);
Setattr($$,ATTR_PARMS,$4);
if ($7) {
Setattr($$,ATTR_CHILD,$7);
setparent($$,$7);
}
}
;
map_element : variable_decl map_element {
DOH *o, *o2;
$$ = $1;
o = $1;
while (o) {
o2 = o;
o = Getattr(o,ATTR_NEXT);
}
Setattr(o2,ATTR_NEXT,$2);
}
| function_decl map_element {
DOH *o, *o2;
$$ = $1;
o = $1;
while (o) {
o2 = o;
o = Getattr(o,ATTR_NEXT);
}
Setattr(o2,ATTR_NEXT,$2);
}
| STRING COLON LBRACE {
DOH *text = LParse_skip_balanced('{','}');
$$ = new_node("mapelement",$1.filename, $1.line);
Setattr($$,ATTR_NAME,$1.text);
Setattr($$,"code",text);
$1.text = $$;
} map_element {
$$ = $1.text;
if ($5)
Setattr($$,ATTR_NEXT,$5);
}
| empty {
$$ = 0;
}
;
/* =============================================================================
@ -812,7 +882,7 @@ variable_decl : storage_spec type declaration array2 def_args stail {
Setattr($$,ATTR_VALUE,$5.text);
}
if ($6) {
Setattr($$,ATTR_SIBLING,$6);
Setattr($$,ATTR_NEXT,$6);
o = $6;
while (o) {
t = Copy($2);
@ -821,7 +891,7 @@ variable_decl : storage_spec type declaration array2 def_args stail {
if ($1.ivalue) {
Setattr(o,ATTR_STORAGE,$1.text);
}
o = Getattr(o,ATTR_SIBLING);
o = Getattr(o,ATTR_NEXT);
}
}
}
@ -850,7 +920,7 @@ function_decl : storage_spec type declaration LPAREN parms RPAREN cpp_const sta
Setattr($$,ATTR_STORAGE, $1.text);
}
if ($8) {
Setattr($$,ATTR_SIBLING,$8);
Setattr($$,ATTR_NEXT,$8);
o = $8;
while (o) {
t = Copy($2);
@ -859,7 +929,7 @@ function_decl : storage_spec type declaration LPAREN parms RPAREN cpp_const sta
if ($1.ivalue) {
Setattr(o,ATTR_STORAGE,$1.text);
}
o = Getattr(o,ATTR_SIBLING);
o = Getattr(o,ATTR_NEXT);
}
}
}
@ -922,7 +992,7 @@ stail : SEMI { $$ = 0; }
if ($4.text)
Setattr($$,ATTR_VALUE,$4.text);
if ($5)
Setattr($$,ATTR_SIBLING, $5);
Setattr($$,ATTR_NEXT, $5);
}
| COMMA declaration LPAREN parms RPAREN stail {
DOH *t = NewString("");
@ -932,7 +1002,7 @@ stail : SEMI { $$ = 0; }
Setattr($$,ATTR_PARMS,$4);
Setattr($$,ATTR_TYPE, t);
if ($6)
Setattr($$,ATTR_SIBLING,$6);
Setattr($$,ATTR_NEXT,$6);
}
;
@ -983,7 +1053,7 @@ enum_decl : storage_spec ENUM ename LBRACE enumlist RBRACE SEMI {
o = new_node("typedef",$7.filename,$7.line);
Setattr(o,ATTR_NAME,$7.text);
Setattr(o,ATTR_TYPE,$3.text);
Setattr($$,ATTR_SIBLING,o);
Setattr($$,ATTR_NEXT,o);
}
}
;
@ -995,22 +1065,9 @@ ename : ID { $$ = $1; }
;
enumlist : enumlist COMMA edecl {
Setattr($1.last,ATTR_SIBLING,$3);
Setattr($1.last,ATTR_NEXT,$3);
$1.last = $3;
$$ = $1;
/*
DOH *o;
if ($3) {
o = Getattr($1,LASTATTR_SIBLING);
if (o) {
Setattr(o,ATTR_SIBLING,$3);
} else {
Setattr($1,ATTR_SIBLING,$3);
}
Setattr($1,LASTSIBLING,$3);;
}
$$ = $1;
*/
}
| edecl {
$$.node = $1;
@ -1050,7 +1107,7 @@ typedef_decl : TYPEDEF type declaration array2 typedeflist SEMI {
SwigType_push(ty,Getattr(d,"array"));
Setattr(o,ATTR_TYPE,ty);
Setattr(o,ATTR_NAME,Getattr(d,ATTR_NAME));
Setattr(prev,ATTR_SIBLING,o);
Setattr(prev,ATTR_NEXT,o);
prev = o;
}
Delete($5);
@ -1162,7 +1219,7 @@ cpp_class : storage_spec cpptype ID inherit LBRACE interface RBRACE opt_id S
t = Copy($3.text);
SwigType_push(t,$8.decl);
Setattr(o,ATTR_TYPE,t);
Setattr($$,ATTR_SIBLING,o);
Setattr($$,ATTR_NEXT,o);
prev = o;
for (i = 0; i < Len($9); i++) {
d = Getitem($9,i);
@ -1172,7 +1229,7 @@ cpp_class : storage_spec cpptype ID inherit LBRACE interface RBRACE opt_id S
SwigType_push(t,Getattr(d,"array"));
Setattr(o,ATTR_TYPE,t);
Setattr(o,ATTR_NAME,Getattr(d,ATTR_NAME));
Setattr(prev,ATTR_SIBLING,o);
Setattr(prev,ATTR_NEXT,o);
prev = o;
}
Delete($9);
@ -1301,7 +1358,7 @@ cpp_other :/* A dummy class name */
$$ = new_node("addmethods",$1.filename,$1.line);
if ($1.text)
Setattr($$,ATTR_NAME,$1.text);
if ($4.node) {
if ($4.node) {
Setattr($$,ATTR_CHILD,$4.node);
setparent($$,$4.node);
}
@ -1318,17 +1375,21 @@ opt_id : ID { $$ = $1; }
/* -- Function parameter lists -- */
parms : parm ptail {
if ($2)
Setattr($1,ATTR_SIBLING,$2);
$$ = $1;
}
if ($2) {
Setattr($1,ATTR_NEXT,$2);
Setattr($2,ATTR_PREV,$1);
}
$$ = $1;
}
| empty { $$ = 0; }
;
ptail : COMMA parm ptail {
if ($3)
Setattr($2,ATTR_SIBLING,$3);
$$ = $2;
if ($3) {
Setattr($2,ATTR_NEXT,$3);
Setattr($3,ATTR_PREV,$2);
}
$$ = $2;
}
| empty { $$ = 0; }
;

View file

@ -13,6 +13,7 @@
#define CPLUS_PRIVATE 2
#define CPLUS_PROTECTED 3
static DOHFile *runtime = 0;
static DOHFile *headers = 0;
static DOHFile *wrappers = 0;
static DOHFile *init = 0;
@ -26,6 +27,15 @@ 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 -------- */
@ -76,18 +86,22 @@ emit_scope(DOH *obj, void *clientdata) {
/* -------- 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);
@ -96,18 +110,121 @@ emit_initblock(DOH *obj, void *clientdata) {
/* ------ Basic C declarations ----- */
/* -----------------------------------------------------------------------------
* function
* ----------------------------------------------------------------------------- */
static int
emit_function(DOH *obj, void *clientdata) {
Printf(stdout,"function\n");
DOHString *name, *scriptname, *type, *storage;
DOHList *parms;
DOHHash *p;
SwigWrapper *wf;
int numarg = 0, numopt = 0;
int i;
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 = NewSwigWrapper();
/* Printf(wf->def,"void %s(args) {\n", Swig_name_wrapper(scriptname));*/
Printv(wf->def,
"static PyObject *", Swig_name_wrapper(scriptname), "(PyObject *self, PyObject *args) {\n",
0);
/* Mapping test */
{
DOH *rules;
int mlen = 0;
rules = Swig_map_match(Rules,"input",parms, &mlen);
Printf(stdout,"match(%d)\n", mlen);
}
/* Loop over all of the function arguments and build pieces of the wrapper function */
{
DOHString *formatstr; /* Format string for parsing arguments */
DOHString *argstr; /* List of arguments */
formatstr = NewString("");
argstr = NewString("");
for (p = parms, i=0; p; p = Swig_next(p), i++) {
DOHString *pdecl, *pname, *ptype, *value;
pname = NewStringf("_arg%d",i);
ptype = Getattr(p,"type");
if (SwigType_isarray(ptype)) {
int i;
int nd;
nd = SwigType_array_ndim(ptype);
for (i = 0; i < nd; i++) {
Printf(stdout,"array[%d] = %s\n", i, SwigType_array_getdim(ptype,i));
}
}
pdecl = SwigType_cstr(ptype,pname);
if ((value = Getattr(p,"value"))) {
Printf(pdecl," = %s", value);
numopt++;
} else {
if (numopt > 0) {
printf("*** Error: Non-optional argument follows optional argument!\n");
}
}
SwigWrapper_add_local(wf,pdecl,pname);
Printf(argstr,",&%s",pname);
Delete(pname);
Delete(pdecl);
}
Printv(wf->code,
"if (!PyParseArgs(\"", formatstr, "\"", argstr, ")) {\n",
"return NULL;\n",
"}\n",
0);
}
Printf(wf->code,"}\n");
SwigWrapper_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");
@ -145,7 +262,10 @@ emit_class(DOH *obj, void *clientdata) {
Printf(stdout,"class\n");
c = Getattr(obj, "child");
if (c) {
int ic = InClass;
InClass = 1;
Swig_emit(c,clientdata);
InClass = ic;
}
return 0;
}
@ -197,7 +317,7 @@ static int
emit_moduledirective(DOH *obj, void *clientdata) {
if (!ModuleName) {
ModuleName = Getattr(obj,"name");
Incref(ModuleName);
DohIncref(ModuleName);
}
return 0;
}
@ -228,7 +348,7 @@ static int
emit_namedirective(DOH *obj, void *clientdata) {
if (NewName) Delete(NewName);
NewName = Getattr(obj,"name");
if (NewName) Incref(NewName);
if (NewName) DohIncref(NewName);
return 0;
}
@ -287,24 +407,65 @@ emit_cleardirective(DOH *obj, void *clientdata) {
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,rules);
}
/* -------- 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 */
headers = NewString("\n/* --- Headers --- */\n");
wrappers = NewString("\n/* --- Wrappers --- */\n");
init = NewString("\n/* --- Initialization --- */\n");
runtime = NewString(runtime_banner);
headers = NewString(header_banner);
wrappers = NewString(wrapper_banner);
init = NewString(init_banner);
Rules = NewHash();
RenameHash = NewHash();
Swig_emit(top, clientdata);
Swig_banner(stdout);
/* Get the runtime library */
Swig_insert_file("python.swg",runtime);
Dump(runtime,stdout);
Dump(headers,stdout);
Dump(wrappers,stdout);
Dump(init, stdout);
Delete(runtime);
Delete(headers);
Delete(wrappers);
Delete(init);
@ -345,6 +506,7 @@ static SwigRule rules[] = {
"typemapcopy", emit_typemapcopy,
"applydirective", emit_applydirective,
"cleardirective", emit_cleardirective,
"map", emit_map,
NULL, NULL
};

View file

@ -5,8 +5,8 @@
srcdir = @srcdir@
VPATH = @srcdir@
SRCS = naming.c tree.c stype.c scanner.c include.c getopt.c misc.c
OBJS = naming.o tree.o stype.o scanner.o include.o getopt.o misc.o
SRCS = map.c wrapfunc.c naming.c tree.c stype.c scanner.c include.c getopt.c misc.c
OBJS = map.o wrapfunc.o naming.o tree.o stype.o scanner.o include.o getopt.o misc.o
prefix = @prefix@
exec_prefix = @exec_prefix@

200
Source/Swig/map.c Normal file
View file

@ -0,0 +1,200 @@
/* -----------------------------------------------------------------------------
* map.c
*
* This file provides support for defining %map rules that match lists of
* parameters to objects defining code generation rules.
*
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
*
* Copyright (C) 1999-2000. The University of Chicago
* See the file LICENSE for information on usage and redistribution.
* ----------------------------------------------------------------------------- */
#include "swig.h"
/* -----------------------------------------------------------------------------
* Synopsis
*
* One of the biggest problems in wrapper generation is that of defining
* the handling of various datatypes and function parameters. This module
* provides support for a generic object known as a 'mapping rule' that is
* defined using the %map directive like this:
*
* %map rulename(typelist) {
* vars;
* rule1 { ... }
* rule2 { ... }
* rule3 { ... }
* rule4 { ... }
* ...
* }
*
* A mapping rule is somewhat similar to a class or structure definition. The
* "vars" field is a list of variable declarations that will be local to the
* mapping rule when it is used. The "rulen" fields simply define code
* fragments and other information that language specific modules can examine
* for their own nefarious purposes.
*
* ----------------------------------------------------------------------------- */
/* -----------------------------------------------------------------------------
* Swig_map_add()
*
* Adds a new mapping rule. The parms input to this function should be a
* properly constructed parameter list with associated attributes. The rules
* field can technically be any valid object.
*
* The structure of how data is stored is as follows:
*
* ruleset (hash)
* --------------
* rulename ------> nameset (hash)
* --------------
* parm1 ---------> rule (hash)
* -------------
* parm2 -----------> rule (hash)
* *obj* --> obj
*
*
* For multiple arguments, we end up building a large tree of hash tables.
* The object will be stored in the *obj* attribute of the last hash table.
* ----------------------------------------------------------------------------- */
void
Swig_map_add(DOHHash *ruleset, DOHString_or_char *rulename, DOHHash *parms, DOH *obj)
{
DOHHash *nameset;
DOHHash *p, *n;
/* Locate the appropriate nameset */
nameset = Getattr(ruleset,rulename);
if (!nameset) {
/* Hmmm. First time we've seen this. Let's add it to our mapping table */
nameset = NewHash();
Setattr(ruleset,rulename,nameset);
}
/* Now, we walk down the parms list and create a series of hash tables */
p = parms;
n = nameset;
while (p) {
DOHString *ty, *name, *key;
DOHHash *nn;
ty = Getattr(p,"type");
name = Getattr(p,"name");
/* Create a hash table key */
key = NewStringf("%s-%s",name,ty);
/* See if there is already a entry with this type in the table */
nn = Getattr(n,key);
if (!nn) {
/* No. Go ahead and create it */
nn = NewHash();
Setattr(n,key,nn);
}
Delete(key);
n = nn;
p = Swig_next(p);
}
/* No more parameters. At this point, n points to the very last hash table in our search.
We'll stick our object there */
Setattr(n,"*obj*",obj);
return;
}
/* -----------------------------------------------------------------------------
* Swig_map_match()
*
* Perform a longest map for a list of parameters and a set of mapping rules.
* Returns the corresponding rule object and the number of parameters that
* were matched.
* ----------------------------------------------------------------------------- */
/* Internal function used for recursively searching rulesets */
static DOH *
Swig_map_match_internal(DOHHash *nameset, DOHHash *parms, int *nmatch) {
DOHHash *nn1, *nn2;
DOHString *ty;
DOHString *name;
DOHString *key;
int mlen1 = 0, mlen2 = 0, bestlen = 0;
DOH *obj1 = 0, *obj2 = 0;
DOH *bestobj, *bestn;
DOHHash *nextp;
if (!parms) {
bestobj = Getattr(nameset,"*obj*");
if (bestobj) *nmatch++;
return bestobj;
}
ty = Getattr(parms,"type");
name = Getattr(parms,"name");
key = NewStringf("%s-%s",name,ty);
/* See if there is an exact name match */
nn1 = Getattr(nameset,key);
if (nn1) {
mlen1++;
obj1 = Swig_map_match_internal(nn1,Swig_next(parms), &mlen1);
}
/* See if there is a generic name match */
Clear(key);
Printf(key,"-%s",ty);
nn2 = Getattr(nameset,key);
if (nn2) {
mlen2++;
obj2 = Swig_map_match_internal(nn2, Swig_next(parms), &mlen2);
}
/* Pick the best match. Note: an exact name match is preferred */
if (obj1 && obj2) {
if (mlen2 > mlen1) {
bestlen = mlen2;
bestobj = obj2;
} else {
bestlen = mlen1;
bestobj = obj1;
}
} else if (obj1) {
bestobj = obj1;
bestlen = mlen1;
} else if (obj2) {
bestobj = obj2;
bestlen = mlen2;
}
if (!bestobj) {
bestobj = Getattr(nameset,"*obj*");
if (bestobj) bestlen = 1;
}
Delete(key);
*nmatch = *nmatch + bestlen;
return bestobj;
}
DOH *
Swig_map_match(DOHHash *ruleset, DOHString_or_char *rulename, DOHHash *parms, int *nmatch)
{
DOHHash *nameset;
int mlen = 0;
DOH *best;
/* Get the nameset */
nameset = Getattr(ruleset,rulename);
if (!nameset) return 0;
best = Swig_map_match_internal(nameset,parms,&mlen);
*nmatch = mlen;
return best;
}

View file

@ -418,6 +418,40 @@ DOHString *SwigType_prefix(DOHString *t) {
return NewString("");
}
/* -----------------------------------------------------------------------------
* SwigType_array_ndim()
*
* Returns the number of dimensions of an array.
* ----------------------------------------------------------------------------- */
int SwigType_array_ndim(DOHString_or_char *id) {
int ndim = 0;
char *c = Char(id);
while (c && SwigType_isarray(c)) {
c = strchr(c,'.');
ndim++;
}
return ndim;
}
/* -----------------------------------------------------------------------------
* SwigType_array_getdim()
*
* Get the value of the nth dimension.
* ----------------------------------------------------------------------------- */
DOHString *SwigType_array_getdim(DOHString_or_char *id, int n) {
char *c = Char(id);
while (c && SwigType_isarray(c) && (n > 0)) {
c = strchr(c,'.');
n--;
}
if (n == 0) return SwigType_parm(c);
return 0;
}
/* -----------------------------------------------------------------------------
* SwigType_cstr(DOH *s, DOH *id)
*
@ -705,25 +739,3 @@ int SwigType_cmp(DOHString_or_char *tpat, DOHString_or_char *type) {
}
return 1;
}
#ifdef DEBUG
int main() {
DOHString *a,*b,*c,*d;
a = NewString("int");
SwigType_add_pointer(a);
SwigType_typedef(a,"IntPtr");
b = NewString("IntPtr");
SwigType_add_array(b,"1000");
Printf(stdout,"b = '%s'\n", b);
c = SwigType_typedef_resolve(b);
Printf(stdout,"c = '%s'\n", c);
Printf(stdout,"cmp = %d\n", SwigType_cmp("a(1000).p.p.int",b));
}
#endif

View file

@ -146,6 +146,8 @@ extern DOHHash *SwigType_pop_scope();
extern DOHString *SwigType_typedef_resolve(DOHString_or_char *t);
extern int SwigType_istypedef(DOHString_or_char *t);
extern int SwigType_cmp(DOHString_or_char *pat, DOHString_or_char *t);
extern int SwigType_array_ndim(DOHString_or_char *t);
extern DOHString *SwigType_array_getdim(DOHString_or_char *t, int n);
/* --- Parse tree support --- */
@ -159,6 +161,9 @@ extern void Swig_add_rule(DOHString_or_char *, int (*action)(DOH *, void *));
extern void Swig_add_rules(SwigRule ruleset[]);
extern void Swig_clear_rules();
extern int Swig_emit(DOH *obj, void *clientdata);
extern void Swig_cut_node(DOH *obj);
extern DOH *Swig_next(DOH *obj);
extern DOH *Swig_prev(DOH *obj);
/* -- Wrapper function Object */
@ -186,6 +191,11 @@ extern char *Swig_name_set(DOHString_or_char *vname);
extern char *Swig_name_construct(DOHString_or_char *classname);
extern char *Swig_name_destroy(DOHString_or_char *classname);
/* --- Mapping interface --- */
extern void Swig_map_add(DOHHash *ruleset, DOHString_or_char *rulename, DOHHash *parms, DOH *obj);
extern DOH *Swig_map_match(DOHHash *ruleset, DOHString_or_char *rulename, DOHHash *parms, int *nmatch);
/* --- Misc --- */
extern char *Swig_copy_string(const char *c);
extern void Swig_banner(DOHFile *f);

View file

@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
* tree.c
*
* This file provides some general purpose functions for walking through
* This file provides some general purpose functions for manipulating
* parse trees.
*
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
@ -16,6 +16,21 @@ static char cvsroot[] = "$Header$";
static DOHHash *rules = 0;
/* -----------------------------------------------------------------------------
* Swig_next()
* Swig_prev()
*
* Return next/prev node in a parse tree
* ----------------------------------------------------------------------------- */
DOH *Swig_next(DOH *obj) {
return Getattr(obj,"next");
}
DOH *Swig_prev(DOH *obj) {
return Getattr(obj,"prev");
}
/* -----------------------------------------------------------------------------
* Swig_dump_tags()
*
@ -38,7 +53,7 @@ Swig_dump_tags(DOH *obj, DOH *root) {
Swig_dump_tags(cobj,newroot);
Delete(newroot);
}
obj = Getattr(obj,"sibling");
obj = Swig_next(obj);
}
if (!root)
Delete(croot);
@ -115,10 +130,62 @@ Swig_emit(DOH *obj, void *clientdata) {
} else {
Printf(stderr,"warning: no action defined for '%s'\n", tag);
}
obj = Getattr(obj,"sibling");
obj = Swig_next(obj);
}
return 0;
}
/* -----------------------------------------------------------------------------
* Swig_cut_node(DOH *obj)
*
* This function cuts an object out of a parse tree. To do this, the object
* MUST be properly initialized with "next", "prev", and "parent" attributes.
* ----------------------------------------------------------------------------- */
void Swig_cut_node(DOH *obj) {
DOH *parent;
DOH *next;
DOH *prev;
parent = Getattr(obj,"parent");
assert(parent);
next = Getattr(obj,"next");
prev = Getattr(obj,"prev");
DohIncref(obj); /* Make sure object doesn't go away */
Delattr(obj,"parent"); /* Disassociate from my parent */
if (!next && !prev) {
/* Well, this is a single child. Guess we'll just update the parent their child is gone */
Delattr(parent,"child");
return;
}
/* If no next node, then this must be at the end of a list */
if (!next) {
Delattr(prev,"next"); /* Break the 'next' link in the previous node */
Delattr(obj,"prev"); /* Break my link back to the previous object */
return;
}
/* No previous node. This must be the beginning of a list */
if (!prev) {
Delattr(next,"prev"); /* Break the 'prev' link of the next node */
Setattr(parent,"child",next); /* Update parent to point at next node */
Delattr(obj,"next"); /* Break my link to the next object */
return;
}
/* In the middle of a list someplace */
Setattr(prev,"next",next); /* Update previous node to my next node */
Setattr(next,"prev",prev); /* Update next node to my previous node */
Delattr(obj,"next");
Delattr(obj,"prev");
return;
}