PIPS
genC.c
Go to the documentation of this file.
1 /*
2 
3  $Id: genC.c 1375 2018-03-26 11:56:55Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of NewGen.
8 
9  NewGen is free software: you can redistribute it and/or modify it under the
10  terms of the GNU General Public License as published by the Free Software
11  Foundation, either version 3 of the License, or any later version.
12 
13  NewGen is distributed in the hope that it will be useful, but WITHOUT ANY
14  WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16  License for more details.
17 
18  You should have received a copy of the GNU General Public License along with
19  NewGen. If not, see <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 /*
24  generates typed newgen structures.
25 */
26 #ifdef HAVE_CONFIG_H
27  #include "config.h"
28 #endif
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <ctype.h>
33 #include <string.h>
34 
35 #include "genC.h"
36 #include "newgen_include.h"
37 
38 #undef gen_recurse
39 #undef gen_context_recurse
40 
41 #define FIELD "" /* was: "field_" */
42 #define STRUCT "_newgen_struct_" /* structure names */
43 
44 #define OPTIMIZE_NEWGEN "OPTIMIZE_NEWGEN"
45 
46 #define IS_TAB(x) ((x)==Tabulated_bp)
47 
48 /* non user domain must be taken care from outside? */
49 /* #define FIRST_USER_DOMAIN (7) */
50 #define TYPE(bp) (bp-Domains-Number_imports-Current_start)
51 
52 #define DomainNumberError \
53  "\"[newgen internal error]\"" \
54  "\"inconsistent domain number for %s: %%d (expecting %%d)\\n\""
55 
56 /* Might be used to generate optimized versions
57  (say macros instead of functions).
58  */
59 static int sharp_ifopt(FILE * out)
60 { return fprintf(out, "#if defined(" OPTIMIZE_NEWGEN ")\n"); }
61 
62 static int sharp_else(FILE * out)
63 { return fprintf(out, "#else\n"); }
64 
65 static int sharp_endif(FILE * out)
66 { return fprintf(out, "#endif /* " OPTIMIZE_NEWGEN " */\n"); }
67 
68 /* GEN_SIZE returns the size (in gen_chunks) of an object of type defined by
69  * the BP type.
70  */
71 int gen_size(int domain)
72 {
73  struct gen_binding * bp = Domains+domain;
74  int overhead = GEN_HEADER + IS_TABULATED(bp);
75 
76  switch (bp->domain->ba.type)
77  {
78  case BASIS_DT:
79  case ARRAY_DT:
80  case LIST_DT:
81  case SET_DT:
82  return overhead + 1;
83  case CONSTRUCTED_DT:
84  if (bp->domain->co.op == OR_OP)
85  return overhead + 2;
86  else if (bp->domain->co.op == AND_OP)
87  {
88  int size ;
89  struct domainlist * dlp = bp->domain->co.components ;
90  for( size=0 ; dlp != NULL ; dlp=dlp->cdr, size++ );
91  return overhead + size;
92  }
93  else if (bp->domain->co.op == ARROW_OP)
94  return overhead+1;
95  else
96  {
97  fatal("gen_size: unknown constructed domain operator %d\n",
98  bp->domain->co.op);
99  return -1;
100  }
101  default:
102  fatal( "gen_size: Unknown type %s\n", i2a( bp->domain->ba.type )) ;
103  return -1; /* to avoid a gcc warning */
104  /*NOTREACHED*/
105  }
106 }
107 
108 /* returns s duplicated and case-uppered.
109  */
110 static string strup(string s)
111 {
112  string r = strdup(s), p=r;
113  while (*p) *p=toupper(*p), p++;
114  return r;
115 }
116 
117 #define same_size(t) (sizeof(t)==sizeof(gen_chunk))
118 
119 static bool inline_directly(union domain * dp)
120 {
121  if (dp->ba.type==BASIS_DT)
122  {
123  struct gen_binding * bp = dp->ba.constructand;
124  string name = bp->name;
125  if (!IS_INLINABLE(bp)) return false;
126  if ((same_string_p(name, "int") && same_size(intptr_t)) ||
127  (same_string_p(name, "string") && same_size(string)) ||
128  (same_string_p(name, "unit") && same_size(unit)))
129  return true;
130  }
131  return false;
132 }
133 
134 /* bof... */
135 static string int_type(void)
136 {
137  return same_size(intptr_t) ? "intptr_t": "gen_chunk";
138 }
139 
140 static string int_type_access_complement(void)
141 {
142  return same_size(intptr_t) ? "": ".i";
143 }
144 
145 /* newgen type name for holder.
146  * could/should always be gen_chunk?
147  */
148 static string newgen_type_name(union domain * dp)
149 {
150  switch (dp->ba.type) {
151  case BASIS_DT: {
152  struct gen_binding * bp = dp->ba.constructand;
153  if (IS_INLINABLE(bp))
154  if (!inline_directly(dp))
155  return "gen_chunk";
156  if (same_string_p(bp->name, "int"))
157  /* Even if the NewGen name is int, the C name can be intptr_t: */
158  return int_type();
159  return bp->name;
160  }
161  case SET_DT: return "set";
162  case LIST_DT: return "list";
163  case ARRAY_DT: return dp->ar.element->name;
164  case CONSTRUCTED_DT:
165  switch (dp->co.op) {
166  case ARROW_OP: return "hash_table";
167  default:
168  break;
169  }
170  /* FALLTHRU */
171  default:
172  fatal("[newgen_type_name] unexpected domain type %d\n", dp->ba.type);
173  }
174  return NULL;
175 }
176 
177 /* C type name for generated function arguments.
178  */
179 static string newgen_argument_type_name(union domain * dp)
180 {
181  switch (dp->ba.type) {
182  case BASIS_DT:
183  if (same_string_p(dp->ba.constructand->name, "int"))
184  /* Even if the NewGen name is int, the C name can be intptr_t: */
185  return int_type();
186  return dp->ba.constructand->name;
187  case LIST_DT: return "list";
188  case SET_DT: return "set";
189  case ARRAY_DT: return dp->ar.element->name;
190  default: fatal("[newgen_argument_type_name] unexpected domain type %d\n",
191  dp->ba.type);
192  }
193  return NULL;
194 }
195 
196 static string newgen_type_name_close(union domain * dp)
197 {
198  if (dp->ba.type==ARRAY_DT) return " *"; /* pointer */
199  return "";
200 }
201 
202 /* what to add to the field to access a given primitive type,
203  * which was typically declared as a gen_chunk.
204  * the field is the first char of the type name.
205  */
206 static char newgen_access_name(union domain * dp)
207 {
208  if (dp->ba.type==BASIS_DT && IS_INLINABLE(dp->ba.constructand))
209  return dp->ba.constructand->name[0];
210  else
211  return '\0';
212 }
213 
214 /* just to generate comprehensive comments.
215  */
216 static string newgen_kind_label(union domain * dp)
217 {
218  switch (dp->ba.type) {
219  case SET_DT: return "{}";
220  case LIST_DT: return "*";
221  case ARRAY_DT: return "[]";
222  default: return "";
223  }
224 }
225 
226 /* make is bigger, thus I put it in a separate function.
227  */
228 static void generate_make(
229  FILE * header,
230  FILE * code,
231  struct gen_binding * bp,
232  int domain_type,
233  int operator)
234 {
235  string name = bp->name;
236  union domain * dom = bp->domain;
237  struct domainlist * dlp;
238  int domain = bp-Domains;
239  int i;
240 
241  /* HEADER
242  */
243  fprintf(header, "extern %s make_%s(", name, name);
244 
245  switch (domain_type) {
246  case CONSTRUCTED_DT:
247  switch (operator) {
248  case AND_OP:
249  for (i=1, dlp=dom->co.components; dlp!=NULL; dlp=dlp->cdr, i++)
250  fprintf(header, "%s%s%s", i==1? "": ", ",
251  newgen_argument_type_name(dlp->domain),
252  newgen_type_name_close(dlp->domain));
253  break;
254  case OR_OP:
255  fprintf(header, "enum %s_utype, void *", name);
256  break;
257  case ARROW_OP:
258  fprintf(header, "void");
259  break;
260  }
261  break;
262  case LIST_DT:
263  case SET_DT:
264  case ARRAY_DT:
265  fprintf(header, "%s%s",
268  break;
269  default:
270  fatal("[generate_make] unexpected domain type tag %d\n", domain_type);
271  }
272 
273  fprintf(header, ");\n");
274 
275  /* CODE
276  */
277  fprintf(code, "%s make_%s(", name, name);
278  switch (domain_type) {
279  case CONSTRUCTED_DT:
280  switch (operator) {
281  case AND_OP:
282  for (i=1, dlp=dom->co.components; dlp!=NULL; dlp=dlp->cdr, i++)
283  fprintf(code, "%s%s%s a%d", i==1? "": ", ",
284  newgen_argument_type_name(dlp->domain),
285  newgen_type_name_close(dlp->domain), i);
286  break;
287  case OR_OP:
288  fprintf(code, "enum %s_utype tag, void * val", name);
289  break;
290  case ARROW_OP:
291  fprintf(code, "void");
292  break;
293  }
294  break;
295  case LIST_DT:
296  case SET_DT:
297  case ARRAY_DT:
298  fprintf(code, "%s%s a",
301  break;
302  }
303 
304  fprintf(code,
305  ") {\n"
306  " return (%s) "
307  "gen_alloc(%d*sizeof(gen_chunk), GEN_CHECK_ALLOC, %s_domain",
308  name, gen_size(domain), name);
309  switch (domain_type) {
310  case CONSTRUCTED_DT:
311  switch (operator) {
312  case AND_OP:
313  for (i=1, dlp=dom->co.components; dlp!=NULL; dlp=dlp->cdr, i++)
314  fprintf(code, ", a%d", i);
315  break;
316  case OR_OP:
317  fprintf(code, ", tag, val");
318  break;
319  case ARROW_OP:
320  break;
321  }
322  break;
323  case LIST_DT:
324  case SET_DT:
325  case ARRAY_DT:
326  fprintf(code, ", a");
327  break;
328  }
329  fprintf(code, ");\n}\n");
330 
331  /* additionnal constructors for OR,
332  so as to improve type checking.
333  */
334  if (domain_type==CONSTRUCTED_DT && operator==OR_OP) {
335  for (dlp=dom->co.components; dlp!=NULL; dlp=dlp->cdr) {
336  /* check for unit... */
337  string field = dlp->domain->ba.constructor;
338  string typen = newgen_argument_type_name(dlp->domain);
339  if(!strcmp(typen, UNIT_TYPE_NAME)) {
340  /* UNIT case */
341  /* header */
342  fprintf(header,
343  "extern %s make_%s_%s(void);\n",
344  name, name, field);
345  /* code */
346  fprintf(code,
347  "%s make_%s_%s(void) {\n"
348  " return make_%s(is_%s_%s, UU);\n"
349  "}\n",
350  name, name, field, name, name, field);
351  }
352  else {
353  /* header */
354  fprintf(header, "extern %s make_%s_%s(%s);\n",
355  name, name, field, typen);
356  /* code */
357  fprintf(code,
358  "%s make_%s_%s(%s _field_) {\n"
359  " return make_%s(is_%s_%s, (void*)(intptr_t) _field_);\n"
360  "}\n",
361  name, name, field, typen,
362  name, name, field);
363  }
364  }
365  }
366 }
367 
368 /* generate the struct for bp.
369  */
371  FILE * out,
372  struct gen_binding * bp,
373  int domain_type,
374  int operator)
375 {
376  union domain * dom = bp->domain;
377  struct domainlist * dlp;
378  string offset = "";
379 
380  /* generate the structure
381  */
382  fprintf(out,
383  "struct " STRUCT "%s_ {\n"
384  " %s _type_;\n",
385  bp->name, int_type());
386 
387  /* there is an additionnal field in tabulated domains.
388  */
389  if (IS_TABULATED(bp))
390  fprintf(out,
391  " %s _%s_index__;\n",
392  int_type(), bp->name);
393 
394  if (domain_type==CONSTRUCTED_DT && operator==OR_OP) {
395  fprintf(out,
396  " enum %s_utype _%s_tag__;\n"
397  " union {\n",
398  bp->name, bp->name);
399  offset = " ";
400  }
401 
402  if ((domain_type==CONSTRUCTED_DT && operator==ARROW_OP) ||
403  domain_type==LIST_DT ||
404  domain_type==SET_DT)
405  fprintf(out,
406  " %s _%s_holder_;\n",
407  newgen_type_name(dom), bp->name);
408 
409  if (domain_type==CONSTRUCTED_DT && operator!=ARROW_OP) {
410  /* generate struct fields */
411  for (dlp=dom->co.components; dlp!=NULL; dlp=dlp->cdr)
412  fprintf(out, "%s %s%s _%s_%s_" FIELD "; /* %s:%s%s */\n",
413  offset,
414  newgen_type_name(dlp->domain),
415  newgen_type_name_close(dlp->domain),
416  bp->name, dlp->domain->ba.constructor,
417  dlp->domain->ba.constructor,
418  dlp->domain->ba.constructand->name,
419  newgen_kind_label(dlp->domain));
420  }
421 
422  if (domain_type==CONSTRUCTED_DT && operator==OR_OP)
423  fprintf(out, " } _%s_union_;\n", bp->name);
424 
425  fprintf(out, "};\n\n");
426 }
427 
429  FILE * out,
430  struct gen_binding * bp,
431  int domain_type,
432  int operator)
433 {
434  union domain * dom = bp->domain;
435  struct domainlist * dlp;
436  string name=bp->name;
437 
438  if (domain_type==CONSTRUCTED_DT &&
439  operator==OR_OP && dom->co.components!=NULL)
440  {
441  fprintf(out,"enum %s_utype {\n", name);
442  for (dlp=dom->co.components; dlp!=NULL; dlp=dlp->cdr) {
443  string field = dlp->domain->ba.constructor;
444  fprintf(out,
445  " is_%s_%s%s\n",
446  name, field, (dlp->cdr == NULL)? "": ",");
447  }
448  fprintf(out,"};\n");
449  }
450 }
451 
452 /* introspection function. could be a dynamic function in genClib...
453  */
455  FILE * header,
456  FILE * code,
457  struct gen_binding * bp,
458  int domain_type,
459  int operator)
460 {
461  union domain * dom = bp->domain;
462  struct domainlist * dlp;
463  string name=bp->name;
464 
465  if (domain_type==CONSTRUCTED_DT &&
466  operator==OR_OP && dom->co.components!=NULL)
467  {
468  fprintf(header, "extern string %s_tag_as_string(enum %s_utype);\n",
469  name, name);
470  fprintf(code, "string %s_tag_as_string(enum %s_utype tag) {\n"
471  " switch (tag) {\n",
472  name, name);
473  for (dlp=dom->co.components; dlp!=NULL; dlp=dlp->cdr) {
474  string field = dlp->domain->ba.constructor;
475  fprintf(code,
476  " case is_%s_%s: return \"%s\";\n",
477  name, field, field);
478  }
479  fprintf(code,
480  " default: return string_undefined;\n"
481  " }\n"
482  "}\n");
483  }
484 }
485 
486 /* access to members are managed thru macros.
487  * cannot be functions because assign would not be possible.
488  * it would be better to avoid having field names that appear twice...
489  */
491  FILE * out,
492  struct gen_binding * bp,
493  int domain_type,
494  int operator)
495 {
496  union domain * dom = bp->domain;
497  struct domainlist * dlp;
498  bool in_between;
499  string name=bp->name;
500 
501  fprintf(out,
502  "#define %s_domain_number(x) ((x)->_type_%s)\n",
504 
505  if (domain_type==CONSTRUCTED_DT && operator==OR_OP) {
506  in_between = true;
507  fprintf(out,
508  "#define %s_tag(x) ((x)->_%s_tag__%s)\n",
509  name, name, int_type_access_complement());
510  }
511  else in_between = false;
512 
513  if (domain_type==CONSTRUCTED_DT && operator==ARROW_OP)
514  fprintf(out, "#define %s_hash_table(x) ((x)->_%s_holder_)\n",
515  name, name);
516 
517  if (domain_type==LIST_DT || domain_type==SET_DT)
518  fprintf(out, "#define %s_%s(x) ((x)->_%s_holder_)\n",
519  name, dom->ba.constructor, name);
520 
521  if (domain_type==ARRAY_DT)
522  fprintf(out, "#define %s_%s(x) ((x)->_%s_%s_" FIELD "\n",
523  name, dom->ba.constructor,
524  name, dom->ba.constructor);
525 
526  if (domain_type==CONSTRUCTED_DT && operator!=ARROW_OP) {
527 
528  /* accesses... */
529  for (dlp=dom->co.components; dlp!=NULL; dlp=dlp->cdr) {
530  char c;
531  if(operator==OR_OP) {
532  string field = dlp->domain->ba.constructor;
533  fprintf(out,
534  "#define %s_%s_p(x) (%s_tag(x)==is_%s_%s)\n",
535  name, field, name, name, field);
536  }
537  fprintf(out,
538  "#define %s_%s_(x) %s_%s(x) /* old hack compatible */\n"
539  "#define %s_%s(x) ((x)->",
540  name, dlp->domain->ba.constructor,
541  name, dlp->domain->ba.constructor,
542  name, dlp->domain->ba.constructor);
543  if (in_between) fprintf(out, "_%s_union_.", name);
544  fprintf(out, "_%s_%s_" FIELD, name, dlp->domain->ba.constructor);
545  c = newgen_access_name(dlp->domain);
546  if (c && !inline_directly(dlp->domain))
547  fprintf(out, ".%c", c);
548  fprintf(out, ")\n");
549  }
550  }
551 }
552 
553 /* constructed types: + x (and ->...)
554  */
556  FILE * header,
557  FILE * code,
558  struct gen_binding * bp,
559  int operator)
560 {
561  generate_union_type_descriptor(header, bp, CONSTRUCTED_DT, operator);
562  generate_union_as_string(header, code, bp, CONSTRUCTED_DT, operator);
563  generate_make(header, code, bp, CONSTRUCTED_DT, operator);
564  fprintf(header, "\n");
565  generate_struct_members(header, bp, CONSTRUCTED_DT, operator);
566  generate_access_members(header, bp, CONSTRUCTED_DT, operator);
567 }
568 
569 /* other types (direct * {} [])
570  */
572  FILE * header,
573  FILE * code,
574  struct gen_binding * bp,
575  int domain_type)
576 {
577  generate_make(header, code, bp, domain_type, UNDEF_OP);
578  fprintf(header, "\n");
579  generate_struct_members(header, bp, domain_type, UNDEF_OP);
580  generate_access_members(header, bp, domain_type, UNDEF_OP);
581 }
582 
583 /* newgen function (->) specific stuff
584  */
585 static void generate_arrow(
586  FILE * header,
587  FILE * code,
588  struct gen_binding * bp)
589 {
590  union domain * dom, * key, * val;
591  string name, kname, vname, Name;
592  char kc, vc;
593 
594  dom = bp->domain;
595  key = dom->co.components->domain;
596  val = dom->co.components->cdr->domain;
597 
598  name = bp->name;
599  Name = strup(name);
600  // To deal with long int version:
601  kname = newgen_argument_type_name(key);
602  vname = newgen_argument_type_name(val);
603 
604  /* how to extract the key and value from the hash_table chunks.
605  */
606  kc = newgen_access_name(key);
607  if (kc=='\0') kc = 'p';
608  vc = newgen_access_name(val);
609  if (vc=='\0') vc = 'p';
610 
611  fprintf(
612  header,
613  "#define %s_key_type %s\n"
614  "#define %s_value_type %s\n"
615  "#define %s_MAP(k,v,c,f) FUNCTION_MAP(%s,%c,%c,k,v,c,f)\n"
616  "#define %s_FOREACH(k,v,f) FUNCTION_FOREACH(%s,%c,%c,k,v,f)\n"
617  "extern %s apply_%s(%s, %s);\n"
618  "extern void update_%s(%s, %s, %s);\n"
619  "extern void extend_%s(%s, %s, %s);\n"
620  "extern %s delete_%s(%s, %s);\n"
621  "extern bool bound_%s_p(%s, %s);\n",
622  name, kname, // key type
623  name, vname, // val type
624  Name, name, kc, vc, // MAP
625  Name, name, kc, vc, // FUNCTION
626  vname, name, name, kname, // apply
627  name, name, kname, vname, // update
628  name, name, kname, vname, // extend
629  vname, name, name, kname, // delete
630  name, name, kname // bound_p
631  );
632 
633  fprintf(code,
634  "%s apply_%s(%s f, %s k) {\n"
635  " return (%s) (intptr_t)HASH_GET(%c, %c, %s_hash_table(f), k);\n"
636  "}\n"
637  "void update_%s(%s f, %s k, %s v) {\n"
638  " HASH_UPDATE(%c, %c, %s_hash_table(f), k, (intptr_t)v);\n"
639  "}\n"
640  "void extend_%s(%s f, %s k, %s v) {\n"
641  " HASH_EXTEND(%c, %c, %s_hash_table(f), k, (intptr_t)v);\n"
642  "}\n"
643  "%s delete_%s(%s f, %s k) {\n"
644  " return (%s)(intptr_t) HASH_DELETE(%c, %c, %s_hash_table(f), k);\n"
645  "}\n"
646  "bool bound_%s_p(%s f, %s k) {\n"
647  " return (intptr_t)HASH_BOUND_P(%c, %c, %s_hash_table(f), k);\n"
648  "}\n",
649  vname, name, name, kname, vname, kc, vc, name, /* apply */
650  name, name, kname, vname, kc, vc, name, /* update */
651  name, name, kname, vname, kc, vc, name, /* extend */
652  vname, name, name, kname, vname, kc, vc, name, /* delete */
653  name, name, kname, kc, vc, name /* bound_p */);
654 
655  free(Name);
656 }
657 
658 /* generates a needed type declaration.
659  */
660 static void
662  FILE * out,
663  struct gen_binding * bp,
664  string file)
665 {
666  string name = bp->name, Name = strup(name);
667  int index = TYPE(bp);
668 
669  if (!IS_EXTERNAL(bp) && !IS_IMPORT(bp))
670  fprintf(out,
671  "#define %s_domain (_gen_%s_start+%d)\n",
672  name, file, index);
673 
674  fprintf(out,
675  "#if !defined(_newgen_%s_domain_defined_)\n"
676  "#define _newgen_%s_domain_defined_\n",
677  name, name);
678 
679  if (IS_EXTERNAL(bp))
680  /* kind of a bug here: if the very same externals appears
681  * several times, they are not sure to be attributed the same
682  * number in different files with different include orders.
683  * externals should really be global?
684  */
685  fprintf(out,
686  "#define newgen_%s(p) (p) /* old hack compatible */\n"
687  "#define %s_NEWGEN_EXTERNAL (_gen_%s_start+%d)\n"
688  "#define %s_NEWGEN_DOMAIN (%s_NEWGEN_EXTERNAL)\n"
689  "#define %s_NEWGEN_DOMAIN (%s_NEWGEN_EXTERNAL)\n",
690  name,
691  Name, file, index,
692  Name, Name,
693  name, Name);
694  else
695  /* should not run if IS_IMPORT(bp)??? */
696  fprintf(out,
697  "#define %s_NEWGEN_DOMAIN (%s_domain)\n"
698  "#define %s_NEWGEN_DOMAIN (%s_domain)\n"
699  "typedef struct " STRUCT "%s_ * %s;\n",
700  Name, name,
701  name, name,
702  name, name);
703 
704  fprintf(out, "#endif /* _newgen_%s_domain_defined_ */\n\n", name);
705  free(Name);
706 }
707 
708 /* generate the needed stuff for bp.
709  */
710 static void
712  FILE * header,
713  FILE * code,
714  struct gen_binding * bp)
715 {
716  union domain * dp = bp->domain;
717  string name = bp->name, Name = strup(bp->name);
718 
719  if (!IS_EXTERNAL(bp)) {
720  /* assumes a preceeding safe definition.
721  * non specific (and/or...) stuff.
722  */
723  fprintf(header,
724  "/* %s\n */\n"
725  "#define %s(x) ((%s)((x).p))\n"
726  // foo_CAST FOO_CAST
727  "#define %s_CAST(x) %s(x)\n"
728  "#define %s_CAST(x) %s(x)\n"
729  "#define %s_(x) ((x).e)\n"
730  // foo_TYPE FOO_TYPE
731  "#define %s_TYPE %s\n"
732  "#define %s_TYPE %s\n"
733  "#define %s_undefined ((%s)gen_chunk_undefined)\n"
734  "#define %s_undefined_p(x) ((x)==%s_undefined)\n"
735  /* what about assignment with checks?
736  // something like:
737  // #define FOO_assign(r,v) \
738  // { FOO * _p = &(r), _v = (v); \
739  // FOO_check(r); FOO_check(v); \
740  // *_p = _v; \
741  // }
742  */
743  "\n"
744  "extern %s copy_%s(%s);\n"
745  "extern void free_%s(%s);\n"
746  "extern %s check_%s(%s);\n"
747  "extern bool %s_consistent_p(%s);\n"
748  "extern bool %s_defined_p(%s);\n"
749  "#define gen_%s_cons gen_%s_cons\n"
750  "extern list gen_%s_cons(%s, list);\n"
751  "extern void %s_assign_contents(%s, %s);\n"
752  "extern void %s_non_recursive_free(%s);\n",
753  Name, // comments
754  Name, name, // defines...
755  name, Name,
756  Name, Name,
757  Name,
758  Name, name, // XXX_TYPE
759  name, name, // xxx_TYPE
760  name, name,
761  name, name,
762  name, name, name, // copy
763  name, name, // free
764  name, name, name, // check
765  name, name, // consistent
766  name, name, // defined
767  Name, name, // gen cons
768  name, name,
769  name, name, name, // assign contents
770  name, name // non recursive free
771  );
772 
773  fprintf(code,
774  "/* %s\n */\n"
775  "%s copy_%s(%s p) {\n"
776  " return (%s) gen_copy_tree((gen_chunk*) p);\n"
777  "}\n"
778  "void free_%s(%s p) {\n"
779  " gen_free((gen_chunk*) p);\n"
780  "}\n"
781  "%s check_%s(%s p) {\n"
782  " return (%s) gen_check((gen_chunk*) p, %s_domain);\n"
783  "}\n"
784  "bool %s_consistent_p(%s p) {\n"
785  " check_%s(p);\n"
786  " return gen_consistent_p((gen_chunk*) p);\n"
787  "}\n"
788  "bool %s_defined_p(%s p) {\n"
789  " return gen_defined_p((gen_chunk*) p);\n"
790  "}\n"
791  "list gen_%s_cons(%s p, list l) {\n"
792  " return gen_typed_cons(%s_NEWGEN_DOMAIN, p, l);\n"
793  "}\n"
794  "void %s_assign_contents(%s r, %s v) {\n"
795  " check_%s(r);\n"
796  " check_%s(v);\n"
797  " message_assert(\"defined references to domain %s\",\n"
798  " %s_defined_p(r) && %s_defined_p(v));\n"
799  " memcpy(r, v, sizeof(struct " STRUCT "%s_));\n"
800  "}\n"
801  "void %s_non_recursive_free(%s p) {\n"
802  " // should clear up contents...\n"
803  " free(p);\n"
804  "}\n",
805  Name, // comments
806  name, name, name, name, // copy
807  name, name, // free
808  name, name, name, name, name, // check
809  name, name, name, // consistent
810  name, name, // consistent
811  name, name, Name, // gen cons
812  name, name, name, // assign contents
813  name, name, name, name, name, name,
814  name, name // non recursive free
815  );
816 
817  if (IS_TABULATED(bp)) {
818  /* tabulated */
819  fprintf(header,
820  "extern %s gen_find_%s(char *);\n"
821  "extern void write_tabulated_%s(FILE *);\n"
822  "extern void read_tabulated_%s(FILE *);\n",
823  name, name, /* find */
824  name, /* write */
825  name /* read */);
826  fprintf(code,
827  "%s gen_find_%s(char* s) {\n"
828  " return (%s) gen_find_tabulated(s, %s_domain);\n"
829  "}\n"
830  "void write_tabulated_%s(FILE* f) {\n"
831  " (void) gen_write_tabulated(f, %s_domain);\n"
832  "}\n"
833  "void read_tabulated_%s(FILE* f) {\n"
834  " int domain = gen_read_tabulated(f, 0);\n"
835  " if (domain!=%s_domain) {\n"
836  " fprintf(stderr, " DomainNumberError ",\n"
837  " domain, %s_domain);\n"
838  " abort();\n"
839  " }\n"
840  "}\n",
841  name, name, name, name, /* find */
842  name, name, /* write */
843  name, name, name, name /* read */);
844  }
845  else {
846  /* NOT tabulated */
847  fprintf(header,
848  "extern void write_%s(FILE*, %s);\n"
849  "extern %s read_%s(FILE*);\n",
850  name, name, /* write */
851  name, name /* read */);
852  fprintf(code,
853  "void write_%s(FILE* f, %s p) {\n"
854  " gen_write(f, (gen_chunk*) p);\n"
855  "}\n"
856  "%s read_%s(FILE* f) {\n"
857  " return (%s) gen_read(f);\n"
858  "}\n",
859  name, name, /* write */
860  name, name, name /* read */);
861  }
862  }
863 
864  switch (dp->ba.type) {
865  case CONSTRUCTED_DT:
866  switch (dp->co.op) {
867  case AND_OP:
868  generate_constructed(header, code, bp, AND_OP);
869  break;
870  case OR_OP:
871  generate_constructed(header, code, bp, OR_OP);
872  break;
873  case ARROW_OP:
874  generate_constructed(header, code, bp, ARROW_OP);
875  generate_arrow(header, code, bp);
876  break;
877  default:
878  fatal("[generate_domain] unexpected constructed %d\n", dp->co.op);
879  }
880  break;
881  case LIST_DT:
882  generate_not_constructed(header, code, bp, LIST_DT);
883  break;
884  case SET_DT:
885  generate_not_constructed(header, code, bp, SET_DT);
886  break;
887  case ARRAY_DT:
888  generate_not_constructed(header, code, bp, ARRAY_DT);
889  break;
890  case EXTERNAL_DT:
891  /* nothing to generate at the time. */
892  break;
893  default:
894  fatal("[generate_domain] unexpected domain type %d\n", dp->ba.type);
895  }
896 
897  fprintf(header, "\n");
898  fprintf(code, "\n");
899 
900  free(Name);
901 }
902 
903 /* fopen prefix + suffix.
904  */
905 static FILE * fopen_suffix(string prefix, string suffix)
906 {
907  FILE * f;
908  string r = (string) malloc(strlen(prefix)+strlen(suffix)+1);
909  if (r==NULL) fatal("[fopen_suffix] no more memory\n");
910  strcpy(r, prefix);
911  strcat(r, suffix);
912  f = fopen(r, "w");
913  if (f==NULL) fatal("[fopen_suffix] of %s failed\n", r);
914  free(r);
915  return f;
916 }
917 
918 #define DONT_TOUCH \
919  "/*\n" \
920  " * THIS FILE HAS BEEN AUTOMATICALLY GENERATED BY NEWGEN.\n" \
921  " *\n" \
922  " * PLEASE DO NOT MODIFY IT.\n" \
923  " */\n\n"
924 
925 /* generate the code necessary to manipulate every internal
926  * non-inlinable type in the Domains table.
927  */
928 void gencode(string file)
929 {
930  // Just a hack to pretend we use these functions
931  void * no_warning = &sharp_ifopt - &sharp_else + &sharp_endif;
932  int i;
933  FILE * header, * code;
934 
935  if (file==NULL)
936  fatal("[gencode] no file name specified (%p)\n", no_warning);
937 
938  if (sizeof(void *)!=sizeof(gen_chunk))
939  fatal("[gencode] newgen fundamental layout hypothesis broken\n");
940 
941  /* header = fopen_suffix(file, ".h"); */
942  header = stdout;
943  code = fopen_suffix(file, ".c");
944 
945  fprintf(header, DONT_TOUCH);
947 
948  for (i=0; i<MAX_DOMAIN; i++) {
949  struct gen_binding * bp = &Domains[i];
950  if (bp->name && !IS_INLINABLE(bp) && !IS_TAB(bp))
951  if (IS_EXTERNAL(bp))
952  fprintf(code, "typedef void * %s;\n", bp->name);
953  }
954 
955  fprintf(code,
956  "\n"
957  "#include <stdio.h>\n"
958  "#include <stdlib.h>\n"
959  "#include <string.h>\n"
960  "#include \"genC.h\"\n"
961  "#include \"%s.h\"\n"
962  "\n",
963  file);
964 
965  /* first generate protected forward declarations.
966  */
967  for (i=0; i<MAX_DOMAIN; i++) {
968  struct gen_binding * bp = &Domains[i];
969  if (bp->name && !IS_INLINABLE(bp) && !IS_TAB(bp))
970  generate_safe_definition(header, bp, file);
971  }
972 
973  /* then generate actual declarations.
974  */
975  for (i=0; i<MAX_DOMAIN; i++) {
976  struct gen_binding * bp = &Domains[i];
977  if (bp->name && !IS_INLINABLE(bp) && !IS_IMPORT(bp) && !IS_TAB(bp))
978  generate_domain(header, code, bp);
979  }
980 
981  /* fclose(header); */
982  fclose(code);
983 }
static FILE * out
Definition: alias_check.c:128
static Value offset
Definition: translation.c:283
static bool inline_directly(union domain *dp)
Definition: genC.c:119
static int sharp_ifopt(FILE *out)
Might be used to generate optimized versions (say macros instead of functions).
Definition: genC.c:59
#define DONT_TOUCH
Definition: genC.c:918
static string int_type(void)
bof...
Definition: genC.c:135
static int sharp_endif(FILE *out)
Definition: genC.c:65
int gen_size(int domain)
GEN_SIZE returns the size (in gen_chunks) of an object of type defined by the BP type.
Definition: genC.c:71
#define TYPE(bp)
non user domain must be taken care from outside?
Definition: genC.c:50
static string int_type_access_complement(void)
Definition: genC.c:140
static string strup(string s)
returns s duplicated and case-uppered.
Definition: genC.c:110
void gencode(string file)
generate the code necessary to manipulate every internal non-inlinable type in the Domains table.
Definition: genC.c:928
static void generate_safe_definition(FILE *out, struct gen_binding *bp, string file)
generates a needed type declaration.
Definition: genC.c:661
static void generate_struct_members(FILE *out, struct gen_binding *bp, int domain_type, int operator)
generate the struct for bp.
Definition: genC.c:370
static int sharp_else(FILE *out)
Definition: genC.c:62
static string newgen_kind_label(union domain *dp)
just to generate comprehensive comments.
Definition: genC.c:216
static string newgen_type_name(union domain *dp)
newgen type name for holder.
Definition: genC.c:148
static void generate_arrow(FILE *header, FILE *code, struct gen_binding *bp)
newgen function (->) specific stuff
Definition: genC.c:585
#define DomainNumberError
Definition: genC.c:52
static void generate_union_as_string(FILE *header, FILE *code, struct gen_binding *bp, int domain_type, int operator)
introspection function.
Definition: genC.c:454
static string newgen_argument_type_name(union domain *dp)
C type name for generated function arguments.
Definition: genC.c:179
#define STRUCT
Definition: genC.c:42
static void generate_union_type_descriptor(FILE *out, struct gen_binding *bp, int domain_type, int operator)
Definition: genC.c:428
static void generate_make(FILE *header, FILE *code, struct gen_binding *bp, int domain_type, int operator)
make is bigger, thus I put it in a separate function.
Definition: genC.c:228
#define same_size(t)
Definition: genC.c:117
#define OPTIMIZE_NEWGEN
Definition: genC.c:44
#define IS_TAB(x)
Definition: genC.c:46
static void generate_domain(FILE *header, FILE *code, struct gen_binding *bp)
generate the needed stuff for bp.
Definition: genC.c:711
#define FIELD
Definition: genC.c:41
static void generate_not_constructed(FILE *header, FILE *code, struct gen_binding *bp, int domain_type)
other types (direct * {} [])
Definition: genC.c:571
static void generate_access_members(FILE *out, struct gen_binding *bp, int domain_type, int operator)
access to members are managed thru macros.
Definition: genC.c:490
static string newgen_type_name_close(union domain *dp)
Definition: genC.c:196
static void generate_constructed(FILE *header, FILE *code, struct gen_binding *bp, int operator)
constructed types: + x (and ->...)
Definition: genC.c:555
static FILE * fopen_suffix(string prefix, string suffix)
fopen prefix + suffix.
Definition: genC.c:905
static char newgen_access_name(union domain *dp)
what to add to the field to access a given primitive type, which was typically declared as a gen_chun...
Definition: genC.c:206
#define GEN_HEADER
include <sys/stdtypes.h>
Definition: genC.h:45
void * malloc(YYSIZE_T)
void free(void *)
struct gen_binding Domains[MAX_DOMAIN]
in build.c
Definition: genspec_yacc.c:114
char * i2a(int)
I2A (Integer TO Ascii) yields a string for a given Integer.
Definition: string.c:121
@ ARROW_OP
@ OR_OP
@ AND_OP
@ UNDEF_OP
#define IS_EXTERNAL(bp)
#define IS_INLINABLE(bp)
Different kinds of BINDING structure pointers.
@ EXTERNAL_DT
@ SET_DT
@ ARRAY_DT
@ LIST_DT
@ BASIS_DT
@ CONSTRUCTED_DT
#define MAX_DOMAIN
MAX_DOMAIN is the maximum number of entries in the DOMAINS table.
void fatal(char *,...)
#define IS_IMPORT(bp)
#define IS_TABULATED(bp)
#define same_string_p(s1, s2)
#define UNIT_TYPE_NAME
The UNIT_TYPE_NAME is the used to type expressions which only perform side-effects.
char * string
STRING.
Definition: newgen_types.h:39
int unit
UNIT.
Definition: newgen_types.h:97
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
static const char * prefix
struct _newgen_struct_code_ * code
Definition: ri.h:79
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
#define intptr_t
Definition: stdint.in.h:294
union domain * domain
A DOMAIN union describes the structure of a user type.
char * constructor
struct gen_binding * element
enum domain_operator op
struct domainlist * components
struct domain::@7 co
int type
EXTERNAL.
struct domain::@3 ba
struct gen_binding * constructand
struct domain::@6 ar
A gen_chunk is used to store every object.
Definition: genC.h:58