~ubuntu-branches/ubuntu/edgy/swig1.3/edgy

« back to all changes in this revision

Viewing changes to Source/Modules/uffi.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-12-05 01:16:04 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051205011604-ygx904it6413k3go
Tags: 1.3.27-1ubuntu1
Resynchronise with Debian again, for the new subversion packages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
char cvsroot_uffi_cxx[] = "$Header: /cvsroot/swig/SWIG/Source/Modules/uffi.cxx,v 1.2 2005/09/08 22:31:21 wsfulton Exp $";
 
2
// TODO: remove remnants of lisptype
 
3
#include "swigmod.h"
 
4
 
 
5
class UFFI : public Language {
 
6
public:
 
7
 
 
8
  virtual void main(int argc, char *argv[]);
 
9
  virtual int top(Node *n);
 
10
  virtual int functionWrapper(Node *n); 
 
11
  virtual int constantWrapper(Node *n);
 
12
  virtual int classHandler(Node *n);
 
13
  virtual int membervariableHandler(Node *n);
 
14
 
 
15
};
 
16
 
 
17
static File *f_cl=0;
 
18
static File *f_null=0;
 
19
 
 
20
static struct {
 
21
  int count;
 
22
  String **entries;
 
23
} defined_foreign_types;
 
24
 
 
25
static const char *identifier_converter="identifier-convert-null";
 
26
 
 
27
static int any_varargs(ParmList *pl) {
 
28
  Parm *p;
 
29
  
 
30
  for(p=pl; p; p=nextSibling(p)) {
 
31
    if (SwigType_isvarargs(Getattr(p, "type")))
 
32
      return 1;
 
33
  }
 
34
 
 
35
  return 0;
 
36
}
 
37
 
 
38
  
 
39
/* utilities */
 
40
/* returns new string w/ parens stripped */
 
41
static String *strip_parens(String *string) {
 
42
        char *s=Char(string), *p;
 
43
        int len=Len(string);
 
44
        String *res;
 
45
        
 
46
        if (len==0 || s[0] != '(' || s[len-1] != ')') {
 
47
                return NewString(string);
 
48
        }
 
49
        
 
50
        p=(char *)malloc(len-2+1);
 
51
        if (!p) {
 
52
                Printf(stderr, "Malloc failed\n");
 
53
                SWIG_exit(EXIT_FAILURE);
 
54
        }
 
55
        
 
56
        strncpy(p, s+1, len-1);
 
57
        p[len-2]=0; /* null terminate */
 
58
        
 
59
        res=NewString(p);
 
60
        free(p);
 
61
        
 
62
        return res;
 
63
}
 
64
 
 
65
 
 
66
static String *convert_literal(String *num_param, String *type) {
 
67
        String *num=strip_parens(num_param), *res;
 
68
        char *s=Char(num);
 
69
        
 
70
        /* Make sure doubles use 'd' instead of 'e' */
 
71
        if (!Strcmp(type, "double")) {
 
72
                String *updated=Copy(num);
 
73
                if (Replace(updated, "e", "d", DOH_REPLACE_ANY) > 1) {
 
74
                        Printf(stderr, "Weird!! number %s looks invalid.\n", num);
 
75
                        SWIG_exit(EXIT_FAILURE);
 
76
                }
 
77
                Delete(num);
 
78
                return updated;
 
79
        }
 
80
 
 
81
        if (SwigType_type(type) == T_CHAR) {
 
82
                /* Use CL syntax for character literals */
 
83
                return NewStringf("#\\%s", num_param);
 
84
        }
 
85
        else if (SwigType_type(type) == T_STRING) {
 
86
                /* Use CL syntax for string literals */
 
87
                return NewStringf("\"%s\"", num_param);
 
88
        }
 
89
        
 
90
        if (Len(num) < 2 || s[0] != '0') {
 
91
                return num;
 
92
        }
 
93
        
 
94
        /* octal or hex */
 
95
        
 
96
        res=NewStringf("#%c%s", 
 
97
                       s[1] == 'x' ? 'x' : 'o', 
 
98
                       s+2);
 
99
        Delete(num);
 
100
 
 
101
        return res;
 
102
}
 
103
 
 
104
static void add_defined_foreign_type(String *type) {
 
105
  if (!defined_foreign_types.count) {
 
106
    /* Make fresh */
 
107
    defined_foreign_types.count=1;
 
108
    defined_foreign_types.entries=(String **)malloc(sizeof(String *));
 
109
  } else {
 
110
    /* make room */
 
111
    defined_foreign_types.count++;
 
112
    defined_foreign_types.entries=(String **)
 
113
      realloc(defined_foreign_types.entries,
 
114
              defined_foreign_types.count*sizeof(String *));
 
115
  }
 
116
 
 
117
  if (!defined_foreign_types.entries) {
 
118
    Printf(stderr, "Out of memory\n");
 
119
    SWIG_exit(EXIT_FAILURE);
 
120
  }
 
121
 
 
122
  /* Fill in the new data */
 
123
  defined_foreign_types.entries[defined_foreign_types.count-1]=
 
124
    Copy(type);
 
125
  
 
126
}
 
127
 
 
128
 
 
129
static String *get_ffi_type(SwigType *ty, const String_or_char *name) {
 
130
  Hash *typemap = Swig_typemap_search("ffitype", ty, name, 0);
 
131
  if (typemap) {
 
132
          String *typespec = Getattr(typemap, "code");
 
133
          return NewString(typespec);
 
134
  }
 
135
  else {
 
136
          SwigType *tr=SwigType_typedef_resolve_all(ty);
 
137
          char *type_reduced=Char(tr);
 
138
          int i;
 
139
 
 
140
          //Printf(stdout,"convert_type %s\n", ty);
 
141
          if (SwigType_isconst(tr)) {
 
142
                  SwigType_pop(tr);
 
143
                  type_reduced=Char(tr);
 
144
          }
 
145
 
 
146
          if (SwigType_ispointer(type_reduced) || SwigType_isarray(ty) ||
 
147
              !strncmp(type_reduced, "p.f", 3)) {
 
148
                  return NewString(":pointer-void");
 
149
          }
 
150
  
 
151
          for(i=0; i<defined_foreign_types.count; i++) {
 
152
                  if (!Strcmp(ty, defined_foreign_types.entries[i])) {
 
153
                          return NewStringf("#.(%s \"%s\" :type :type)",
 
154
                                            identifier_converter, 
 
155
                                            ty);
 
156
                  }
 
157
          }
 
158
  
 
159
          if (!Strncmp(type_reduced, "enum ", 5)) {
 
160
                  return NewString(":int");
 
161
          }
 
162
 
 
163
          Printf(stderr, "Unsupported data type: %s (was: %s)\n", type_reduced, ty);
 
164
          SWIG_exit(EXIT_FAILURE);
 
165
  }
 
166
  return 0;
 
167
}
 
168
 
 
169
static String *get_lisp_type(SwigType *ty, const String_or_char *name)
 
170
{
 
171
  Hash *typemap = Swig_typemap_search("lisptype", ty, name, 0);
 
172
  if (typemap) {
 
173
    String *typespec = Getattr(typemap, "code");
 
174
    return NewString(typespec);
 
175
  }
 
176
  else {
 
177
    return NewString("");
 
178
  }
 
179
}
 
180
 
 
181
void UFFI :: main(int argc, char *argv[]) {
 
182
  int i;
 
183
 
 
184
  SWIG_library_directory("uffi"); 
 
185
  SWIG_config_file("uffi.swg");
 
186
 
 
187
 
 
188
  for(i=1; i<argc; i++) {
 
189
    if (!strcmp(argv[i], "-identifier-converter")) {
 
190
      char *conv=argv[i+1];
 
191
      
 
192
      if (!conv)
 
193
        Swig_arg_error();
 
194
 
 
195
      Swig_mark_arg(i);
 
196
      Swig_mark_arg(i+1);
 
197
      i++;
 
198
 
 
199
      /* check for built-ins */
 
200
      if (!strcmp(conv, "lispify")) {
 
201
        identifier_converter="identifier-convert-lispify";
 
202
      } else if (!strcmp(conv, "null")) {
 
203
        identifier_converter="identifier-convert-null";
 
204
      } else {
 
205
        /* Must be user defined */
 
206
        char *idconv = new char[strlen(conv)+1];
 
207
        strcpy(idconv, conv);
 
208
        identifier_converter=idconv;
 
209
      }
 
210
    }
 
211
 
 
212
    if (!strcmp(argv[i], "-help")) {
 
213
      fprintf(stdout, "UFFI Options (available with -uffi)\n");
 
214
      fprintf(stdout, 
 
215
              "    -identifier-converter <type or funcname>\n"
 
216
              "\tSpecifies the type of conversion to do on C identifiers to convert\n"
 
217
              "\tthem to symbols.  There are two built-in converters:  'null' and\n"
 
218
              "\t 'lispify'.  The default is 'null'.  If you supply a name other\n"
 
219
              "\tthan one of the built-ins, then a function by that name will be\n"
 
220
              "\tcalled to convert identifiers to symbols.\n");
 
221
 
 
222
    }
 
223
      
 
224
  }
 
225
      
 
226
  
 
227
}
 
228
 
 
229
int UFFI :: top(Node *n) {
 
230
  String *module=Getattr(n, "name");
 
231
  String *output_filename=NewString("");
 
232
  String *devnull=NewString("/dev/null");
 
233
 
 
234
  f_null=NewFile(devnull, "w+");
 
235
  if (!f_null) {
 
236
          FileErrorDisplay(devnull);
 
237
          SWIG_exit(EXIT_FAILURE);
 
238
  }
 
239
  Delete(devnull);
 
240
 
 
241
 
 
242
  Printf(output_filename, "%s%s.cl", SWIG_output_directory(), module);
 
243
 
 
244
 
 
245
  f_cl=NewFile(output_filename, "w");
 
246
  if (!f_cl) {
 
247
    FileErrorDisplay(output_filename);
 
248
    SWIG_exit(EXIT_FAILURE);
 
249
  }
 
250
 
 
251
  Swig_register_filebyname("header",f_null);
 
252
  Swig_register_filebyname("runtime",f_null);
 
253
  Swig_register_filebyname("wrapper", f_cl);
 
254
 
 
255
  Printf(f_cl, ";; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; package: %s -*-\n;; This is an automatically generated file.  Make changes in\n;; the definition file, not here.\n\n(defpackage :%s\n  (:use :common-lisp :uffi))\n\n(in-package :%s)\n", module, module, module);
 
256
  Printf(f_cl, "(eval-when (compile load eval)\n  (defparameter *swig-identifier-converter* '%s))\n", identifier_converter);
 
257
  
 
258
  Language::top(n);
 
259
 
 
260
  Close(f_cl);
 
261
  Delete(f_cl); // Delete the handle, not the file
 
262
  Close(f_null);
 
263
  Delete(f_null);
 
264
  
 
265
  return SWIG_OK;
 
266
}
 
267
 
 
268
int UFFI :: functionWrapper(Node *n) {
 
269
  String *funcname=Getattr(n, "sym:name");
 
270
  ParmList *pl=Getattr(n, "parms");
 
271
  Parm *p;
 
272
  int argnum=0, first=1, varargs=0;
 
273
  
 
274
  //Language::functionWrapper(n);
 
275
 
 
276
  Printf(f_cl, "(swig-defun \"%s\"\n", funcname);
 
277
  Printf(f_cl, "  (");
 
278
 
 
279
  /* Special cases */
 
280
  
 
281
  if (ParmList_len(pl) == 0) {
 
282
    Printf(f_cl, ":void");
 
283
  } else if (any_varargs(pl)) {
 
284
    Printf(f_cl, "#| varargs |#");
 
285
    varargs=1;
 
286
  } else {
 
287
    for (p=pl; p; p=nextSibling(p), argnum++) {
 
288
      String *argname=Getattr(p, "name");
 
289
      SwigType *argtype=Getattr(p, "type");
 
290
      String *ffitype=get_ffi_type(argtype, argname);
 
291
      String *lisptype=get_lisp_type(argtype, argname);
 
292
      int tempargname=0;
 
293
      
 
294
      if (!argname) {
 
295
        argname=NewStringf("arg%d", argnum);
 
296
        tempargname=1;
 
297
      }
 
298
      
 
299
      if (!first) {
 
300
        Printf(f_cl, "\n   ");
 
301
      }
 
302
      Printf(f_cl, "(%s %s %s)", argname, ffitype, lisptype);
 
303
      first=0;
 
304
      
 
305
      Delete(ffitype);
 
306
      Delete(lisptype);
 
307
      if (tempargname) 
 
308
        Delete(argname);
 
309
      
 
310
    }
 
311
  }
 
312
  Printf(f_cl, ")\n"); /* finish arg list */
 
313
  Printf(f_cl, "  :returning %s\n"
 
314
         //"  :strings-convert t\n"
 
315
         //"  :call-direct %s\n"
 
316
         //"  :optimize-for-space t"
 
317
         ")\n", 
 
318
         get_ffi_type(Getattr(n, "type"), "result")
 
319
         //,varargs ? "nil"  : "t"
 
320
         );
 
321
 
 
322
  
 
323
  return SWIG_OK;
 
324
}
 
325
 
 
326
int UFFI :: constantWrapper(Node *n) {
 
327
  String *type=Getattr(n, "type");
 
328
  String *converted_value=convert_literal(Getattr(n, "value"), type);
 
329
  String *name=Getattr(n, "sym:name");
 
330
 
 
331
#if 0
 
332
  Printf(stdout, "constant %s is of type %s. value: %s\n",
 
333
         name, type, converted_value);
 
334
#endif
 
335
 
 
336
  Printf(f_cl, "(swig-defconstant \"%s\" %s)\n",
 
337
         name, converted_value);
 
338
 
 
339
  Delete(converted_value);
 
340
 
 
341
  return SWIG_OK;
 
342
}
 
343
 
 
344
// Includes structs
 
345
int UFFI :: classHandler(Node *n) {
 
346
 
 
347
  String *name=Getattr(n, "sym:name");
 
348
  String *kind = Getattr(n,"kind");
 
349
  Node *c;
 
350
  
 
351
  if (Strcmp(kind, "struct")) {
 
352
    Printf(stderr, "Don't know how to deal with %s kind of class yet.\n",
 
353
           kind);
 
354
    Printf(stderr, " (name: %s)\n", name);
 
355
    SWIG_exit(EXIT_FAILURE);
 
356
  }
 
357
 
 
358
  Printf(f_cl, 
 
359
         "(swig-def-struct \"%s\"\n \n", 
 
360
         name);
 
361
 
 
362
  for (c=firstChild(n); c; c=nextSibling(c)) {
 
363
    SwigType *type=Getattr(c, "type");
 
364
    SwigType *decl=Getattr(c, "decl");
 
365
    type = Copy(type);
 
366
    SwigType_push(type, decl);
 
367
    String *lisp_type;
 
368
 
 
369
    if (Strcmp(nodeType(c), "cdecl")) {
 
370
      Printf(stderr, "Structure %s has a slot that we can't deal with.\n",
 
371
             name);
 
372
      Printf(stderr, "nodeType: %s, name: %s, type: %s\n", 
 
373
             nodeType(c),
 
374
             Getattr(c, "name"),
 
375
             Getattr(c, "type"));
 
376
      SWIG_exit(EXIT_FAILURE);
 
377
    }
 
378
 
 
379
    
 
380
    /* Printf(stdout, "Converting %s in %s\n", type, name); */
 
381
    lisp_type=get_ffi_type(type, Getattr(c, "sym:name"));
 
382
 
 
383
    Printf(f_cl, 
 
384
           "  (#.(%s \"%s\" :type :slot) %s)\n", 
 
385
           identifier_converter,
 
386
           Getattr(c, "sym:name"), 
 
387
           lisp_type);
 
388
 
 
389
    Delete(lisp_type);
 
390
  }
 
391
 
 
392
  // Language::classHandler(n);
 
393
  
 
394
  Printf(f_cl, " )\n");
 
395
 
 
396
  /* Add this structure to the known lisp types */
 
397
  //Printf(stdout, "Adding %s foreign type\n", name);
 
398
  add_defined_foreign_type(name);
 
399
  
 
400
  return SWIG_OK;
 
401
}
 
402
 
 
403
int UFFI :: membervariableHandler(Node *n)
 
404
{
 
405
  Language::membervariableHandler(n);
 
406
  return SWIG_OK;
 
407
}
 
408
 
 
409
 
 
410
extern "C" Language *swig_uffi(void) {
 
411
  return new UFFI();
 
412
}
 
413
 
 
414
 
 
415
 
 
416