import source from 1.3.40
[external/swig.git] / Source / Swig / wrapfunc.c
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.
4  *
5  * wrapfunc.c
6  *
7  * This file defines a object for creating wrapper functions.  Primarily
8  * this is used for convenience since it allows pieces of a wrapper function
9  * to be created in a piecemeal manner.
10  * ----------------------------------------------------------------------------- */
11
12 char cvsroot_wrapfunc_c[] = "$Id: wrapfunc.c 11080 2009-01-24 13:15:51Z bhy $";
13
14 #include "swig.h"
15 #include <ctype.h>
16
17 static int Compact_mode = 0;    /* set to 0 on default */
18 static int Max_line_size = 128;
19
20 /* -----------------------------------------------------------------------------
21  * NewWrapper()
22  *
23  * Create a new wrapper function object.
24  * ----------------------------------------------------------------------------- */
25
26 Wrapper *NewWrapper(void) {
27   Wrapper *w;
28   w = (Wrapper *) malloc(sizeof(Wrapper));
29   w->localh = NewHash();
30   w->locals = NewStringEmpty();
31   w->code = NewStringEmpty();
32   w->def = NewStringEmpty();
33   return w;
34 }
35
36 /* -----------------------------------------------------------------------------
37  * DelWrapper()
38  *
39  * Delete a wrapper function object.
40  * ----------------------------------------------------------------------------- */
41
42 void DelWrapper(Wrapper *w) {
43   Delete(w->localh);
44   Delete(w->locals);
45   Delete(w->code);
46   Delete(w->def);
47   free(w);
48 }
49
50 /* -----------------------------------------------------------------------------
51  * Wrapper_compact_print_mode_set()
52  *
53  * Set compact_mode.
54  * ----------------------------------------------------------------------------- */
55
56 void Wrapper_compact_print_mode_set(int flag) {
57   Compact_mode = flag;
58 }
59
60 /* -----------------------------------------------------------------------------
61  * Wrapper_pretty_print()
62  *
63  * Formats a wrapper function and fixes up the indentation.
64  * ----------------------------------------------------------------------------- */
65
66 void Wrapper_pretty_print(String *str, File *f) {
67   String *ts;
68   int level = 0;
69   int c, i;
70   int empty = 1;
71   int indent = 2;
72   int plevel = 0;
73   int label = 0;
74
75   ts = NewStringEmpty();
76   Seek(str, 0, SEEK_SET);
77   while ((c = Getc(str)) != EOF) {
78     if (c == '\"') {
79       Putc(c, ts);
80       while ((c = Getc(str)) != EOF) {
81         if (c == '\\') {
82           Putc(c, ts);
83           c = Getc(str);
84         }
85         Putc(c, ts);
86         if (c == '\"')
87           break;
88       }
89       empty = 0;
90     } else if (c == '\'') {
91       Putc(c, ts);
92       while ((c = Getc(str)) != EOF) {
93         if (c == '\\') {
94           Putc(c, ts);
95           c = Getc(str);
96         }
97         Putc(c, ts);
98         if (c == '\'')
99           break;
100       }
101       empty = 0;
102     } else if (c == ':') {
103       Putc(c, ts);
104       if ((c = Getc(str)) == '\n') {
105         if (!empty && !strchr(Char(ts), '?'))
106           label = 1;
107       }
108       Ungetc(c, str);
109     } else if (c == '(') {
110       Putc(c, ts);
111       plevel += indent;
112       empty = 0;
113     } else if (c == ')') {
114       Putc(c, ts);
115       plevel -= indent;
116       empty = 0;
117     } else if (c == '{') {
118       Putc(c, ts);
119       Putc('\n', ts);
120       for (i = 0; i < level; i++)
121         Putc(' ', f);
122       Printf(f, "%s", ts);
123       Clear(ts);
124       level += indent;
125       while ((c = Getc(str)) != EOF) {
126         if (!isspace(c)) {
127           Ungetc(c, str);
128           break;
129         }
130       }
131       empty = 0;
132     } else if (c == '}') {
133       if (!empty) {
134         Putc('\n', ts);
135         for (i = 0; i < level; i++)
136           Putc(' ', f);
137         Printf(f, "%s", ts);
138         Clear(ts);
139       }
140       level -= indent;
141       Putc(c, ts);
142       empty = 0;
143     } else if (c == '\n') {
144       Putc(c, ts);
145       empty = 0;
146       if (!empty) {
147         int slevel = level;
148         if (label && (slevel >= indent))
149           slevel -= indent;
150         if ((Char(ts))[0] != '#') {
151           for (i = 0; i < slevel; i++)
152             Putc(' ', f);
153         }
154         Printf(f, "%s", ts);
155         for (i = 0; i < plevel; i++)
156           Putc(' ', f);
157       }
158       Clear(ts);
159       label = 0;
160       empty = 1;
161     } else if (c == '/') {
162       empty = 0;
163       Putc(c, ts);
164       c = Getc(str);
165       if (c != EOF) {
166         Putc(c, ts);
167         if (c == '/') {         /* C++ comment */
168           while ((c = Getc(str)) != EOF) {
169             if (c == '\n') {
170               Ungetc(c, str);
171               break;
172             }
173             Putc(c, ts);
174           }
175         } else if (c == '*') {  /* C comment */
176           int endstar = 0;
177           while ((c = Getc(str)) != EOF) {
178             if (endstar && c == '/') {  /* end of C comment */
179               Putc(c, ts);
180               break;
181             }
182             endstar = (c == '*');
183             Putc(c, ts);
184             if (c == '\n') {    /* multi-line C comment. Could be improved slightly. */
185               for (i = 0; i < level; i++)
186                 Putc(' ', ts);
187             }
188           }
189         }
190       }
191     } else {
192       if (!empty || !isspace(c)) {
193         Putc(c, ts);
194         empty = 0;
195       }
196     }
197   }
198   if (!empty)
199     Printf(f, "%s", ts);
200   Delete(ts);
201   Printf(f, "\n");
202 }
203
204 /* -----------------------------------------------------------------------------
205  * Wrapper_compact_print()
206  *
207  * Formats a wrapper function and fixes up the indentation.
208  * Print out in compact format, with Compact enabled.
209  * ----------------------------------------------------------------------------- */
210
211 void Wrapper_compact_print(String *str, File *f) {
212   String *ts, *tf;              /*temp string & temp file */
213   int level = 0;
214   int c, i;
215   int empty = 1;
216   int indent = 2;
217
218   ts = NewStringEmpty();
219   tf = NewStringEmpty();
220   Seek(str, 0, SEEK_SET);
221
222   while ((c = Getc(str)) != EOF) {
223     if (c == '\"') {            /* string 1 */
224       empty = 0;
225       Putc(c, ts);
226       while ((c = Getc(str)) != EOF) {
227         if (c == '\\') {
228           Putc(c, ts);
229           c = Getc(str);
230         }
231         Putc(c, ts);
232         if (c == '\"')
233           break;
234       }
235     } else if (c == '\'') {     /* string 2 */
236       empty = 0;
237       Putc(c, ts);
238       while ((c = Getc(str)) != EOF) {
239         if (c == '\\') {
240           Putc(c, ts);
241           c = Getc(str);
242         }
243         Putc(c, ts);
244         if (c == '\'')
245           break;
246       }
247     } else if (c == '{') {      /* start of {...} */
248       empty = 0;
249       Putc(c, ts);
250       if (Len(tf) == 0) {
251         for (i = 0; i < level; i++)
252           Putc(' ', tf);
253       } else if ((Len(tf) + Len(ts)) < Max_line_size) {
254         Putc(' ', tf);
255       } else {
256         Putc('\n', tf);
257         Printf(f, "%s", tf);
258         Clear(tf);
259         for (i = 0; i < level; i++)
260           Putc(' ', tf);
261       }
262       Append(tf, ts);
263       Clear(ts);
264       level += indent;
265       while ((c = Getc(str)) != EOF) {
266         if (!isspace(c)) {
267           Ungetc(c, str);
268           break;
269         }
270       }
271     } else if (c == '}') {      /* end of {...} */
272       empty = 0;
273       if (Len(tf) == 0) {
274         for (i = 0; i < level; i++)
275           Putc(' ', tf);
276       } else if ((Len(tf) + Len(ts)) < Max_line_size) {
277         Putc(' ', tf);
278       } else {
279         Putc('\n', tf);
280         Printf(f, "%s", tf);
281         Clear(tf);
282         for (i = 0; i < level; i++)
283           Putc(' ', tf);
284       }
285       Append(tf, ts);
286       Putc(c, tf);
287       Clear(ts);
288       level -= indent;
289     } else if (c == '\n') {     /* line end */
290       while ((c = Getc(str)) != EOF) {
291         if (!isspace(c))
292           break;
293       }
294       if (c == '#') {
295         Putc('\n', ts);
296       } else if (c == '}') {
297         Putc(' ', ts);
298       } else if ((c != EOF) || (Len(ts) != 0)) {
299         if (Len(tf) == 0) {
300           for (i = 0; i < level; i++)
301             Putc(' ', tf);
302         } else if ((Len(tf) + Len(ts)) < Max_line_size) {
303           Putc(' ', tf);
304         } else {
305           Putc('\n', tf);
306           Printf(f, "%s", tf);
307           Clear(tf);
308           for (i = 0; i < level; i++)
309             Putc(' ', tf);
310         }
311         Append(tf, ts);
312         Clear(ts);
313       }
314       Ungetc(c, str);
315
316       empty = 1;
317     } else if (c == '/') {      /* comment */
318       empty = 0;
319       c = Getc(str);
320       if (c != EOF) {
321         if (c == '/') {         /* C++ comment */
322           while ((c = Getc(str)) != EOF) {
323             if (c == '\n') {
324               Ungetc(c, str);
325               break;
326             }
327           }
328         } else if (c == '*') {  /* C comment */
329           int endstar = 0;
330           while ((c = Getc(str)) != EOF) {
331             if (endstar && c == '/') {  /* end of C comment */
332               break;
333             }
334             endstar = (c == '*');
335           }
336         } else {
337           Putc('/', ts);
338           Putc(c, ts);
339         }
340       }
341     } else if (c == '#') {      /* Preprocessor line */
342       Putc('#', ts);
343       while ((c = Getc(str)) != EOF) {
344         Putc(c, ts);
345         if (c == '\\') {        /* Continued line of the same PP */
346           c = Getc(str);
347           if (c == '\n')
348             Putc(c, ts);
349           else
350             Ungetc(c, str);
351         } else if (c == '\n')
352           break;
353       }
354       if (!empty) {
355         Append(tf, "\n");
356       }
357       Append(tf, ts);
358       Printf(f, "%s", tf);
359       Clear(tf);
360       Clear(ts);
361       for (i = 0; i < level; i++)
362         Putc(' ', tf);
363       empty = 1;
364     } else {
365       if (!empty || !isspace(c)) {
366         Putc(c, ts);
367         empty = 0;
368       }
369     }
370   }
371   if (!empty) {
372     Append(tf, ts);
373   }
374   if (Len(tf) != 0)
375     Printf(f, "%s", tf);
376   Delete(ts);
377   Delete(tf);
378   Printf(f, "\n");
379 }
380
381 /* -----------------------------------------------------------------------------
382  * Wrapper_print()
383  *
384  * Print out a wrapper function.  Does pretty or compact printing as well.
385  * ----------------------------------------------------------------------------- */
386
387 void Wrapper_print(Wrapper *w, File *f) {
388   String *str;
389
390   str = NewStringEmpty();
391   Printf(str, "%s\n", w->def);
392   Printf(str, "%s\n", w->locals);
393   Printf(str, "%s\n", w->code);
394   if (Compact_mode == 1)
395     Wrapper_compact_print(str, f);
396   else
397     Wrapper_pretty_print(str, f);
398
399   Delete(str);
400 }
401
402 /* -----------------------------------------------------------------------------
403  * Wrapper_add_local()
404  *
405  * Adds a new local variable declaration to a function. Returns -1 if already
406  * present (which may or may not be okay to the caller).
407  * ----------------------------------------------------------------------------- */
408
409 int Wrapper_add_local(Wrapper *w, const_String_or_char_ptr name, const_String_or_char_ptr decl) {
410   /* See if the local has already been declared */
411   if (Getattr(w->localh, name)) {
412     return -1;
413   }
414   Setattr(w->localh, name, decl);
415   Printf(w->locals, "%s;\n", decl);
416   return 0;
417 }
418
419 /* -----------------------------------------------------------------------------
420  * Wrapper_add_localv()
421  *
422  * Same as add_local(), but allows a NULL terminated list of strings to be
423  * used as a replacement for decl.   This saves the caller the trouble of having
424  * to manually construct the 'decl' string before calling.
425  * ----------------------------------------------------------------------------- */
426
427 int Wrapper_add_localv(Wrapper *w, const_String_or_char_ptr name, ...) {
428   va_list ap;
429   int ret;
430   String *decl;
431   DOH *obj;
432   decl = NewStringEmpty();
433   va_start(ap, name);
434
435   obj = va_arg(ap, void *);
436   while (obj) {
437     Append(decl, obj);
438     Putc(' ', decl);
439     obj = va_arg(ap, void *);
440   }
441   va_end(ap);
442
443   ret = Wrapper_add_local(w, name, decl);
444   Delete(decl);
445   return ret;
446 }
447
448 /* -----------------------------------------------------------------------------
449  * Wrapper_check_local()
450  *
451  * Check to see if a local name has already been declared
452  * ----------------------------------------------------------------------------- */
453
454 int Wrapper_check_local(Wrapper *w, const_String_or_char_ptr name) {
455   if (Getattr(w->localh, name)) {
456     return 1;
457   }
458   return 0;
459 }
460
461 /* ----------------------------------------------------------------------------- 
462  * Wrapper_new_local()
463  *
464  * Adds a new local variable with a guarantee that a unique local name will be
465  * used.  Returns the name that was actually selected.
466  * ----------------------------------------------------------------------------- */
467
468 char *Wrapper_new_local(Wrapper *w, const_String_or_char_ptr name, const_String_or_char_ptr decl) {
469   int i;
470   String *nname = NewString(name);
471   String *ndecl = NewString(decl);
472   char *ret;
473
474   i = 0;
475
476   while (Wrapper_check_local(w, nname)) {
477     Clear(nname);
478     Printf(nname, "%s%d", name, i);
479     i++;
480   }
481   Replace(ndecl, name, nname, DOH_REPLACE_ID);
482   Setattr(w->localh, nname, ndecl);
483   Printf(w->locals, "%s;\n", ndecl);
484   ret = Char(nname);
485   Delete(nname);
486   Delete(ndecl);
487   return ret;                   /* Note: nname should still exists in the w->localh hash */
488 }
489
490
491 /* -----------------------------------------------------------------------------
492  * Wrapper_new_localv()
493  *
494  * Same as add_local(), but allows a NULL terminated list of strings to be
495  * used as a replacement for decl.   This saves the caller the trouble of having
496  * to manually construct the 'decl' string before calling.
497  * ----------------------------------------------------------------------------- */
498
499 char *Wrapper_new_localv(Wrapper *w, const_String_or_char_ptr name, ...) {
500   va_list ap;
501   char *ret;
502   String *decl;
503   DOH *obj;
504   decl = NewStringEmpty();
505   va_start(ap, name);
506
507   obj = va_arg(ap, void *);
508   while (obj) {
509     Append(decl, obj);
510     Putc(' ', decl);
511     obj = va_arg(ap, void *);
512   }
513   va_end(ap);
514
515   ret = Wrapper_new_local(w, name, decl);
516   Delete(decl);
517   return ret;
518 }