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 12char cvsroot_wrapfunc_c[] = "$Id: wrapfunc.c 11080 2009-01-24 13:15:51Z bhy $"; 13 14#include "swig.h" 15#include <ctype.h> 16 17static int Compact_mode = 0; /* set to 0 on default */ 18static int Max_line_size = 128; 19 20/* ----------------------------------------------------------------------------- 21 * NewWrapper() 22 * 23 * Create a new wrapper function object. 24 * ----------------------------------------------------------------------------- */ 25 26Wrapper *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 42void 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 56void 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 66void 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 211void 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 387void 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 409int 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 427int 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 454int 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 468char *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 499char *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} 519