1 /***************************************************************************
2     begin       : Mon Mar 01 2004
3     copyright   : (C) 2004-2010 by Martin Preuss
4     email       : martin@libchipcard.de
5 
6  ***************************************************************************
7  *          Please see toplevel file COPYING for license details           *
8  ***************************************************************************/
9 
10 #ifdef HAVE_CONFIG_H
11 # include <config.h>
12 #endif
13 
14 
15 
16 #include "args.h"
17 #include "typemaker_p.h"
18 #include <gwenhywfar/debug.h>
19 #include <gwenhywfar/logger.h>
20 #include <gwenhywfar/xml.h>
21 #include <gwenhywfar/syncio_file.h>
22 
23 #include <stdlib.h>
24 #include <assert.h>
25 
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <errno.h>
30 #include <string.h>
31 #include <ctype.h>
32 
33 
34 
35 
write_ha_file_c(ARGUMENTS * args,GWEN_XMLNODE * node)36 int write_ha_file_c(ARGUMENTS *args, GWEN_XMLNODE *node)
37 {
38   int rv;
39   const char *f;
40   GWEN_BUFFER *fname;
41   GWEN_BUFFER *hbuf;
42   const char *s;
43   const char *nacc;
44   const char *constAcc;
45   const char *constName;
46   const char *fromDbAcc;
47   const char *fromDbName;
48   const char *dupAcc;
49   const char *dupName;
50   GWEN_SYNCIO *sio;
51   int err;
52   GWEN_XMLNODE *n;
53   const char *id;
54   const char *prefix;
55 
56   id=get_struct_property(node, "id", 0);
57   if (!id) {
58     DBG_ERROR(0, "No id for struct");
59     return -1;
60   }
61 
62   prefix=get_struct_property(node, "prefix", 0);
63   if (!prefix) {
64     DBG_ERROR(0, "No prefix for struct");
65     return -1;
66   }
67 
68   f=get_struct_property(node, "filename", 0);
69   if (!f) {
70     DBG_ERROR(0, "No filename given");
71     return -1;
72   }
73 
74   nacc=get_struct_property(node, "access", "public");
75   constAcc=get_struct_property(node, "constructor-access", nacc);
76   constName=get_struct_property(node, "constructor-name", 0);
77   fromDbAcc=get_struct_property(node, "fromdb-access", nacc);
78   fromDbName=get_struct_property(node, "fromdb-name", 0);
79   dupAcc=get_struct_property(node, "dup-access", nacc);
80   dupName=get_struct_property(node, "fromdb-name", 0);
81 
82   fname=GWEN_Buffer_new(0, 256, 0, 1);
83   GWEN_Buffer_AppendString(fname, f);
84   GWEN_Buffer_AppendString(fname, ".h");
85 
86   sio=GWEN_SyncIo_File_new(GWEN_Buffer_GetStart(fname),
87                            GWEN_SyncIo_File_CreationMode_CreateAlways);
88   GWEN_SyncIo_AddFlags(sio,
89                        GWEN_SYNCIO_FILE_FLAGS_READ |
90                        GWEN_SYNCIO_FILE_FLAGS_WRITE |
91                        GWEN_SYNCIO_FILE_FLAGS_UREAD |
92                        GWEN_SYNCIO_FILE_FLAGS_UWRITE |
93                        GWEN_SYNCIO_FILE_FLAGS_GREAD |
94                        GWEN_SYNCIO_FILE_FLAGS_GWRITE);
95   rv=GWEN_SyncIo_Connect(sio);
96   if (rv<0) {
97     DBG_ERROR(0, "open(%s): %s",
98               GWEN_Buffer_GetStart(fname),
99               strerror(errno));
100     GWEN_Buffer_free(fname);
101     GWEN_SyncIo_free(sio);
102     return -1;
103   }
104   GWEN_Buffer_free(fname);
105 
106   /* Insert the auto-generation warning */
107   GWEN_SyncIo_WriteString(sio, "/* This file is auto-generated from \"");
108   GWEN_SyncIo_WriteString(sio, f);
109   GWEN_SyncIo_WriteLine(sio, ".xml\" by the typemaker");
110   GWEN_SyncIo_WriteLine(sio, "   tool of Gwenhywfar. ");
111   GWEN_SyncIo_WriteLine(sio, "   Do not edit this file -- all changes will be lost! */");
112 
113   hbuf=GWEN_Buffer_new(0, 256, 0, 1);
114   s=f;
115   while (*s) {
116     GWEN_Buffer_AppendByte(hbuf, toupper(*s));
117     s++;
118   }
119   GWEN_Buffer_AppendString(hbuf, "_H");
120 
121   GWEN_SyncIo_WriteString(sio, "#ifndef ");
122   GWEN_SyncIo_WriteLine(sio, GWEN_Buffer_GetStart(hbuf));
123   GWEN_SyncIo_WriteString(sio, "#define ");
124   GWEN_SyncIo_WriteLine(sio, GWEN_Buffer_GetStart(hbuf));
125   GWEN_SyncIo_WriteLine(sio, "");
126 
127   rv=write_apidoc_c(args, node, sio, "public");
128   if (rv) {
129     DBG_INFO(0, "here (%d)", rv);
130     return rv;
131   }
132 
133   if (strcasecmp(nacc, "public")==0) {
134     GWEN_SyncIo_WriteLine(sio, "#ifdef __cplusplus");
135     GWEN_SyncIo_WriteLine(sio, "extern \"C\" {");
136     GWEN_SyncIo_WriteLine(sio, "#endif");
137     GWEN_SyncIo_WriteLine(sio, "");
138     GWEN_SyncIo_WriteString(sio, "typedef struct ");
139     GWEN_SyncIo_WriteString(sio, id);
140     GWEN_SyncIo_WriteString(sio, " ");
141     GWEN_SyncIo_WriteString(sio, id);
142     GWEN_SyncIo_WriteLine(sio, ";");
143     GWEN_SyncIo_WriteLine(sio, "");
144     GWEN_SyncIo_WriteLine(sio, "#ifdef __cplusplus");
145     GWEN_SyncIo_WriteLine(sio, "} /* __cplusplus */");
146     GWEN_SyncIo_WriteLine(sio, "#endif");
147     GWEN_SyncIo_WriteLine(sio, "");
148   }
149 
150   GWEN_SyncIo_WriteLine(sio, "#include <gwenhywfar/db.h>");
151 
152   if (strcasecmp(get_struct_property(node, "inherit", ""),
153                  "public")==0) {
154     GWEN_SyncIo_WriteLine(sio, "#include <gwenhywfar/inherit.h>");
155   }
156 
157   if (strcasecmp(get_struct_property(node, "list", ""),
158                  "public")==0) {
159     GWEN_SyncIo_WriteLine(sio, "#include <gwenhywfar/misc.h>");
160   }
161 
162   if (strcasecmp(get_struct_property(node, "list2", ""),
163                  "public")==0) {
164     GWEN_SyncIo_WriteLine(sio, "#include <gwenhywfar/list2.h>");
165   }
166 
167   n=GWEN_XMLNode_FindFirstTag(node, "pre-headers", 0, 0);
168   if (n) {
169     GWEN_XMLNODE *nn;
170 
171     GWEN_SyncIo_WriteLine(sio, "/* pre-headers */");
172     nn=GWEN_XMLNode_GetFirstTag(n);
173     while (nn) {
174       rv=write_hp_group_c(args, nn, sio);
175       if (rv) {
176         GWEN_Buffer_free(hbuf);
177         return -1;
178       }
179       nn=GWEN_XMLNode_GetNextTag(nn);
180     } /* while */
181     GWEN_SyncIo_WriteLine(sio, "");
182   }
183 
184   n=GWEN_XMLNode_FindFirstTag(node, "headers", 0, 0);
185   if (n) {
186     GWEN_XMLNODE *nn;
187 
188     GWEN_SyncIo_WriteLine(sio, "/* headers */");
189     nn=GWEN_XMLNode_GetFirstTag(n);
190     while (nn) {
191       rv=write_hp_group_c(args, nn, sio);
192       if (rv) {
193         GWEN_Buffer_free(hbuf);
194         DBG_INFO(0, "here (%d)", rv);
195         return -1;
196       }
197       nn=GWEN_XMLNode_GetNextTag(nn);
198     } /* while */
199     GWEN_SyncIo_WriteLine(sio, "");
200   }
201 
202   GWEN_SyncIo_WriteLine(sio, "#ifdef __cplusplus");
203   GWEN_SyncIo_WriteLine(sio, "extern \"C\" {");
204   GWEN_SyncIo_WriteLine(sio, "#endif");
205   GWEN_SyncIo_WriteLine(sio, "");
206 
207   if (write_h_enums(args, node, sio, "public")) {
208     DBG_ERROR(0, "Error writing enum types");
209     return -1;
210   }
211 
212   if (write_h_funcs(args, node, sio, "public")) {
213     DBG_ERROR(0, "Error writing function types");
214     return -1;
215   }
216 
217   if (strcasecmp(get_struct_property(node, "inherit", ""),
218                  "public")==0) {
219     if (args->domain)
220       GWEN_SyncIo_WriteString(sio, "GWEN_INHERIT_FUNCTION_LIB_DEFS(");
221     else
222       GWEN_SyncIo_WriteString(sio, "GWEN_INHERIT_FUNCTION_DEFS(");
223     GWEN_SyncIo_WriteString(sio, id);
224     if (args->domain) {
225       GWEN_SyncIo_WriteString(sio, ", ");
226       GWEN_SyncIo_WriteString(sio, args->domain);
227     }
228     GWEN_SyncIo_WriteLine(sio, ")");
229   }
230 
231   if (strcasecmp(get_struct_property(node, "list", ""),
232                  "public")==0) {
233     if (args->domain)
234       GWEN_SyncIo_WriteString(sio, "GWEN_LIST_FUNCTION_LIB_DEFS(");
235     else
236       GWEN_SyncIo_WriteString(sio, "GWEN_LIST_FUNCTION_DEFS(");
237     GWEN_SyncIo_WriteString(sio, id);
238     GWEN_SyncIo_WriteString(sio, ", ");
239     GWEN_SyncIo_WriteString(sio, prefix);
240     if (args->domain) {
241       GWEN_SyncIo_WriteString(sio, ", ");
242       GWEN_SyncIo_WriteString(sio, args->domain);
243     }
244     GWEN_SyncIo_WriteLine(sio, ")");
245 
246     if (dupAcc && strcasecmp(dupAcc, "none")!=0) {
247       if (args->domain) {
248         GWEN_SyncIo_WriteString(sio, args->domain);
249         GWEN_SyncIo_WriteString(sio, " ");
250       }
251       GWEN_SyncIo_WriteString(sio, id);
252       GWEN_SyncIo_WriteString(sio, "_LIST *");
253       GWEN_SyncIo_WriteString(sio, prefix);
254       GWEN_SyncIo_WriteString(sio, "_List_dup(const ");
255       GWEN_SyncIo_WriteString(sio, id);
256       GWEN_SyncIo_WriteLine(sio, "_LIST *stl);");
257       GWEN_SyncIo_WriteLine(sio, "");
258     }
259   }
260 
261   if (strcasecmp(get_struct_property(node, "list2", ""),
262                  "public")==0) {
263     if (args->domain)
264       GWEN_SyncIo_WriteString(sio, "GWEN_LIST2_FUNCTION_LIB_DEFS(");
265     else
266       GWEN_SyncIo_WriteString(sio, "GWEN_LIST2_FUNCTION_DEFS(");
267     GWEN_SyncIo_WriteString(sio, id);
268     GWEN_SyncIo_WriteString(sio, ", ");
269     GWEN_SyncIo_WriteString(sio, prefix);
270     if (args->domain) {
271       GWEN_SyncIo_WriteString(sio, ", ");
272       GWEN_SyncIo_WriteString(sio, args->domain);
273     }
274     GWEN_SyncIo_WriteLine(sio, ")");
275     GWEN_SyncIo_WriteLine(sio, "");
276 
277     GWEN_SyncIo_WriteLine(sio,
278                           "/** Destroys all objects stored in the given "
279                           "LIST2 and the list itself");
280     GWEN_SyncIo_WriteLine(sio, "*/");
281     if (args->domain) {
282       GWEN_SyncIo_WriteString(sio, args->domain);
283       GWEN_SyncIo_WriteString(sio, " ");
284     }
285     GWEN_SyncIo_WriteString(sio, "void ");
286     GWEN_SyncIo_WriteString(sio, prefix);
287     GWEN_SyncIo_WriteString(sio, "_List2_freeAll(");
288     GWEN_SyncIo_WriteString(sio, id);
289     GWEN_SyncIo_WriteLine(sio, "_LIST2 *stl);");
290 
291     GWEN_SyncIo_WriteLine(sio, "");
292   }
293 
294   n=GWEN_XMLNode_FindFirstTag(node, "post-headers", 0, 0);
295   if (n) {
296     GWEN_XMLNODE *nn;
297 
298     GWEN_SyncIo_WriteLine(sio, "/* post-headers */");
299     nn=GWEN_XMLNode_GetFirstTag(n);
300     while (nn) {
301       rv=write_hp_group_c(args, nn, sio);
302       if (rv) {
303         GWEN_Buffer_free(hbuf);
304         DBG_INFO(0, "here (%d)", rv);
305         return -1;
306       }
307       nn=GWEN_XMLNode_GetNextTag(nn);
308     } /* while */
309     GWEN_SyncIo_WriteLine(sio, "");
310   }
311 
312 
313   if (strcasecmp(constAcc, "public")==0) {
314     GWEN_SyncIo_WriteLine(sio,
315                           "/** Creates a new object.");
316     GWEN_SyncIo_WriteLine(sio, "*/");
317     if (args->domain) {
318       GWEN_SyncIo_WriteString(sio, args->domain);
319       GWEN_SyncIo_WriteString(sio, " ");
320     }
321     GWEN_SyncIo_WriteString(sio, id);
322     GWEN_SyncIo_WriteString(sio, " *");
323     GWEN_SyncIo_WriteString(sio, prefix);
324     if (constName)
325       GWEN_SyncIo_WriteString(sio, constName);
326     else
327       GWEN_SyncIo_WriteString(sio, "_new");
328     GWEN_SyncIo_WriteLine(sio, "(void);");
329   }
330 
331   /* FromDb */
332   if (strcasecmp(fromDbAcc, "public")==0) {
333     GWEN_SyncIo_WriteLine(sio,
334                           "/** Creates an object from the data in the"
335                           " given GWEN_DB_NODE");
336     GWEN_SyncIo_WriteLine(sio, "*/");
337     if (args->domain) {
338       GWEN_SyncIo_WriteString(sio, args->domain);
339       GWEN_SyncIo_WriteString(sio, " ");
340     }
341     GWEN_SyncIo_WriteString(sio, id);
342     GWEN_SyncIo_WriteString(sio, " *");
343     GWEN_SyncIo_WriteString(sio, prefix);
344     if (fromDbName)
345       GWEN_SyncIo_WriteString(sio, fromDbName);
346     else
347       GWEN_SyncIo_WriteString(sio, "_fromDb");
348     GWEN_SyncIo_WriteLine(sio, "(GWEN_DB_NODE *db);");
349   }
350 
351   /* dup */
352   if (strcasecmp(dupAcc, "public")==0) {
353     GWEN_SyncIo_WriteLine(sio,
354                           "/** Creates and returns a deep copy of the"
355                           "given object.");
356     GWEN_SyncIo_WriteLine(sio, "*/");
357     if (args->domain) {
358       GWEN_SyncIo_WriteString(sio, args->domain);
359       GWEN_SyncIo_WriteString(sio, " ");
360     }
361     GWEN_SyncIo_WriteString(sio, id);
362     GWEN_SyncIo_WriteString(sio, " *");
363     GWEN_SyncIo_WriteString(sio, prefix);
364     if (dupName)
365       GWEN_SyncIo_WriteString(sio, dupName);
366     else
367       GWEN_SyncIo_WriteString(sio, "_dup");
368     GWEN_SyncIo_WriteString(sio, "(const ");
369     GWEN_SyncIo_WriteString(sio, id);
370     GWEN_SyncIo_WriteLine(sio, "*st);");
371   }
372 
373   if (strcasecmp(nacc, "public")==0) {
374     GWEN_SyncIo_WriteLine(sio,
375                           "/** Destroys the given object.");
376     GWEN_SyncIo_WriteLine(sio, "*/");
377     if (args->domain) {
378       GWEN_SyncIo_WriteString(sio, args->domain);
379       GWEN_SyncIo_WriteString(sio, " ");
380     }
381     GWEN_SyncIo_WriteString(sio, "void ");
382     GWEN_SyncIo_WriteString(sio, prefix);
383     GWEN_SyncIo_WriteString(sio, "_free(");
384     GWEN_SyncIo_WriteString(sio, id);
385     GWEN_SyncIo_WriteLine(sio, " *st);");
386 
387     GWEN_SyncIo_WriteLine(sio,
388                           "/** Increments the usage counter of the "
389                           "given object, so an additional free() is"
390                           " needed to destroy the object.");
391     GWEN_SyncIo_WriteLine(sio, "*/");
392     if (args->domain) {
393       GWEN_SyncIo_WriteString(sio, args->domain);
394       GWEN_SyncIo_WriteString(sio, " ");
395     }
396     GWEN_SyncIo_WriteString(sio, "void ");
397     GWEN_SyncIo_WriteString(sio, prefix);
398     GWEN_SyncIo_WriteString(sio, "_Attach(");
399     GWEN_SyncIo_WriteString(sio, id);
400     GWEN_SyncIo_WriteLine(sio, " *st);");
401 
402     /* ReadDb */
403     GWEN_SyncIo_WriteLine(sio, "/** Reads data from a GWEN_DB.");
404     GWEN_SyncIo_WriteLine(sio, "*/");
405     if (args->domain) {
406       GWEN_SyncIo_WriteString(sio, args->domain);
407       GWEN_SyncIo_WriteString(sio, " ");
408     }
409     GWEN_SyncIo_WriteString(sio, "int ");
410     GWEN_SyncIo_WriteString(sio, prefix);
411     GWEN_SyncIo_WriteString(sio, "_ReadDb(");
412     GWEN_SyncIo_WriteString(sio, id);
413     GWEN_SyncIo_WriteLine(sio, " *st, GWEN_DB_NODE *db);");
414 
415     /* ToDb */
416     GWEN_SyncIo_WriteLine(sio,
417                           "/** Stores an object in the"
418                           " given GWEN_DB_NODE");
419     GWEN_SyncIo_WriteLine(sio, "*/");
420     if (args->domain) {
421       GWEN_SyncIo_WriteString(sio, args->domain);
422       GWEN_SyncIo_WriteString(sio, " ");
423     }
424     GWEN_SyncIo_WriteString(sio, "int ");
425     GWEN_SyncIo_WriteString(sio, prefix);
426     GWEN_SyncIo_WriteString(sio, "_toDb(const ");
427     GWEN_SyncIo_WriteString(sio, id);
428     GWEN_SyncIo_WriteLine(sio, "*st, GWEN_DB_NODE *db);");
429 
430     GWEN_SyncIo_WriteLine(sio,
431                           "/** Returns 0 if this object has not been"
432                           " modified, !=0 otherwise");
433     GWEN_SyncIo_WriteLine(sio, "*/");
434     if (args->domain) {
435       GWEN_SyncIo_WriteString(sio, args->domain);
436       GWEN_SyncIo_WriteString(sio, " ");
437     }
438     GWEN_SyncIo_WriteString(sio, "int ");
439     GWEN_SyncIo_WriteString(sio, prefix);
440     GWEN_SyncIo_WriteString(sio, "_IsModified(const ");
441     GWEN_SyncIo_WriteString(sio, id);
442     GWEN_SyncIo_WriteLine(sio, " *st);");
443 
444     GWEN_SyncIo_WriteLine(sio,
445                           "/** Sets the modified state of the given "
446                           "object");
447     GWEN_SyncIo_WriteLine(sio, "*/");
448     if (args->domain) {
449       GWEN_SyncIo_WriteString(sio, args->domain);
450       GWEN_SyncIo_WriteString(sio, " ");
451     }
452     GWEN_SyncIo_WriteString(sio, "void ");
453     GWEN_SyncIo_WriteString(sio, prefix);
454     GWEN_SyncIo_WriteString(sio, "_SetModified(");
455     GWEN_SyncIo_WriteString(sio, id);
456     GWEN_SyncIo_WriteLine(sio, " *st, int i);");
457   }
458 
459   rv=write_h_setget_c(args, node, sio, "public");
460   if (rv) {
461     GWEN_Buffer_free(hbuf);
462     GWEN_SyncIo_Disconnect(sio);
463     GWEN_SyncIo_free(sio);
464     DBG_INFO(0, "here (%d)", rv);
465     return rv;
466   }
467 
468   err=GWEN_SyncIo_WriteLine(sio, "");
469   if (err) {
470     DBG_ERROR_ERR(0, err);
471     GWEN_Buffer_free(hbuf);
472     return -1;
473   }
474 
475   err=GWEN_SyncIo_WriteLine(sio, "#ifdef __cplusplus");
476   if (err) {
477     DBG_ERROR_ERR(0, err);
478     GWEN_Buffer_free(hbuf);
479     return -1;
480   }
481   err=GWEN_SyncIo_WriteLine(sio, "} /* __cplusplus */");
482   if (err) {
483     DBG_ERROR_ERR(0, err);
484     GWEN_Buffer_free(hbuf);
485     return -1;
486   }
487   err=GWEN_SyncIo_WriteLine(sio, "#endif");
488   if (err) {
489     DBG_ERROR_ERR(0, err);
490     GWEN_Buffer_free(hbuf);
491     return -1;
492   }
493   err=GWEN_SyncIo_WriteLine(sio, "");
494   if (err) {
495     DBG_ERROR_ERR(0, err);
496     GWEN_Buffer_free(hbuf);
497     return -1;
498   }
499 
500   /* write trailing endif */
501   err=GWEN_SyncIo_WriteLine(sio, "");
502   if (err) {
503     DBG_ERROR_ERR(0, err);
504     GWEN_Buffer_free(hbuf);
505     return -1;
506   }
507 
508   err=GWEN_SyncIo_WriteString(sio, "#endif /* ");
509   if (err) {
510     DBG_ERROR_ERR(0, err);
511     GWEN_Buffer_free(hbuf);
512     return -1;
513   }
514   err=GWEN_SyncIo_WriteString(sio, GWEN_Buffer_GetStart(hbuf));
515   if (err) {
516     DBG_ERROR_ERR(0, err);
517     GWEN_Buffer_free(hbuf);
518     return -1;
519   }
520   err=GWEN_SyncIo_WriteLine(sio, " */");
521   if (err) {
522     DBG_ERROR_ERR(0, err);
523     GWEN_Buffer_free(hbuf);
524     return -1;
525   }
526 
527   err=GWEN_SyncIo_Disconnect(sio);
528   if (err) {
529     DBG_ERROR_ERR(0, err);
530     GWEN_SyncIo_free(sio);
531     GWEN_Buffer_free(hbuf);
532     return -1;
533   }
534 
535   GWEN_Buffer_free(hbuf);
536   return 0;
537 }
538 
539 
540 
write_ha_files_c(ARGUMENTS * args,GWEN_XMLNODE * node)541 int write_ha_files_c(ARGUMENTS *args, GWEN_XMLNODE *node)
542 {
543   GWEN_XMLNODE *n;
544   int rv;
545 
546   n=GWEN_XMLNode_FindFirstTag(node, "type", 0, 0);
547   while (n) {
548     const char *nacc;
549 
550     nacc=get_struct_property(n, "access", "public");
551     if (strcasecmp(nacc, "public")==0) {
552       rv=write_ha_file_c(args, n);
553       if (rv) {
554         DBG_INFO(0, "here (%d)", rv);
555         return rv;
556       }
557     }
558     n=GWEN_XMLNode_FindNextTag(n, "type", 0, 0);
559   }
560   return 0;
561 }
562 
563 
564 
565 
566 
567 
568 
569 
570