1 /***************************************************************************
2 dia2code.c - Global functions
3 -------------------
4 begin : Sat Dec 16 2000
5 copyright : (C) 2000-2001 by Javier O'Hara
6 email : joh314@users.sourceforge.net
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include "dia2code.h"
19 #include <errno.h>
20
21 char * d2c_indentstring = " ";
22 int d2c_indentposition = 0;
23
24 int indentlevel = 0;
25 static int number_of_spaces_for_one_indentation = 2;
26 static int DBG_LEVEL = 4;
27
dia2code_initializations()28 void dia2code_initializations()
29 {
30 }
31
debug_setlevel(int newlevel)32 void debug_setlevel( int newlevel )
33 {
34 DBG_LEVEL = newlevel;
35 }
36
37 /*
38 * a dummy logger / debugger function
39 */
debug(int level,char * fmt,...)40 void debug( int level, char *fmt, ... )
41 {
42 static char debug_buffer[HUGE_BUFFER];
43 va_list argptr;
44 //printf( "debug call\n" );
45 if( level != DBG_LEVEL )
46 return;
47 va_start(argptr, fmt);
48 vsprintf(debug_buffer, fmt, argptr);
49 va_end(argptr);
50 fprintf( stderr, "DBG %d: %s\n", level, debug_buffer );
51 fflush( stderr);
52 //printf( "END debug call\n" );
53 }
54
55 /**
56 * This function returns the upper case char* of the one taken on input
57 * The char * received may be freed by the caller
58 */
strtoupper(char * s)59 char *strtoupper(char *s) {
60 char *tmp = strdup(s);
61 int i, n;
62 if (tmp == NULL) {
63 fprintf(stderr, "Out of memory\n");
64 exit(1);
65 }
66 n = strlen(tmp);
67 for (i = 0; i < n; i++) {
68 tmp[i] = toupper(tmp[i]);
69 }
70 return tmp;
71 }
72
73 /**
74 * This function returns the lower case char* of the one taken on input
75 * The char * received may be freed by the caller
76 */
strtolower(char * s)77 char *strtolower(char *s) {
78 char *tmp = strdup(s);
79 int i, n;
80 if (tmp == NULL) {
81 fprintf(stderr, "Out of memory\n");
82 exit(1);
83 }
84 n = strlen(tmp);
85 for (i = 0; i < n; i++) {
86 tmp[i] = tolower(tmp[i]);
87 }
88 return tmp;
89 }
90
91 /**
92 * This function returns the a char* that has the first
93 * character in upper case and the rest unchanged.
94 * The char * received may be freed by the caller
95 */
strtoupperfirst(char * s)96 char *strtoupperfirst(char *s) {
97 char *tmp = strdup(s);
98 int i, n;
99 if (tmp == NULL) {
100 fprintf(stderr, "Out of memory\n");
101 exit(1);
102 }
103 n = strlen(tmp);
104 tmp[0] = toupper(tmp[0]);
105 for (i = 1; i < n; i++) {
106 tmp[i] = tmp[i];
107 }
108 return tmp;
109 }
110
111
parse_class_names(const char * s)112 namelist parse_class_names(const char *s) {
113 char *cp, *token;
114 const char *delim = ",";
115 namelist list = NULL;
116
117 cp = strdup(s);
118 if (cp == NULL) {
119 fprintf(stderr, "Out of memory\n");
120 exit(1);
121 }
122 token = strtok (cp, delim);
123 while ( token != NULL ) {
124 namenode *tmp = NEW (namenode);
125 if (tmp == NULL) {
126 fprintf(stderr, "Out of memory\n");
127 exit(1);
128 }
129 tmp->name = strdup(token);
130 if (tmp->name == NULL) {
131 fprintf(stderr, "Out of memory\n");
132 exit(1);
133 }
134 tmp->next = list;
135 list = tmp;
136 token = strtok (NULL, delim);
137 }
138 free(cp);
139 return list;
140 }
141
parse_sql_options(const char * s)142 namelist parse_sql_options(const char *s) {
143 /* AI: same thing for now but it could change in the future */
144 return parse_class_names(s);
145 }
146
is_present(namelist list,const char * name)147 int is_present(namelist list, const char *name) {
148 while (list != NULL) {
149 int len;
150 char* mask;
151 if ( ! strcmp(list->name, name) ) {
152 return 1;
153 }
154 len = strlen(list->name);
155 if (len >= 2 && len <= strlen(name)
156 && (mask = strchr(list->name, '*')) != NULL
157 && mask == strrchr(list->name, '*') ) {
158 len--;
159 if ( mask == list->name && ! strcmp(list->name+1, name+strlen(name)-len) ) {
160 return 1;
161 }
162 if ( mask == list->name+len && ! strncmp(list->name, name, len) ) {
163 return 1;
164 }
165 }
166 list = list->next;
167 }
168 return 0;
169 }
170
my_malloc(size_t size)171 void * my_malloc( size_t size ) {
172 void * tmp;
173 tmp = malloc(size);
174 if (tmp == NULL) {
175 fprintf(stderr, "Out of memory\n");
176 exit(1);
177 }
178 /* safer zone */
179 memset (tmp, 0, size);
180 return tmp;
181 }
182
183
184 /*
185 Builds a package list from the hierarchy of parents of package.
186 The topmost package will be the first on the list and the initial
187 package will be the last.
188 */
make_package_list(umlpackage * package)189 umlpackagelist make_package_list(umlpackage * package){
190 umlpackagelist dummylist, tmplist=NULL;
191
192 while ( package != NULL ){
193 dummylist = NEW (umlpackagenode);
194 dummylist->next = tmplist;
195 tmplist = dummylist;
196 tmplist->key = package;
197 package = package->parent;
198 }
199 return tmplist;
200 }
201
copy_attributes(umlattrlist src)202 umlattrlist copy_attributes(umlattrlist src)
203 {
204 umlattrlist cpy = NULL, start = NULL;
205
206 while (src != NULL)
207 {
208 umlattrlist tmp = NEW (umlattrnode);
209 tmp->key = src->key;
210 if (cpy == NULL) {
211 cpy = tmp;
212 start = tmp;
213 } else {
214 cpy->next = tmp;
215 cpy = tmp;
216 }
217 src = src->next;
218 }
219 if (cpy != NULL)
220 cpy->next = NULL;
221
222 return start;
223 }
224
225
226 /**
227 * create a directory hierarchy for the package name
228 * batch.outdir is taken as root directory
229 * works with java-like package naming convention
230 * the directory path is stored in pkg->directory
231 * eg. org.foo.bar will create directory tree org/foo/bar
232 * @param the current batch
233 * @param the package pointer
234 * @return the full directory path eg. "<outdir>/org/foo/bar"
235 *
236 */
create_package_dir(const batch * batch,umlpackage * pkg)237 char *create_package_dir( const batch *batch, umlpackage *pkg )
238 {
239 char *fulldirname, *dirname, fulldirnamedup[BIG_BUFFER];
240 /* created directories permissions */
241 mode_t dir_mask = S_IRUSR | S_IWUSR | S_IXUSR |S_IRGRP | S_IXGRP;
242 if (pkg == NULL) {
243 return NULL;
244 }
245 if (batch->buildtree == 0 || pkg->name == NULL) {
246 pkg->directory = batch->outdir;
247 } else {
248 fulldirname = (char*)my_malloc(BIG_BUFFER);
249 sprintf(fulldirname, "%s", batch->outdir);
250 dirname = strdup(pkg->name);
251 dirname = strtok( dirname, "." );
252 while (dirname != NULL) {
253 sprintf( fulldirnamedup, "%s/%s", fulldirname, dirname );
254 sprintf( fulldirname, "%s", fulldirnamedup );
255 /* TODO : should create only if not existent */
256 mkdir( fulldirname, dir_mask );
257 dirname = strtok( NULL, "." );
258 }
259 /* set the package directory used later for source file creation */
260 pkg->directory = fulldirname;
261 }
262 return pkg->directory;
263 }
264
set_number_of_spaces_for_one_indentation(int n)265 void set_number_of_spaces_for_one_indentation(int n)
266 {
267 number_of_spaces_for_one_indentation = n;
268 }
269
spc()270 char *spc()
271 {
272 static char spcbuf[BIG_BUFFER];
273 int n_spaces = number_of_spaces_for_one_indentation * indentlevel;
274 if (n_spaces >= sizeof(spcbuf)) {
275 fprintf (stderr, "spc(): spaces buffer overflow\n");
276 exit (1);
277 }
278 memset (spcbuf, ' ', n_spaces);
279 spcbuf[n_spaces] = '\0';
280 return spcbuf;
281 }
282
283 FILE *spec = NULL, *body = NULL;
284
285 /* Auxiliary define for the emit/print functions */
286 #define var_arg_to_str(first_arg) \
287 va_list vargu; \
288 char str[LARGE_BUFFER]; \
289 va_start (vargu, first_arg); \
290 vsnprintf (str, LARGE_BUFFER, first_arg, vargu); \
291 va_end (vargu)
292
emit(char * msg,...)293 void emit (char *msg, ...)
294 {
295 var_arg_to_str (msg);
296 fputs (str, spec);
297 }
298
ebody(char * msg,...)299 void ebody (char *msg, ...)
300 {
301 var_arg_to_str (msg);
302 if (body != NULL)
303 fputs (str, body);
304 }
305
eboth(char * msg,...)306 void eboth (char *msg, ...)
307 {
308 var_arg_to_str (msg);
309 fputs (str, spec);
310 if (body != NULL)
311 fputs (str, body);
312 }
313
314
print(char * msg,...)315 void print (char *msg, ...)
316 {
317 var_arg_to_str (msg);
318 fprintf (spec, "%s%s", spc(), str);
319 }
320
pbody(char * msg,...)321 void pbody (char *msg, ...)
322 {
323 var_arg_to_str (msg);
324 if (body != NULL)
325 fprintf (body, "%s%s", spc(), str);
326 }
327
pboth(char * msg,...)328 void pboth (char *msg, ...)
329 {
330 var_arg_to_str (msg);
331 fprintf (spec, "%s%s", spc(), str);
332 if (body != NULL)
333 fprintf (body, "%s%s", spc(), str);
334 }
335
336 char *file_ext = NULL;
337 char *body_file_ext = NULL;
338
open_outfile(char * filename,batch * b)339 FILE * open_outfile (char *filename, batch *b)
340 {
341 static char outfilename[BIG_BUFFER];
342 FILE *o;
343 int tmpdirlgth, tmpfilelgth;
344
345 if (b->outdir == NULL) {
346 b->outdir = ".";
347 }
348
349 tmpdirlgth = strlen (b->outdir);
350 tmpfilelgth = strlen (filename);
351
352 /* This prevents buffer overflows */
353 if (tmpfilelgth + tmpdirlgth > sizeof(outfilename) - 2) {
354 fprintf (stderr, "Sorry, name of file too long ...\n"
355 "Try a smaller dir name\n");
356 exit (1);
357 }
358
359 sprintf (outfilename, "%s/%s", b->outdir, filename);
360 o = fopen (outfilename, "r");
361 if (o != NULL && !b->clobber) {
362 fclose (o);
363 return NULL;
364 }
365 o = fopen (outfilename, "w");
366 if (o == NULL) {
367 fprintf (stderr, "Can't open file %s for writing\n", outfilename);
368 exit (1);
369 }
370 return o;
371 }
372
373
374 int
is_enum_stereo(char * stereo)375 is_enum_stereo (char *stereo)
376 {
377 return (!strcasecmp(stereo, "enum") ||
378 !strcasecmp (stereo, "enumeration") ||
379 !strcmp (stereo, "CORBAEnum"));
380 }
381
382 int
is_struct_stereo(char * stereo)383 is_struct_stereo (char *stereo)
384 {
385 return (!strcasecmp(stereo, "struct") ||
386 !strcasecmp (stereo, "structure") ||
387 !strcmp (stereo, "CORBAStruct"));
388 }
389
390 int
is_typedef_stereo(char * stereo)391 is_typedef_stereo (char *stereo)
392 {
393 return (!strcasecmp(stereo, "typedef") ||
394 !strcmp (stereo, "CORBATypedef"));
395 }
396
397 int
is_const_stereo(char * stereo)398 is_const_stereo (char *stereo)
399 {
400 return (!strcasecmp(stereo, "const") ||
401 !strcasecmp (stereo, "constant") ||
402 !strcmp (stereo, "CORBAConstant"));
403 }
404
405 /* Added by RK 2003-02-20
406 This should become part of the uml_class object. */
407
408 struct endless_string_buf
409 {
410 char *buf;
411 struct endless_string_buf *next;
412 };
413 typedef struct endless_string_buf endless_string_buf;
414
415 struct endless_string
416 {
417 endless_string_buf *start;
418 endless_string_buf *end;
419 };
420 typedef struct endless_string endless_string;
421
dump_endless_string(FILE * f,endless_string * es)422 void dump_endless_string(FILE *f, endless_string *es)
423 {
424 endless_string_buf *esb = es->start;
425 while (esb != NULL)
426 {
427 fprintf(f, "%s", esb->buf); /* We do not d2c_fprintf the buffer, cause it's read in indented. */
428 esb = esb->next;
429 }
430 }
431
new_endless_string()432 endless_string * new_endless_string()
433 {
434 endless_string *es = NEW (endless_string);
435 es->start = NULL;
436 es->end = NULL;
437 return es;
438 }
439
destroy_endless_string(endless_string * es)440 void destroy_endless_string(endless_string * es)
441 {
442 endless_string_buf *esb = es->start;
443 endless_string_buf *esb_next;
444 while (esb != NULL)
445 {
446 if (esb->buf != NULL)
447 free(esb->buf);
448 esb_next = esb->next;
449 free(esb);
450 esb = esb_next;
451 }
452 free (es);
453 }
454
append_endless_string(endless_string * es,char * s)455 void append_endless_string(endless_string * es, char *s)
456 {
457 endless_string_buf *esb = NEW (endless_string_buf);
458 esb->buf = strdup(s);
459 esb->next = NULL;
460 if (es->start == NULL)
461 es->start = esb;
462 if (es->end != NULL)
463 es->end->next = esb;
464 es->end = esb;
465 }
466
467 struct d2c_impl{
468 char name[SMALL_BUFFER];
469 endless_string *impl;
470 int impl_len;
471 int in_source;
472 int in_class;
473 struct d2c_impl *next;
474 };
475
476 typedef struct d2c_impl d2c_impl;
477 d2c_impl *d2c_impl_list = NULL;
478
d2c_impl_list_destroy()479 void d2c_impl_list_destroy()
480 {
481 d2c_impl *p = d2c_impl_list;
482 while (p != NULL)
483 {
484 destroy_endless_string(p->impl);
485 d2c_impl_list = p;
486 p = p->next;
487 free(d2c_impl_list);
488 }
489 d2c_impl_list = NULL;
490 }
491
d2c_impl_add(char * name)492 d2c_impl * d2c_impl_add(char *name)
493 {
494 d2c_impl *d2ci = NEW (d2c_impl);
495 strcpy(d2ci->name, name);
496 d2ci->impl = new_endless_string();
497 d2ci->impl_len = 0;
498 d2ci->in_source = 0;
499 d2ci->in_class = 0;
500 d2ci->next = d2c_impl_list;
501 d2c_impl_list = d2ci;
502
503 return d2ci;
504 }
505
d2c_impl_find(char * name)506 d2c_impl* d2c_impl_find(char *name)
507 {
508 d2c_impl *p = d2c_impl_list;
509 while (p != NULL)
510 {
511 if (strcmp(p->name, name) == 0)
512 return p;
513 p = p->next;
514 }
515 return NULL;
516 }
517
d2c_impl_find_or_add(char * name)518 d2c_impl *d2c_impl_find_or_add(char *name)
519 {
520 d2c_impl *p = d2c_impl_find(name);
521 if (p == NULL)
522 p = d2c_impl_add(name);
523
524 return p;
525 }
526
527 #define IMPLEMENTATION "Implementation"
528
d2c_impl_comment(FILE * f,char * nm,char * range,int preserve,char * comment_start,char * comment_end)529 void d2c_impl_comment(FILE *f, char *nm, char *range, int preserve, char *comment_start, char *comment_end)
530 {
531 d2c_fprintf(f, "%s ## %s %spreserve %s class %s %s\n",
532 comment_start, IMPLEMENTATION, preserve?"":"no", range, nm, comment_end);
533 }
534
535 #if defined (USE_DUMPIMPL)
d2c_dump_impl(FILE * f,char * section,char * name)536 void d2c_dump_impl(FILE *f, char *section, char *name)
537 {
538 char nm[LARGE_BUFFER];
539 d2c_impl *d2ci;
540
541 sprintf(nm, "%s.%s", section, name);
542 d2ci = d2c_impl_find_or_add(nm);
543
544 d2ci->in_class = 1;
545
546 d2c_impl_comment(f, nm, "start", 1, "//", "");
547 dump_endless_string(f, d2ci->impl);
548 d2c_impl_comment(f, nm, "end", 1, "//", "");
549 }
550 #else
d2c_dump_impl(FILE * f,char * section,char * name)551 void d2c_dump_impl(FILE *f, char *section, char *name)
552 {
553 }
554 #endif
555
d2c_deprecate_impl(FILE * f,char * comment_start,char * comment_end)556 void d2c_deprecate_impl(FILE *f, char *comment_start, char *comment_end)
557 {
558 d2c_impl *p = d2c_impl_list;
559 int cnt = 0;
560 endless_string_buf *esb;
561
562 while (p != NULL)
563 {
564 if (p->in_class == 0 && p->in_source == 1)
565 {
566 fprintf(stderr, "Deprecating implementation %s\n", p->name);
567
568 if (cnt == 0)
569 {
570 d2c_fprintf(f, "\n%s WARNING: %s\n", comment_start, comment_end);
571 d2c_fprintf(f, "%s The following code blocks will be deleted the next time code is generated. %s\n\n", comment_start, comment_end);
572 }
573 d2c_impl_comment(f, p->name, "start", 0, comment_start, comment_end);
574 esb = p->impl->start;
575 while (esb != NULL)
576 {
577 /* We do not d2c_fprintf the buffer, cause it's read in indented. */
578 fprintf(f, "// %s", esb->buf);
579 esb = esb->next;
580 }
581
582 d2c_impl_comment(f, p->name, "end", 0, comment_start, comment_end);
583 cnt++;
584 }
585 p = p->next;
586 }
587 if (cnt > 0)
588 fprintf(stderr, "Warning: %d implementation blocks have been deprecated; examime source files.\n", cnt);
589 }
590
sscanfmt(int size)591 static char *sscanfmt(int size)
592 {
593 static char buf[10];
594 sprintf (buf, " %%%ds", size - 1);
595 return buf;
596 }
597
d2c_parse_impl(FILE * f,char * cmt_start,char * cmt_end)598 void d2c_parse_impl(FILE *f, char *cmt_start, char *cmt_end)
599 {
600 #define IN_SOURCE 0
601 #define START_IMPL 1
602 #define IN_IMPL 2
603 #define END_IMPL 3
604
605 #define STATE_WARNING(s) fprintf(stderr, "Warning: line %ld %s, state=%d, %p, %s\n", line, (s), state, d2ci, ((d2ci != NULL) ? d2ci->name : "<no section>"));
606
607 char s[HUGE_BUFFER];
608 char s_comment[LARGE_BUFFER], s_dbl_hash[SMALL_BUFFER], s_implementation[BIG_BUFFER],
609 s_preserve[SMALL_BUFFER], s_marker[SMALL_BUFFER], s_class[LARGE_BUFFER], s_name[LARGE_BUFFER];
610 int state = IN_SOURCE;
611 int count;
612 d2c_impl *d2ci=NULL;
613 endless_string *es=NULL;
614 long line = 0;
615 int preserve=0;
616 char fmtbuf[SMALL_BUFFER];
617
618 d2c_impl_list_destroy();
619
620 while (fgets(s, HUGE_BUFFER - 1, f) != NULL)
621 {
622 line++;
623 if (state == START_IMPL) state = IN_IMPL;
624 if (state == END_IMPL) state = IN_SOURCE;
625 fmtbuf[0] = '\0';
626 strcat (fmtbuf, sscanfmt (sizeof(s_comment)));
627 strcat (fmtbuf, sscanfmt (sizeof(s_dbl_hash)));
628 strcat (fmtbuf, sscanfmt (sizeof(s_implementation)));
629 strcat (fmtbuf, sscanfmt (sizeof(s_preserve)));
630 strcat (fmtbuf, sscanfmt (sizeof(s_marker)));
631 strcat (fmtbuf, sscanfmt (sizeof(s_class)));
632 strcat (fmtbuf, sscanfmt (sizeof(s_name)));
633 count = sscanf(s, fmtbuf,
634 s_comment, s_dbl_hash, s_implementation, s_preserve, s_marker, s_class, s_name);
635 if (count == 7 &&
636 (strncmp(s_comment, cmt_start, sizeof(s_comment)) == 0) &&
637 (strncmp(s_dbl_hash, "##", sizeof(s_dbl_hash)) == 0) &&
638 (strncmp(s_implementation, IMPLEMENTATION, sizeof(s_implementation)) == 0))
639 {
640 if (strncmp(s_marker, "start", sizeof(s_marker)) == 0)
641 {
642 if (state != IN_SOURCE)
643 {
644 STATE_WARNING("found a nested implementation comment")
645 }
646 preserve = strcmp(s_preserve, "preserve") ? 0 : 1;
647 state = START_IMPL;
648 d2ci = d2c_impl_find_or_add(s_name);
649 es = d2ci->impl;
650 }
651 else if (strncmp(s_marker, "end", sizeof(s_marker)) == 0)
652 {
653 if (state != IN_IMPL)
654 {
655 STATE_WARNING("found an end implemenataion comment without matching start")
656 }
657 if (d2ci && strcmp(d2ci->name, s_name) != 0)
658 {
659 STATE_WARNING("end implementation comment does not match start implementation comment")
660 }
661 state = END_IMPL;
662 d2ci = NULL;
663 es = NULL;
664 }
665 else
666 {
667 STATE_WARNING("unrecognized state marker")
668 }
669 }
670
671 if (state == IN_IMPL && preserve)
672 {
673 append_endless_string(es, s);
674 d2ci->in_source= 1;
675 }
676 }
677 if (state != IN_SOURCE && state != END_IMPL)
678 STATE_WARNING("found start implementation comment without end comment")
679 }
680
681 /* This function takes a UML Operation and mangles it for implementation comments.
682 Because it uses an internal buffer to store and return, repeated calls to this
683 function will overwrite previous values.
684 */
d2c_operation_mangle_name(umloperation * ope)685 char *d2c_operation_mangle_name(umloperation *ope)
686 {
687 static char d2c_mangle_name[LARGE_BUFFER];
688 umlattrlist params = ope->parameters;
689 char *p;
690
691 sprintf(d2c_mangle_name, "%s@%s@@", ope->attr.name, ope->attr.type);
692 while (params != NULL)
693 {
694 strcat(d2c_mangle_name, "@");
695 strcat(d2c_mangle_name, params->key.type);
696 params = params->next;
697 }
698
699 /* Convert whitespace to underbars */
700 for (p = d2c_mangle_name; *p != '\0'; p++)
701 {
702 if (*p == ' ' || *p == '\t') *p = '_';
703 }
704 return d2c_mangle_name;
705 }
706
d2c_backup(char * filename)707 int d2c_backup(char *filename)
708 {
709 /* This is not necessarily portable. (requires ability to just
710 * tag-on four more characters - not DOS-friendly)
711 * But I'll admit to being a bit out-of-the loop here.
712 */
713 char *backup_filename = my_malloc(strlen(filename) + 4);
714 strcpy(backup_filename, filename);
715 strcat(backup_filename, ".bak");
716
717 if (generate_backup)
718 {
719 if (remove(backup_filename))
720 {
721 if (errno != ENOENT)
722 {
723 fprintf(stderr, "Error %d while trying to delete file %s\n", errno, backup_filename);
724 free(backup_filename);
725 return -1;
726 }
727 }
728 if (rename(filename, backup_filename))
729 {
730 if (errno != ENOENT)
731 {
732 fprintf(stderr, "Error %d while trying to rename %s to %s\n", errno, filename, backup_filename);
733 free(backup_filename);
734 return -1;
735 }
736 }
737 }
738 free(backup_filename);
739 return 0;
740 }
741
742 /* Todo on auto-indentation:
743 1. Define meta-characters that are converted to braces
744 */
745 int indent_count = 4;
746 int indent_open_brace_on_newline = 1;
747
748
749 typedef struct
750 {
751 FILE *f;
752 int indentation;
753 } D2C_INDENT_STRUCT;
754
755 D2C_INDENT_STRUCT d2c_files[32];
756 int d2c_num_files = 0;
757
d2c_indent_offset(FILE * f)758 int d2c_indent_offset(FILE *f)
759 {
760 int i;
761 for (i = 0; i < d2c_num_files; i++)
762 {
763 if (d2c_files[i].f == f)
764 {
765 return i;
766 }
767 }
768 d2c_files[i].f = f;
769 d2c_files[i].indentation = 0;
770 d2c_num_files++;
771 return i;
772 }
773
d2c_indent(FILE * f)774 void d2c_indent(FILE *f)
775 {
776 d2c_files[d2c_indent_offset(f)].indentation++;
777 }
778
d2c_outdent(FILE * f)779 void d2c_outdent(FILE *f)
780 {
781 d2c_files[d2c_indent_offset(f)].indentation--;
782 }
783
d2c_fprint_indent(FILE * f)784 int d2c_fprint_indent(FILE *f)
785 {
786 int i;
787 int indentation;
788
789 indentation = d2c_files[d2c_indent_offset(f)].indentation;
790
791 for (i = 0; i < indentation * indent_count; i++)
792 fputc(' ', f);
793 return i;
794 }
795
796 char d2c_io_lchar = 0;
797
_d2c_fputc(int c,FILE * f)798 int _d2c_fputc(int c, FILE *f)
799 {
800 int indent_cnt = 0;
801 int rc;
802
803 if (d2c_io_lchar == '\n' && c != '\n')
804 indent_cnt = d2c_fprint_indent(f);
805 d2c_io_lchar = c;
806 rc = fputc(c, f);
807 if (rc == EOF)
808 return rc;
809 else
810 return indent_cnt + 1;
811 }
812
_d2c_fputs(const char * s,FILE * f)813 int _d2c_fputs(const char *s, FILE *f)
814 {
815 const char *buf = s;
816 /* int len = 0; */
817 while (*buf != '\0')
818 {
819 if (fputc(*buf, f) == EOF)
820 return EOF;
821 /* len++; */
822 buf++;
823 }
824 return 1;
825 }
826
827
828 char d2c_fprintf_buf[HUGE_BUFFER * 2];
_d2c_fprintf(FILE * f,char * fmt,...)829 int _d2c_fprintf(FILE *f, char *fmt, ...)
830 {
831 va_list argptr;
832 int cnt;
833 int extern_cnt;
834 int i;
835
836 va_start(argptr, fmt);
837 cnt = vsprintf(d2c_fprintf_buf, fmt, argptr);
838 va_end(argptr);
839
840 extern_cnt = cnt;
841 if (cnt != EOF)
842 {
843 for (i = 0; i < cnt; i++)
844 {
845 extern_cnt += _d2c_fputc(d2c_fprintf_buf[i], f);
846 }
847 }
848 return extern_cnt;
849 }
850
d2c_directprintf(FILE * f,char * fmt,...)851 int d2c_directprintf(FILE *f, char *fmt, ...)
852 {
853 va_list argptr;
854
855 d2c_indentate(f);
856 va_start(argptr, fmt);
857 vfprintf(f, fmt, argptr);
858 va_end(argptr);
859 return 0;
860 }
861
d2c_open_brace(FILE * f,char * suffix)862 void d2c_open_brace(FILE *f, char *suffix)
863 {
864 if (indent_open_brace_on_newline)
865 {
866 d2c_fputc('\n', f);
867 }
868 else
869 {
870 d2c_fputc(' ', f);
871 }
872 d2c_fprintf(f, "{%s\n", suffix);
873 d2c_indent(f);
874 }
875
d2c_close_brace(FILE * f,char * suffix)876 void d2c_close_brace(FILE *f, char *suffix)
877 {
878 d2c_outdent(f);
879 d2c_fprintf(f, "}%s\n", suffix);
880 }
881
882 param_list *d2c_parameters = NULL;
883
param_list_destroy()884 void param_list_destroy()
885 {
886 param_list *p = d2c_parameters;
887 while (p != NULL)
888 {
889 free(p->name);
890 free(p->value);
891 d2c_parameters = p;
892 p = p->next;
893 free(d2c_parameters);
894 }
895 d2c_parameters = NULL;
896 }
897
d2c_parameter_add(char * name,char * value)898 param_list * d2c_parameter_add(char *name, char *value)
899 {
900 param_list *entry = my_malloc (sizeof(d2c_parameters));
901 entry->name = strdup(name);
902 entry->value = value ? strdup(value) : NULL;
903 entry->next = d2c_parameters;
904 d2c_parameters = entry;
905
906 return entry;
907 }
908
d2c_parameter_set(char * name,char * value)909 param_list * d2c_parameter_set(char *name, char *value)
910 {
911 param_list *entry = d2c_parameter_find(name);
912 if (entry == NULL)
913 entry=d2c_parameter_add(name, value);
914 else
915 {
916 free(entry->value);
917 entry->value = value ? strdup(value) : NULL;
918 }
919
920 return entry;
921 }
922
d2c_parameter_value(char * name)923 char * d2c_parameter_value(char *name)
924 {
925 param_list *entry = d2c_parameter_find(name);
926 if (entry != NULL)
927 return entry->value;
928 return NULL;
929 }
930
d2c_parameter_find(char * name)931 param_list *d2c_parameter_find(char *name)
932 {
933 param_list *p = d2c_parameters;
934 while (p != NULL)
935 {
936 if (strcmp(p->name, name) == 0)
937 return p;
938 p = p->next;
939 }
940 return NULL;
941 }
942
943
d2c_indentate(FILE * f)944 void d2c_indentate( FILE *f)
945 {
946 int i;
947 for ( i = 0; i < d2c_indentposition; i++) {
948 fputs( d2c_indentstring, f);
949 }
950 }
951
952
953 /*
954 * increment the tab position
955 * tab position is used in d2c_fprintf and alike
956 */
d2c_shift_code()957 void d2c_shift_code()
958 {
959 d2c_indentposition ++;
960 }
961
962
963 /*
964 * increment the tab position
965 * tab position is used in d2c_fprintf and alike
966 */
d2c_unshift_code()967 void d2c_unshift_code()
968 {
969 if( d2c_indentposition > 0 )
970 d2c_indentposition --;
971 }
972
973
974
975
976 /*
977 * find a diaoid token in a string
978 * the diaoid must be formatted as @diaoid <oid> where oid is a string without space
979 * @param the NULL terminated string buffer to look in
980 * @param (out) a pointer located on the first oid charater - NULL is allowed if you dont need this pointer
981 * @return the diaoid found or NULL if none is found
982 */
find_diaoid(const char * buf,char ** newpos)983 char *find_diaoid( const char *buf, char **newpos )
984 {
985 static const char *oidtag = "@diaoid";
986 char *cp, *ep; // current pos, diaoid ending position
987 char *oidp=NULL;
988 debug( DBG_CORE, "find_diaoid()" );
989 if( buf == NULL ) {
990 return NULL;
991 }
992 cp = strstr( buf, oidtag );
993 if( cp == NULL )
994 return NULL;
995 cp += strlen(oidtag)+1;
996 /* get the oid */
997 ep = strpbrk( cp, " \t\n\r" );
998 if( ep == NULL ) {
999 oidp = strdup(cp);
1000 } else {
1001 oidp= (char*) strndup( cp, (size_t) ( ep-cp));
1002 }
1003 /* caller want the new position : we set it */
1004 if( newpos != NULL ) {
1005 (*newpos) = cp;
1006 }
1007 return oidp;
1008 }
1009
1010
1011