1 /* -----------------------------------------------------------------------------
2 * See the LICENSE file for information on copyright, usage and redistribution
3 * of SWIG, and the README file for authors - http://www.swig.org/release.html.
7 * cffi language module for SWIG.
8 * ----------------------------------------------------------------------------- */
10 char cvsroot_cffi_cxx[] = "$Id: cffi.cxx 11380 2009-07-08 12:17:45Z wsfulton $";
17 //#define CFFI_WRAP_DEBUG
19 class CFFI:public Language {
24 bool CWrap; // generate wrapper file for C code?
32 virtual void main(int argc, char *argv[]);
33 virtual int top(Node *n);
34 virtual int functionWrapper(Node *n);
35 virtual int variableWrapper(Node *n);
36 virtual int constantWrapper(Node *n);
37 // virtual int classDeclaration(Node *n);
38 virtual int enumDeclaration(Node *n);
39 virtual int typedefHandler(Node *n);
42 virtual int constructorHandler(Node *n);
43 virtual int destructorHandler(Node *n);
44 virtual int memberfunctionHandler(Node *n);
45 virtual int membervariableHandler(Node *n);
46 virtual int classHandler(Node *n);
49 void emit_defun(Node *n, String *name);
50 void emit_defmethod(Node *n);
51 void emit_initialize_instance(Node *n);
52 void emit_getter(Node *n);
53 void emit_setter(Node *n);
54 void emit_class(Node *n);
55 void emit_struct_union(Node *n, bool un);
56 void emit_export(Node *n, String *name);
57 void emit_inline(Node *n, String *name);
58 String *lispy_name(char *name);
59 String *lispify_name(Node *n, String *ty, const char *flag, bool kw = false);
60 String *convert_literal(String *num_param, String *type, bool try_to_split = true);
61 String *infix_to_prefix(String *val, char split_op, const String *op, String *type);
62 String *strip_parens(String *string);
63 String *trim(String *string);
64 int generate_typedef_flag;
68 void CFFI::main(int argc, char *argv[]) {
71 Preprocessor_define("SWIGCFFI 1", 0);
72 SWIG_library_directory("cffi");
73 SWIG_config_file("cffi.swg");
74 generate_typedef_flag = 0;
77 for (i = 1; i < argc; i++) {
78 if (!Strcmp(argv[i], "-help")) {
79 Printf(stdout, "cffi Options (available with -cffi)\n");
81 " -generate-typedef\n"
82 "\tIf this option is given then defctype will be used to generate\n"
83 "\tshortcuts according to the typedefs in the input.\n"
85 "\tTurn on or turn off generation of an intermediate C file when\n"
86 "\tcreating a C interface. By default this is only done for C++ code.\n"
88 "\tTurns on or off generation of code for helper lisp macro, functions,\n"
89 "\tetc. which SWIG uses while generating wrappers. These macros, functions\n" "\tmay still be used by generated wrapper code.\n");
90 } else if (!strcmp(argv[i], "-cwrap")) {
93 } else if ((Strcmp(argv[i], "-generate-typedef") == 0)) {
94 generate_typedef_flag = 1;
96 } else if (!strcmp(argv[i], "-nocwrap")) {
99 } else if (!strcmp(argv[i], "-swig-lisp")) {
100 no_swig_lisp = false;
102 } else if (!strcmp(argv[i], "-noswig-lisp")) {
108 f_clhead = NewString("");
109 f_clwrap = NewString("");
110 f_cl = NewString("");
115 int CFFI::top(Node *n) {
116 File *f_null = NewString("");
117 module = Getattr(n, "name");
119 String *cxx_filename = Getattr(n, "outfile");
120 String *lisp_filename = NewString("");
122 Printf(lisp_filename, "%s%s.lisp", SWIG_output_directory(), module);
124 File *f_lisp = NewFile(lisp_filename, "w", SWIG_output_files());
126 FileErrorDisplay(lisp_filename);
127 SWIG_exit(EXIT_FAILURE);
130 if (CPlusPlus || CWrap) {
131 f_begin = NewFile(cxx_filename, "w", SWIG_output_files());
135 Printf(stderr, "Unable to open %s for writing\n", cxx_filename);
136 SWIG_exit(EXIT_FAILURE);
139 String *clos_filename = NewString("");
140 Printf(clos_filename, "%s%s-clos.lisp", SWIG_output_directory(), module);
141 f_clos = NewFile(clos_filename, "w", SWIG_output_files());
145 Printf(stderr, "Unable to open %s for writing\n", cxx_filename);
146 SWIG_exit(EXIT_FAILURE);
149 f_begin = NewString("");
150 f_clos = NewString("");
153 f_runtime = NewString("");
154 f_cxx_header = f_runtime;
155 f_cxx_wrapper = NewString("");
157 Swig_register_filebyname("header", f_cxx_header);
158 Swig_register_filebyname("wrapper", f_cxx_wrapper);
159 Swig_register_filebyname("begin", f_begin);
160 Swig_register_filebyname("runtime", f_runtime);
161 Swig_register_filebyname("lisphead", f_clhead);
163 Swig_register_filebyname("swiglisp", f_cl);
165 Swig_register_filebyname("swiglisp", f_null);
167 Swig_banner(f_begin);
169 Printf(f_runtime, "\n");
170 Printf(f_runtime, "#define SWIGCFFI\n");
171 Printf(f_runtime, "\n");
173 Swig_banner_target_lang(f_lisp, ";;;");
176 Printf(f_lisp, "%s\n", f_clhead);
177 Printf(f_lisp, "%s\n", f_cl);
178 Printf(f_lisp, "%s\n", f_clwrap);
181 Delete(f_lisp); // Deletes the handle, not the file
185 Dump(f_runtime, f_begin);
189 Delete(f_cxx_wrapper);
195 int CFFI::classHandler(Node *n) {
197 Printf(stderr, "class %s::%s\n", "some namespace", //current_namespace,
198 Getattr(n, "sym:name"));
200 String *name = Getattr(n, "sym:name");
201 String *kind = Getattr(n, "kind");
203 // maybe just remove this check and get rid of the else clause below.
204 if (Strcmp(kind, "struct") == 0) {
205 emit_struct_union(n, false);
207 } else if (Strcmp(kind, "union") == 0) {
208 emit_struct_union(n, true);
210 } else if (Strcmp(kind, "class") == 0) {
212 Language::classHandler(n);
214 Printf(stderr, "Don't know how to deal with %s kind of class yet.\n", kind);
215 Printf(stderr, " (name: %s)\n", name);
216 SWIG_exit(EXIT_FAILURE);
223 int CFFI::constructorHandler(Node *n) {
225 Printf(stderr, "constructor %s\n", Getattr(n, "name"));
226 Printf(stderr, "constructor %s\n and %s and %s", Getattr(n, "kind"), Getattr(n, "sym:name"), Getattr(n, "allegrocl:old-sym:name"));
228 Setattr(n, "cffi:constructorfunction", "1");
229 // Let SWIG generate a global forwarding function.
230 return Language::constructorHandler(n);
233 int CFFI::destructorHandler(Node *n) {
235 Printf(stderr, "destructor %s\n", Getattr(n, "name"));
238 // Let SWIG generate a global forwarding function.
239 return Language::destructorHandler(n);
242 void CFFI::emit_defmethod(Node *n) {
243 String *args_placeholder = NewStringf("");
244 String *args_call = NewStringf("");
246 ParmList *pl = Getattr(n, "parms");
248 Node *parent = getCurrentClass();
251 for (Parm *p = pl; p; p = nextSibling(p), argnum++) {
252 String *argname = Getattr(p, "name");
253 String *ffitype = Swig_typemap_lookup("lispclass", p, "", 0);
260 Printf(args_placeholder, " ");
263 argname = NewStringf("arg%d", argnum);
265 } else if (Strcmp(argname, "t") == 0 || Strcmp(argname, "T") == 0) {
266 argname = NewStringf("t-arg%d", argnum);
269 if (Len(ffitype) > 0)
270 Printf(args_placeholder, "(%s %s)", argname, ffitype);
272 Printf(args_placeholder, "%s", argname);
274 if (ffitype && Strcmp(ffitype, lispify_name(parent, lispy_name(Char(Getattr(parent, "sym:name"))), "'classname")) == 0)
275 Printf(args_call, " (ff-pointer %s)", argname);
277 Printf(args_call, " %s", argname);
285 String *method_name = Getattr(n, "name");
286 int x = Replace(method_name, "operator ", "", DOH_REPLACE_FIRST); //
289 Printf(f_clos, "(cl:shadow \"%s\")\n", method_name);
291 Printf(f_clos, "(cl:defmethod %s (%s)\n (%s%s))\n\n",
292 lispify_name(n, lispy_name(Char(method_name)), "'method"), args_placeholder,
293 lispify_name(n, Getattr(n, "sym:name"), "'function"), args_call);
297 void CFFI::emit_initialize_instance(Node *n) {
298 String *args_placeholder = NewStringf("");
299 String *args_call = NewStringf("");
301 ParmList *pl = Getattr(n, "parms");
303 Node *parent = getCurrentClass();
305 for (Parm *p = pl; p; p = nextSibling(p), argnum++) {
306 String *argname = Getattr(p, "name");
307 String *ffitype = Swig_typemap_lookup("lispclass", p, "", 0);
311 argname = NewStringf("arg%d", argnum);
313 } else if (Strcmp(argname, "t") == 0 || Strcmp(argname, "T") == 0) {
314 argname = NewStringf("t-arg%d", argnum);
317 if (Len(ffitype) > 0)
318 Printf(args_placeholder, " (%s %s)", argname, ffitype);
320 Printf(args_placeholder, " %s", argname);
322 if (Strcmp(ffitype, lispify_name(parent, lispy_name(Char(Getattr(parent, "sym:name"))), "'classname")) == 0)
323 Printf(args_call, " (ff-pointer %s)", argname);
325 Printf(args_call, " %s", argname);
333 Printf(f_clos, "(cl:defmethod initialize-instance :after ((obj %s) &key%s)\n (setf (slot-value obj 'ff-pointer) (%s%s)))\n\n",
334 lispify_name(parent, lispy_name(Char(Getattr(parent, "sym:name"))), "'class"), args_placeholder,
335 lispify_name(n, Getattr(n, "sym:name"), "'function"), args_call);
339 void CFFI::emit_setter(Node *n) {
340 Node *parent = getCurrentClass();
341 Printf(f_clos, "(cl:defmethod (cl:setf %s) (arg0 (obj %s))\n (%s (ff-pointer obj) arg0))\n\n",
342 lispify_name(n, Getattr(n, "name"), "'method"),
343 lispify_name(parent, lispy_name(Char(Getattr(parent, "sym:name"))), "'class"), lispify_name(n, Getattr(n, "sym:name"), "'function"));
347 void CFFI::emit_getter(Node *n) {
348 Node *parent = getCurrentClass();
349 Printf(f_clos, "(cl:defmethod %s ((obj %s))\n (%s (ff-pointer obj)))\n\n",
350 lispify_name(n, Getattr(n, "name"), "'method"),
351 lispify_name(parent, lispy_name(Char(Getattr(parent, "sym:name"))), "'class"), lispify_name(n, Getattr(n, "sym:name"), "'function"));
354 int CFFI::memberfunctionHandler(Node *n) {
355 // Let SWIG generate a global forwarding function.
356 Setattr(n, "cffi:memberfunction", "1");
357 return Language::memberfunctionHandler(n);
360 int CFFI::membervariableHandler(Node *n) {
361 // Let SWIG generate a get/set function pair.
362 Setattr(n, "cffi:membervariable", "1");
363 return Language::membervariableHandler(n);
366 int CFFI::functionWrapper(Node *n) {
368 ParmList *parms = Getattr(n, "parms");
369 String *iname = Getattr(n, "sym:name");
370 Wrapper *f = NewWrapper();
372 String *raw_return_type = Swig_typemap_lookup("ctype", n, "", 0);
373 SwigType *return_type = Swig_cparse_type(raw_return_type);
374 SwigType *resolved = SwigType_typedef_resolve_all(return_type);
375 int is_void_return = (Cmp(resolved, "void") == 0);
378 if (!is_void_return) {
379 String *lresult_init = NewStringf("lresult = (%s)0", raw_return_type);
380 Wrapper_add_localv(f, "lresult", raw_return_type, lresult_init, NIL);
381 Delete(lresult_init);
384 String *overname = 0;
385 if (Getattr(n, "sym:overloaded")) {
386 overname = Getattr(n, "sym:overname");
388 if (!addSymbol(iname, n)) {
394 String *wname = Swig_name_wrapper(iname);
396 Append(wname, overname);
398 Setattr(n, "wrap:name", wname);
400 // Emit all of the local variables for holding arguments.
401 emit_parameter_variables(parms, f);
403 // Attach the standard typemaps
404 Swig_typemap_attach_parms("ctype", parms, f);
405 emit_attach_parmmaps(parms, f);
407 int num_arguments = emit_num_arguments(parms);
408 String *name_and_parms = NewStringf("%s (", wname);
414 Printf(stderr, "function - %s - %d\n", Getattr(n, "name"), num_arguments);
417 for (i = 0, p = parms; i < num_arguments; i++) {
419 while (checkAttribute(p, "tmap:in:numinputs", "0")) {
420 p = Getattr(p, "tmap:in:next");
423 SwigType *c_parm_type = Swig_cparse_type(Getattr(p, "tmap:ctype"));
424 String *arg = NewStringf("l%s", Getattr(p, "lname"));
426 // Emit parameter declaration
428 Printf(name_and_parms, ", ");
429 String *parm_decl = SwigType_str(c_parm_type, arg);
430 Printf(name_and_parms, "%s", parm_decl);
432 Printf(stderr, " param: %s\n", parm_decl);
437 // Emit parameter conversion code
438 String *parm_code = Getattr(p, "tmap:in");
440 Replaceall(parm_code, "$input", arg);
441 Setattr(p, "emit:input", arg);
442 Printf(f->code, "%s\n", parm_code);
443 p = Getattr(p, "tmap:in:next");
448 Printf(name_and_parms, ")");
450 // Emit the function definition
451 String *signature = SwigType_str(return_type, name_and_parms);
452 Printf(f->def, "EXPORT %s {", signature);
453 Printf(f->code, " try {\n");
455 String *actioncode = emit_action(n);
457 String *result_convert = Swig_typemap_lookup_out("out", n, "result", f, actioncode);
458 Replaceall(result_convert, "$result", "lresult");
459 Printf(f->code, "%s\n", result_convert);
460 if(!is_void_return) Printf(f->code, " return lresult;\n");
461 Delete(result_convert);
462 emit_return_variable(n, Getattr(n, "type"), f);
464 Printf(f->code, " } catch (...) {\n");
466 Printf(f->code, " return (%s)0;\n", raw_return_type);
467 Printf(f->code, " }\n");
468 Printf(f->code, "}\n");
471 Wrapper_print(f, f_runtime);
474 emit_defun(n, wname);
475 if (Getattr(n, "cffi:memberfunction"))
477 else if (Getattr(n, "cffi:membervariable")) {
478 if (Getattr(n, "memberget"))
480 else if (Getattr(n, "memberset"))
483 else if (Getattr(n, "cffi:constructorfunction")) {
484 emit_initialize_instance(n);
487 emit_defun(n, iname);
489 // if (!overloaded || !Getattr(n, "sym:nextSibling")) {
490 // update_package_if_needed(n);
491 // emit_buffered_defuns(n);
492 // // this is the last overload.
494 // emit_dispatch_defun(n);
505 void CFFI::emit_defun(Node *n, String *name) {
507 // String *storage=Getattr(n,"storage");
508 // if(!storage || (Strcmp(storage,"extern") && Strcmp(storage,"externc")))
511 String *func_name = Getattr(n, "sym:name");
513 ParmList *pl = Getattr(n, "parms");
517 func_name = lispify_name(n, func_name, "'function");
519 emit_inline(n, func_name);
521 Printf(f_cl, "\n(cffi:defcfun (\"%s\" %s)", name, func_name);
522 String *ffitype = Swig_typemap_lookup("cout", n, ":pointer", 0);
524 Printf(f_cl, " %s", ffitype);
527 for (Parm *p = pl; p; p = nextSibling(p), argnum++) {
529 if (SwigType_isvarargs(Getattr(p, "type"))) {
530 Printf(f_cl, "\n %s", NewString("&rest"));
534 String *argname = Getattr(p, "name");
536 ffitype = Swig_typemap_lookup("cin", p, "", 0);
541 argname = NewStringf("arg%d", argnum);
543 } else if (Strcmp(argname, "t") == 0 || Strcmp(argname, "T") == 0) {
544 argname = NewStringf("t_arg%d", argnum);
548 Printf(f_cl, "\n (%s %s)", argname, ffitype);
555 Printf(f_cl, ")\n"); /* finish arg list */
557 emit_export(n, func_name);
561 int CFFI::constantWrapper(Node *n) {
562 String *type = Getattr(n, "type");
563 String *converted_value = convert_literal(Getattr(n, "value"), type);
564 String *name = lispify_name(n, Getattr(n, "sym:name"), "'constant");
566 if (Strcmp(name, "t") == 0 || Strcmp(name, "T") == 0)
567 name = NewStringf("t_var");
569 Printf(f_cl, "\n(cl:defconstant %s %s)\n", name, converted_value);
570 Delete(converted_value);
572 emit_export(n, name);
576 int CFFI::variableWrapper(Node *n) {
577 // String *storage=Getattr(n,"storage");
578 // Printf(stdout,"\"%s\" %s)\n",storage,Getattr(n, "sym:name"));
580 // if(!storage || (Strcmp(storage,"extern") && Strcmp(storage,"externc")))
583 String *var_name = Getattr(n, "sym:name");
584 String *lisp_type = Swig_typemap_lookup("cin", n, "", 0);
585 String *lisp_name = lispify_name(n, var_name, "'variable");
587 if (Strcmp(lisp_name, "t") == 0 || Strcmp(lisp_name, "T") == 0)
588 lisp_name = NewStringf("t_var");
590 Printf(f_cl, "\n(cffi:defcvar (\"%s\" %s)\n %s)\n", var_name, lisp_name, lisp_type);
594 emit_export(n, lisp_name);
598 int CFFI::typedefHandler(Node *n) {
599 if (generate_typedef_flag && strncmp(Char(Getattr(n, "type")), "enum", 4)) {
600 String *lisp_name = lispify_name(n, Getattr(n, "name"), "'typename");
601 Printf(f_cl, "\n(cffi:defctype %s %s)\n", lisp_name, Swig_typemap_lookup("cin", n, "", 0));
602 emit_export(n, lisp_name);
604 return Language::typedefHandler(n);
607 int CFFI::enumDeclaration(Node *n) {
608 String *name = Getattr(n, "sym:name");
609 bool slot_name_keywords;
610 String *lisp_name = 0;
611 if (name && Len(name) != 0) {
612 lisp_name = lispify_name(n, name, "'enumname");
613 if (GetFlag(n, "feature:bitfield")) {
614 Printf(f_cl, "\n(cffi:defbitfield %s", lisp_name);
616 Printf(f_cl, "\n(cffi:defcenum %s", lisp_name);
618 slot_name_keywords = true;
620 //Registering the enum name to the cin and cout typemaps
621 Parm *pattern = NewParm(name, NULL);
622 Swig_typemap_register("cin", pattern, lisp_name, NULL, NULL);
623 Swig_typemap_register("cout", pattern, lisp_name, NULL, NULL);
625 //Registering with the kind, i.e., enum
626 pattern = NewParm(NewStringf("enum %s", name), NULL);
627 Swig_typemap_register("cin", pattern, lisp_name, NULL, NULL);
628 Swig_typemap_register("cout", pattern, lisp_name, NULL, NULL);
632 Printf(f_cl, "\n(defanonenum %s", name);
633 slot_name_keywords = false;
636 for (Node *c = firstChild(n); c; c = nextSibling(c)) {
638 String *slot_name = lispify_name(c, Getattr(c, "name"), "'enumvalue", slot_name_keywords);
639 String *value = Getattr(c, "enumvalue");
641 if (!value || GetFlag(n, "feature:bitfield:ignore_values"))
642 Printf(f_cl, "\n\t%s", slot_name);
644 String *type = Getattr(c, "type");
645 String *converted_value = convert_literal(value, type);
646 Printf(f_cl, "\n\t(%s #.%s)", slot_name, converted_value);
647 Delete(converted_value);
654 // No need to export keywords
655 if (lisp_name && Len(lisp_name) != 0) {
656 emit_export(n, lisp_name);
658 for (Node *c = firstChild(n); c; c = nextSibling(c))
659 emit_export(c, lispify_name(c, Getattr(c, "name"), "'enumvalue"));
664 void CFFI::emit_class(Node *n) {
666 #ifdef CFFI_WRAP_DEBUG
667 Printf(stderr, "emit_class: ENTER... '%s'(%x)\n", Getattr(n, "sym:name"), n);
670 String *name = Getattr(n, "sym:name");
671 String *lisp_name = lispify_name(n, lispy_name(Char(name)), "'classname");
673 String *bases = Getattr(n, "bases");
674 String *supers = NewString("(");
677 for (Iterator i = First(bases); i.item; i = Next(i)) {
680 String *s = Getattr(i.item, "name");
681 Printf(supers, "%s", lispify_name(i.item, s, "'classname"));
684 // Printf(supers,"ff:foreign-pointer");
688 Printf(f_clos, "\n(cl:defclass %s%s", lisp_name, supers);
689 Printf(f_clos, "\n ((ff-pointer :reader ff-pointer)))\n\n");
691 Parm *pattern = NewParm(Getattr(n, "name"), NULL);
693 Swig_typemap_register("lispclass", pattern, lisp_name, NULL, NULL);
694 SwigType_add_pointer(Getattr(pattern, "type"));
695 Swig_typemap_register("lispclass", pattern, lisp_name, NULL, NULL);
696 SwigType_add_qualifier(Getattr(pattern, "type"), "const");
697 Swig_typemap_register("lispclass", pattern, lisp_name, NULL, NULL);
698 SwigType_del_pointer(Getattr(pattern, "type"));
699 SwigType_add_reference(Getattr(pattern, "type"));
700 Swig_typemap_register("lispclass", pattern, lisp_name, NULL, NULL);
702 #ifdef CFFI_WRAP_DEBUG
703 Printf(stderr, " pattern %s name %s .. ... %s .\n", pattern, lisp_name);
708 // Walk children to generate type definition.
709 String *slotdefs = NewString(" ");
711 #ifdef CFFI_WRAP_DEBUG
712 Printf(stderr, " walking children...\n");
716 for (c = firstChild(n); c; c = nextSibling(c)) {
717 String *storage_type = Getattr(c, "storage");
718 if ((!Strcmp(nodeType(c), "cdecl") && (!storage_type || Strcmp(storage_type, "typedef")))) {
719 String *access = Getattr(c, "access");
721 // hack. why would decl have a value of "variableHandler" and now "0"?
722 String *childDecl = Getattr(c, "decl");
723 // Printf(stderr,"childDecl = '%s' (%s)\n", childDecl, Getattr(c,"view"));
724 if (!Strcmp(childDecl, "0"))
725 childDecl = NewString("");
727 SwigType *childType = NewStringf("%s%s", childDecl,
729 String *cname = (access && Strcmp(access, "public")) ? NewString("nil") : Copy(Getattr(c, "name"));
731 if (!SwigType_isfunction(childType)) {
732 // Printf(slotdefs, ";;; member functions don't appear as slots.\n ");
733 // Printf(slotdefs, ";; ");
734 // String *ns = listify_namespace(Getattr(n, "cffi:package"));
735 String *ns = NewString("");
736 #ifdef CFFI_WRAP_DEBUG
737 Printf(stderr, "slot name = '%s' ns = '%s' class-of '%s' and type = '%s'\n", cname, ns, name, childType);
739 Printf(slotdefs, "(#.(swig-insert-id \"%s\" %s :type :slot :class \"%s\") %s)", cname, ns, name, childType); //compose_foreign_type(childType)
741 if (access && Strcmp(access, "public"))
742 Printf(slotdefs, " ;; %s member", access);
744 Printf(slotdefs, "\n ");
752 // String *ns_list = listify_namespace(Getattr(n,"cffi:namespace"));
753 // update_package_if_needed(n,f_clhead);
755 // "(swig-def-foreign-class \"%s\"\n %s\n (:%s\n%s))\n\n",
756 // name, supers, kind, slotdefs);
761 // Parm *pattern = NewParm(name,NULL);
762 // Swig_typemap_register("cin",pattern,lisp_name,NULL,NULL);
763 //Swig_typemap_register("cout",pattern,lisp_name,NULL,NULL);
766 #ifdef CFFI_WRAP_DEBUG
767 Printf(stderr, "emit_class: EXIT\n");
772 void CFFI::emit_struct_union(Node *n, bool un = false) {
774 Printf(stderr, "struct/union %s\n", Getattr(n, "name"));
775 Printf(stderr, "struct/union %s\n and %s", Getattr(n, "kind"), Getattr(n, "sym:name"));
778 String *name = Getattr(n, "sym:name");
779 String *kind = Getattr(n, "kind");
781 if (Strcmp(kind, "struct") != 0 && Strcmp(kind, "union") != 0) {
782 Printf(stderr, "Don't know how to deal with %s kind of class yet.\n", kind);
783 Printf(stderr, " (name: %s)\n", name);
784 SWIG_exit(EXIT_FAILURE);
786 String *lisp_name = lispify_name(n, name, "'classname");
788 //Register the struct/union name to the cin and cout typemaps
790 Parm *pattern = NewParm(name, NULL);
791 Swig_typemap_register("cin", pattern, lisp_name, NULL, NULL);
792 Swig_typemap_register("cout", pattern, lisp_name, NULL, NULL);
794 //Registering with the kind, i.e., struct or union
795 pattern = NewParm(NewStringf("%s %s", kind, name), NULL);
796 Swig_typemap_register("cin", pattern, lisp_name, NULL, NULL);
797 Swig_typemap_register("cout", pattern, lisp_name, NULL, NULL);
801 Printf(f_cl, "\n(cffi:defcunion %s", lisp_name);
803 Printf(f_cl, "\n(cffi:defcstruct %s", lisp_name);
806 for (Node *c = firstChild(n); c; c = nextSibling(c)) {
808 Printf(stderr, "struct/union %s\n", Getattr(c, "name"));
809 Printf(stderr, "struct/union %s and %s \n", Getattr(c, "kind"), Getattr(c, "sym:name"));
812 if (Strcmp(nodeType(c), "cdecl")) {
813 //C declaration ignore
814 // Printf(stderr, "Structure %s has a slot that we can't deal with.\n",
816 // Printf(stderr, "nodeType: %s, name: %s, type: %s\n",
818 // Getattr(c, "name"),
819 // Getattr(c, "type"));
820 // SWIG_exit(EXIT_FAILURE);
822 SwigType *childType = NewStringf("%s%s", Getattr(c, "decl"), Getattr(c, "type"));
824 Node *node = NewHash();
825 Setattr(node, "type", childType);
826 Setfile(node, Getfile(n));
827 Setline(node, Getline(n));
828 const String *tm = Swig_typemap_lookup("cin", node, "", 0);
830 String *typespec = tm ? NewString(tm) : NewString("");
832 String *slot_name = lispify_name(c, Getattr(c, "sym:name"), "'slotname");
833 if (Strcmp(slot_name, "t") == 0 || Strcmp(slot_name, "T") == 0)
834 slot_name = NewStringf("t_var");
836 Printf(f_cl, "\n\t(%s %s)", slot_name, typespec);
846 emit_export(n, lisp_name);
847 for (Node *child = firstChild(n); child; child = nextSibling(child)) {
848 if (!Strcmp(nodeType(child), "cdecl")) {
849 emit_export(child, lispify_name(child, Getattr(child, "sym:name"), "'slotname"));
853 /* Add this structure to the known lisp types */
854 //Printf(stdout, "Adding %s foreign type\n", name);
855 // add_defined_foreign_type(name);
859 void CFFI::emit_export(Node *n, String *name) {
860 if (GetInt(n, "feature:export"))
861 Printf(f_cl, "\n(cl:export '%s)\n", name);
864 void CFFI::emit_inline(Node *n, String *name) {
865 if (GetInt(n, "feature:inline"))
866 Printf(f_cl, "\n(cl:declaim (cl:inline %s))\n", name);
869 String *CFFI::lispify_name(Node *n, String *ty, const char *flag, bool kw) {
870 String *intern_func = Getattr(n, "feature:intern_function");
872 if (Strcmp(intern_func, "1") == 0)
873 intern_func = NewStringf("swig-lispify");
874 return NewStringf("#.(%s \"%s\" %s%s)", intern_func, ty, flag, kw ? " :keyword" : "");
876 return NewStringf(":%s", ty);
882 /* returns new string w/ parens stripped */
883 String *CFFI::strip_parens(String *string) {
884 char *s = Char(string), *p;
885 int len = Len(string);
888 if (len == 0 || s[0] != '(' || s[len - 1] != ')') {
889 return NewString(string);
892 p = (char *) malloc(len - 2 + 1);
894 Printf(stderr, "Malloc failed\n");
895 SWIG_exit(EXIT_FAILURE);
898 strncpy(p, s + 1, len - 1);
899 p[len - 2] = 0; /* null terminate */
907 String *CFFI::trim(String *str) {
909 while (*c != '\0' && isspace((int) *c))
911 String *result = NewString(c);
916 String *CFFI::infix_to_prefix(String *val, char split_op, const String *op, String *type) {
917 List *ored = Split(val, split_op, -1);
919 // some float hackery
920 //i don't understand it, if you do then please explain
921 // if ( ((split_op == '+') || (split_op == '-')) && Len(ored) == 2 &&
922 // (SwigType_type(type) == T_FLOAT || SwigType_type(type) == T_DOUBLE ||
923 // SwigType_type(type) == T_LONGDOUBLE) ) {
924 // // check that we're not splitting a float
925 // String *possible_result = convert_literal(val, type, false);
926 // if (possible_result) return possible_result;
930 // try parsing the split results. if any part fails, kick out.
931 bool part_failed = false;
933 String *result = NewStringf("(%s", op);
934 for (Iterator i = First(ored); i.item; i = Next(i)) {
935 String *converted = convert_literal(i.item, type);
937 Printf(result, " %s", converted);
946 return part_failed ? 0 : result;
953 /* To be called by code generating the lisp interface
954 Will return a String containing the literal based on type.
955 Will return null if there are problems.
957 try_to_split defaults to true (see stub above).
959 String *CFFI::convert_literal(String *literal, String *type, bool try_to_split) {
960 String *num_param = Copy(literal);
961 String *trimmed = trim(num_param);
962 String *num = strip_parens(trimmed), *res = 0;
966 // very basic parsing of infix expressions.
968 if ((res = infix_to_prefix(num, '|', "cl:logior", type)))
970 if ((res = infix_to_prefix(num, '&', "cl:logand", type)))
972 if ((res = infix_to_prefix(num, '^', "cl:logxor", type)))
974 if ((res = infix_to_prefix(num, '*', "cl:*", type)))
976 if ((res = infix_to_prefix(num, '/', "cl:/", type)))
978 if ((res = infix_to_prefix(num, '+', "cl:+", type)))
980 if ((res = infix_to_prefix(num, '-', "cl:-", type)))
984 if (SwigType_type(type) == T_FLOAT || SwigType_type(type) == T_DOUBLE || SwigType_type(type) == T_LONGDOUBLE) {
985 // Use CL syntax for float literals
987 // careful. may be a float identifier or float constant.
988 char *num_start = Char(num);
989 char *num_end = num_start + strlen(num_start) - 1;
991 bool is_literal = isdigit(*num_start) || (*num_start == '.') || (*num_start == '+') || (*num_start == '-');
993 String *lisp_exp = 0;
995 if (*num_end == 'f' || *num_end == 'F') {
996 lisp_exp = NewString("f");
998 lisp_exp = NewString("d");
1001 if (*num_end == 'l' || *num_end == 'L' || *num_end == 'f' || *num_end == 'F') {
1006 int exponents = Replaceall(num, "e", lisp_exp) + Replaceall(num, "E", lisp_exp);
1009 Printf(num, "%s0", lisp_exp);
1011 if (exponents > 1 || (exponents + Replaceall(num, ".", ".") == 0)) {
1017 } else if (SwigType_type(type) == T_CHAR) {
1018 /* Use CL syntax for character literals */
1019 String* result = NewStringf("#\\%c", s[2]);
1021 // Printf(stderr, "%s %c %d", s, s[2], s);
1023 } else if (SwigType_type(type) == T_STRING) {
1024 /* Use CL syntax for string literals */
1025 String* result = NewStringf("\"%s\"", num_param);
1028 } else if (SwigType_type(type) == T_INT || SwigType_type(type) == T_UINT) {
1029 // Printf(stderr, "Is a T_INT or T_UINT %s, before replaceall\n", s);
1030 Replaceall(num, "u", "");
1031 Replaceall(num, "U", "");
1032 Replaceall(num, "l", "");
1033 Replaceall(num, "L", "");
1036 if (sscanf(s, "%d >> %d", &i, &j) == 2) {
1037 String* result = NewStringf("(cl:ash %d -%d)", i, j);
1040 } else if (sscanf(s, "%d << %d", &i, &j) == 2) {
1041 String* result = NewStringf("(cl:ash %d %d)", i, j);
1047 if (Len(num) >= 2 && s[0] == '0') { /* octal or hex */
1049 DohReplace(num,"0","#",DOH_REPLACE_FIRST);
1052 DohReplace(num,"0","#o",DOH_REPLACE_FIRST);
1058 //less flexible as it does the conversion in C, the lispify name does the conversion in lisp
1059 String *CFFI::lispy_name(char *name) {
1060 bool helper = false;
1061 String *new_name = NewString("");
1062 for (unsigned int i = 0; i < strlen(name); i++) {
1063 if (name[i] == '_' || name[i] == '-') {
1064 Printf(new_name, "%c", '-');
1066 } else if (name[i] >= 'A' && name[i] <= 'Z') {
1068 Printf(new_name, "%c", '-');
1069 Printf(new_name, "%c", ('a' + (name[i] - 'A')));
1073 Printf(new_name, "%c", name[i]);
1079 extern "C" Language *swig_cffi(void) {