80ce04ae5b02349a3cb9080550c3e0a0632d35cc
[libfirm] / ir / external / read.c
1 /* -*- c -*- */
2
3 /*
4  * Project:     libFIRM
5  * File name:   ir/external/read.c
6  * Purpose:     Read descriptions of external effects
7  * Author:      Florian
8  * Modified by:
9  * Created:     11.10.2004
10  * CVS-ID:      $$
11  * Copyright:   (c) 1999-2004 Universität Karlsruhe
12  * Licence:     This file is protected by GPL -  GNU GENERAL PUBLIC LICENSE.
13  */
14
15 # define _GNU_SOURCE
16 # include "read.h"
17
18 static type_t *types = NULL;
19 static entity_t *entities = NULL;
20 static effs_t *effs = NULL;
21
22 static int _ent_id = 0;
23 /* static int _node_id = 0; */
24
25 static const char*
26 getNodeModule (xmlNodePtr node)
27 {
28   const char *mod_str = (const char*) xmlGetProp (node, BAD_CAST "module");
29
30   if (NULL == mod_str) {
31     return (NULL);
32   } else {
33     char *res = strdup (mod_str);
34
35     return (res);
36   }
37 }
38
39 static char*
40 getNodeProcName (xmlNodePtr node)
41 {
42   char *proc_str = (char*) xmlGetProp (node, BAD_CAST "procname");
43
44   assert (proc_str);
45
46   return (strdup (proc_str));
47 }
48
49 static const int
50 getNodeId (xmlNodePtr node)
51 {
52   char *id_str = (char*) xmlGetProp (node, BAD_CAST "id");
53   int id;
54   assert (id_str);
55   id = atoi (id_str+1);
56
57   return (id);
58 }
59
60 static const int
61 getNodeRefId (xmlNodePtr node)
62 {
63   char *refid_str = (char*) xmlGetProp (node, BAD_CAST "refid");
64   int refid;
65   assert (refid_str);
66   refid = atoi (refid_str+1);
67
68   return (refid);
69 }
70
71 static const int
72 getNodeTypeId (xmlNodePtr node)
73 {
74   char *type_str = (char*) xmlGetProp (node, BAD_CAST "type");
75   int type_id;
76   assert (type_str);
77   type_id = atoi (type_str+1);
78
79   return (type_id);
80 }
81
82 static const char
83 *getNodeTypeStr (xmlNodePtr node)
84 {
85   const char *type_str = (char*) xmlGetProp (node, BAD_CAST "type");
86   assert (type_str);
87
88   return (type_str);
89 }
90
91 static const char
92 *getNodeEntityStr (xmlNodePtr node)
93 {
94   const char *ent_str = (char*) xmlGetProp (node, BAD_CAST "entity");
95   assert (ent_str);
96
97   return (ent_str);
98 }
99
100 static arg_t *
101 parseArg (xmlDocPtr doc, xmlNodePtr argelm)
102 {
103   int id;
104   int num;
105   char *num_str;
106   arg_t *arg;
107
108   CHECK_NAME (argelm, arg);
109   /* fprintf (stdout, "arg node \t0x%08x\n", (int) argelm); */
110
111   id = getNodeId (argelm);
112   /* fprintf (stdout, "arg->id = \"%d\"\n", id); */
113   num_str = (char*) xmlGetProp (argelm, BAD_CAST "number");
114   num = atoi (num_str);
115   /* fprintf (stdout, "arg->no = \"%d\"\n", no); */
116
117   arg = NEW (arg_t);
118   arg->kind = eff_arg;
119   arg->id = id;
120   arg->num = num;
121
122   return (arg);
123 }
124
125 static valref_t
126 *parseValref (xmlDocPtr doc, xmlNodePtr valelm)
127 {
128   int ref_id;
129   valref_t *valref;
130   CHECK_NAME (valelm, valref);
131   /* fprintf (stdout, "valref node \t0x%08x\n", (int) valelm); */
132
133   ref_id = getNodeRefId (valelm);
134   /* fprintf (stdout, "val->refid = \"%d\"\n", ref_id); */
135
136   valref = NEW (valref_t);
137   valref->kind = eff_valref;
138   valref->refid = ref_id;
139
140   return (valref);
141 }
142
143 static select_t
144 *parseSelect (xmlDocPtr doc, xmlNodePtr selelm)
145 {
146   char *entity_str = (char*) xmlGetProp (selelm, BAD_CAST "entity");
147   const int entity_id = atoi (entity_str+1);
148   entity_t *ent;
149   xmlNodePtr child;
150   valref_t *valref = NULL;
151   select_t *sel = NEW (select_t);
152   sel->kind = eff_select;
153
154   CHECK_NAME (selelm, select);
155   /* fprintf (stdout, "select node \t0x%08x\n", (int) selelm); */
156
157   ent = getEntityById (entity_id);
158
159   child = selelm->xmlChildrenNode;
160
161   if (child) {
162     valref = parseValref (doc, child);
163   }
164
165   sel->valrefid = valref ? valref->refid : -1;
166   sel->ent = ent;
167
168   if (valref) {
169     free (valref);
170   }
171
172   return (sel);
173 }
174
175 static load_t
176 *parseLoad (xmlDocPtr doc, xmlNodePtr loadelm)
177 {
178   int id;
179   xmlNodePtr child;
180   select_t *sel;
181   load_t *load = NEW (load_t);
182   load->kind = eff_load;
183
184   CHECK_NAME (loadelm, load);
185   /* fprintf (stdout, "load node \t0x%08x\n", (int) loadelm); */
186   id = getNodeId (loadelm);
187
188   child = loadelm->xmlChildrenNode;
189
190   sel = parseSelect (doc, child);
191
192   load->id = id;
193   load->ptrrefid = sel->valrefid;
194   load->ent = sel->ent;
195
196   free (sel);
197
198   return (load);
199 }
200
201 static store_t
202 *parseStore (xmlDocPtr doc, xmlNodePtr storeelm)
203 {
204   xmlNodePtr child;
205   select_t *sel;
206   valref_t *valref;
207   store_t *store = NEW (store_t);
208   store->kind = eff_store;
209
210   CHECK_NAME (storeelm, store);
211   /* fprintf (stdout, "store node \t0x%08x\n", (int) storeelm); */
212
213   child = storeelm->xmlChildrenNode;
214
215   sel = parseSelect (doc, child);
216
217   child = child->next;
218
219   valref = parseValref (doc, child);
220
221   store->ent = sel->ent;
222   store->ptrrefid = sel->valrefid;
223   store->valrefid = valref->refid;
224
225   free (sel);
226   free (valref);
227
228   return (store);
229 }
230
231 static alloc_t
232 *parseAlloc (xmlDocPtr doc, xmlNodePtr allocelm)
233 {
234   int id;
235   int type_id;
236   alloc_t *alloc = NEW (alloc_t); /* ...! */
237   alloc->kind = eff_alloc;
238
239   CHECK_NAME (allocelm, alloc);
240   /* fprintf (stdout, "alloc node \t0x%08x\n", (int) allocelm); */
241   id = getNodeId (allocelm);
242   /* fprintf (stdout, "alloc->id = \"%d\"\n", id); */
243   type_id = getNodeTypeId (allocelm);
244   /* fprintf (stdout, "alloc->type_id = \"%d\"\n", type_id); */
245
246   alloc->id = id;
247   alloc->tp_id = type_id;
248
249   return (alloc);
250 }
251
252 static call_t
253 *parseCall (xmlDocPtr doc, xmlNodePtr callelm)
254 {
255   int id;
256   xmlNodePtr child;
257   select_t *sel;
258   xmlNodePtr arg;
259   int n_args;
260   call_t *call = NEW (call_t);
261   call->kind = eff_call;
262
263   CHECK_NAME (callelm, call);
264   /* fprintf (stdout, "call node \t0x%08x\n", (int) callelm); */
265   id = getNodeId (callelm);
266   /* fprintf (stdout, "call->id = \"%d\"\n", id); */
267
268   child = callelm->xmlChildrenNode;
269
270   sel = parseSelect (doc, child);
271
272   arg = child = child->next;
273
274   n_args = 0;
275
276   while (NULL != child) {
277     n_args ++;
278
279     child = child->next;
280   }
281
282   call->id = id;
283   call->valrefid = sel->valrefid;
284   call->ent = sel->ent;
285   call->n_args = n_args;
286   call->args = NULL;
287
288   free (sel);
289
290   if (0 != n_args) {
291     int *args = (int*) malloc (n_args * sizeof (int) );
292     int i = 0;
293
294     while (NULL != arg) {
295       valref_t *valref = parseValref (doc, arg);
296       args [i ++] = valref->refid;
297       free (valref);
298
299       arg = arg->next;
300     }
301
302     call->args = args;
303   }
304
305   return (call);
306 }
307
308 static join_t
309 *parseJoin (xmlDocPtr doc, xmlNodePtr joinelm)
310 {
311   int id;
312   int n_ins;
313   int *ins;
314   int i;
315   xmlNodePtr child;
316   join_t *join = NEW (join_t);
317   join->kind = eff_join;
318
319   CHECK_NAME (joinelm, join);
320   /* fprintf (stdout, "join node \t0x%08x\n", (int) joinelm); */
321   id = getNodeId (joinelm);
322   /* fprintf (stdout, "join->id = \"%d\"\n", id); */
323
324   child = joinelm->xmlChildrenNode;
325
326   n_ins = 0;
327
328   while (NULL != child) {
329     n_ins ++;
330     child = child->next;
331   }
332
333   ins = (int*) malloc (n_ins * sizeof (int) );
334   i = 0;
335
336   child = joinelm->xmlChildrenNode;
337
338   while (NULL != child) {
339     valref_t *valref = parseValref (doc, child);
340     ins [i ++] = valref->refid;
341
342     child = child->next;
343   }
344
345   join->id = id;
346   join->n_ins = n_ins;
347   join->ins = ins;
348
349   return (join);
350 }
351
352 static unknown_t
353 *parseUnknown (xmlDocPtr doc, xmlNodePtr unknownelm)
354 {
355   int id;
356   unknown_t *unknown = NEW (unknown_t);
357   unknown->kind = eff_unknown;
358
359   CHECK_NAME (unknownelm, unknown);
360   /* fprintf (stdout, "unknown node \t0x%08x\n", (int) unknownelm); */
361   id = getNodeId (unknownelm);
362
363   unknown->id = id;
364
365   return (unknown);
366 }
367
368 static ret_t
369 *parseReturn (xmlDocPtr doc, xmlNodePtr retelm)
370 {
371   xmlNodePtr child;
372   ret_t *ret = NEW (ret_t);
373   ret->kind = eff_ret;
374
375   CHECK_NAME (retelm, ret);
376   /* fprintf (stdout, "ret node \t0x%08x\n", (int) retelm); */
377
378   child = retelm->xmlChildrenNode;
379
380   if (child) {
381     valref_t *valref = parseValref (doc, child);
382     ret->ret_id = valref->refid;
383     free (valref);
384   } else {
385     ret->ret_id = -1;
386   }
387
388   return (ret);
389 }
390
391 static raise_t
392 *parseRaise (xmlDocPtr doc, xmlNodePtr raiseelm)
393 {
394   int tp_id;
395   valref_t *valref;
396   xmlNodePtr child;
397   raise_t *raise = NEW (raise_t);
398   raise->kind = eff_raise;
399
400   CHECK_NAME (raiseelm, raise);
401   /* fprintf (stdout, "raise node \t0x%08x\n", (int) raiseelm); */
402
403   tp_id = getNodeTypeId (raiseelm);
404   /* fprintf (stdout, "raise->type = \"%d\"\n", tp_id); */
405
406   child = raiseelm->xmlChildrenNode;
407
408   assert (NULL != child);
409
410   valref = parseValref (doc, child);
411
412   raise->valref = valref->refid;
413   raise->tp_id = tp_id;
414
415   free (valref);
416
417   return (raise);
418 }
419
420 /*
421   Types and Entities
422 */
423
424 /** parse a type node and insert it into the list */
425 static void
426 parseType (xmlDocPtr doc, xmlNodePtr typeelm)
427 {
428   type_t *type;
429   const int tp_id = getNodeId (typeelm);
430   /* fprintf (stdout, "type node \t0x%08x (%d)\n", (int) typeelm, tp_id); */
431   fprintf (stdout, "type = \"%s\"\n", getNodeTypeStr (typeelm));
432
433   type = (type_t*) malloc (sizeof (type_t));
434
435   type->name = (char*) strdup (getNodeTypeStr (typeelm));
436   type->id = tp_id;
437
438   type->prev = types;
439   types = type;
440
441   if (_ent_id <= tp_id) {
442     _ent_id = tp_id+1;
443   }
444 }
445
446 /** parse an entity node and insert it into the list */
447 static void
448 parseEntity (xmlDocPtr doc, xmlNodePtr entelm)
449 {
450   entity_t *ent = NEW (entity_t);
451
452   /* parse it */
453   const int ent_id = getNodeId (entelm);
454   /* fprintf (stdout, "entity node \t0x%08x (%d)\n", (int) entelm, ent_id); */
455   fprintf (stdout, "ent  = \"%s.%s\"\n",
456            getNodeTypeStr (entelm),
457            getNodeEntityStr (entelm));
458
459
460   ent->name    = (char*) strdup (getNodeEntityStr (entelm));
461   ent->tp_name = (char*) strdup (getNodeTypeStr   (entelm));
462   ent->id = ent_id;
463
464   ent->prev = entities;
465   entities = ent;
466
467   if (_ent_id <= ent_id) {
468     _ent_id = ent_id+1;
469   }
470 }
471
472 /** parse any effect, and turn it into an eff_t (TODO) */
473 static void
474 parseEffect (xmlDocPtr doc, xmlNodePtr effelm)
475 {
476   xmlNodePtr cur = effelm->xmlChildrenNode;
477   char *procname = getNodeProcName (effelm);
478   effs_t *curr_effs = NULL;
479   int i = 0;
480   int n_effs = 0;
481
482   fprintf (stdout, "effect for \"%s\"\n", procname);
483
484   while (NULL != cur) {
485     n_effs ++;
486     cur = cur->next;
487   }
488
489   curr_effs = NEW (effs_t);
490   curr_effs->procname = procname;
491   curr_effs->n_effs = n_effs;
492   curr_effs->effs = (eff_t**) malloc (n_effs * sizeof (eff_t*));
493
494   while (NULL != cur) {
495     eff_t *eff = NULL;
496
497     if (NODE_NAME (cur, arg)) {
498       eff = (eff_t*) parseArg (doc, cur);
499     } else if (NODE_NAME (cur, load)) {
500       eff = (eff_t*) parseLoad (doc, cur);
501     } else if (NODE_NAME (cur, store)) {
502       eff = (eff_t*) parseStore (doc, cur);
503     } else if (NODE_NAME (cur, alloc)) {
504       eff = (eff_t*) parseAlloc (doc, cur);
505     } else if (NODE_NAME (cur, call)) {
506       eff = (eff_t*) parseCall (doc, cur);
507     } else if (NODE_NAME (cur, join)) {
508       eff = (eff_t*) parseJoin (doc, cur);
509     } else if (NODE_NAME (cur, unknown)) {
510       eff = (eff_t*) parseUnknown (doc, cur);
511     } else if (NODE_NAME (cur, ret)) {
512       eff = (eff_t*) parseReturn (doc, cur);
513     } else if (NODE_NAME (cur, raise)) {
514       eff = (eff_t*) parseRaise (doc, cur);
515     } else if (NODE_NAME (cur, comment)) {
516       /* comment */
517     } else {
518       fprintf (stderr, "wrong element \"%s\"\n", BAD_CAST cur->name);
519       exit (EXIT_FAILURE);
520     }
521
522     cur = cur->next;
523
524     curr_effs->effs [i ++] = eff;
525   }
526
527   curr_effs->next = effs;
528   effs = curr_effs;
529 }
530
531 /*
532   Public Interface
533 */
534 type_t *getTypeByName (const char *name)
535 {
536   type_t *curr = types;
537
538   while (NULL != curr) {
539     if (0 == strcmp (name, curr->name)) {
540       return (curr);
541     }
542
543     curr = curr->prev;
544   }
545
546   return (NULL);
547 }
548
549 type_t *getTypeById (const int id)
550 {
551   type_t *curr = types;
552
553   while (NULL != curr) {
554     if (id == curr->id) {
555       return (curr);
556     }
557
558     curr = curr->prev;
559   }
560
561   return (NULL);
562 }
563
564 entity_t *getEntityByNames (const char *name, const char *tp_name)
565 {
566   entity_t *curr = entities;
567
568   while (NULL != curr) {
569     if ((0 == strcmp (name, curr->name)) && (0 == strcmp (tp_name, curr->tp_name))) {
570       return (curr);
571     }
572
573     curr = curr->prev;
574   }
575
576   return (NULL);
577 }
578
579 entity_t *getEntityById (const int id)
580 {
581   entity_t *curr = entities;
582
583   while (NULL != curr) {
584     if (id == curr->id) {
585       return (curr);
586     }
587
588     curr = curr->prev;
589   }
590
591   return (NULL);
592 }
593
594 effs_t *getEffectByName (const char *procname)
595 {
596   effs_t *curr_effs = effs;
597
598   while (NULL != curr_effs) {
599     if (0 == strcmp (procname, curr_effs->procname)) {
600       return (curr_effs);
601     }
602
603     curr_effs = curr_effs->next;
604   }
605
606   return (NULL);
607 }
608
609 void extern_init ()
610 {
611   /* nothing to do */
612 }
613
614 void extern_read (const char *filename)
615 {
616   /* xmlNsPtr ns = NULL; */           /* no namespace for us */
617   xmlDocPtr doc;                /* whole document */
618   xmlNodePtr cur;               /* current node */
619
620   /* i've got no idea what the VERSION cast is all about. voodoo
621      programming at its finest. */
622   LIBXML_TEST_VERSION xmlKeepBlanksDefault (0);
623   doc = xmlParseFile (filename);
624   CHECK (doc, "xmlParseFile");
625
626   cur = xmlDocGetRootElement (doc);
627   CHECK (cur, "xmlDocGetRootElement");
628
629   if (! NODE_NAME (cur, effects)) {
630     fprintf (stderr,"root node \"%s\" != \"effects\"\n", BAD_CAST cur->name);
631     xmlFreeDoc (doc);
632
633     exit (EXIT_FAILURE);
634   }
635
636   if (EXTERN_VERBOSE) {
637     const char *mod_str = getNodeModule (cur);
638
639     if (NULL != mod_str) {
640       fprintf (stdout, "effects for \"%s\"\n", mod_str);
641     } else {
642       fprintf (stdout, "effects \t0x%08x\n", (int) cur);
643     }
644   }
645
646   /* parse entities */
647   cur = cur->xmlChildrenNode;
648   while (cur != NULL) {
649     if (NODE_NAME (cur, type)) {
650       parseType (doc, cur);
651     } else if (NODE_NAME (cur, entity)) {
652       parseEntity (doc, cur);
653     } else if (NODE_NAME (cur, effect)) {
654       parseEffect (doc, cur);
655     } else if ((NODE_NAME (cur, comment))) {
656       /* comment */
657     } else {
658       fprintf (stderr, "wrong element \"%s\"\n", BAD_CAST cur->name);
659       exit (EXIT_FAILURE);
660     }
661
662     cur = cur->next;
663   }
664 }
665
666 /** clean up our mess */
667 void extern_cleanup ()
668 {
669   /* the types */
670   {
671     type_t *tp = types;
672
673     while (NULL != tp) {
674       type_t *curr = tp;
675       tp = tp->prev;
676
677       free ((char*) curr->name);
678       memset (curr, 0x00, sizeof (type_t));
679       free (curr);
680     }
681
682     types = NULL;
683   }
684
685   /* the ennities */
686   {
687     entity_t *ent = entities;
688
689     while (NULL != ent) {
690       entity_t *curr = ent;
691       ent = ent->prev;
692
693       free ((char*) curr->name);
694       free ((char*) curr->tp_name);
695       memset (curr, 0x00, sizeof (entity_t));
696       free (curr);
697     }
698
699     entities = NULL;
700   }
701
702   /* the effs */
703   {
704     effs_t *eff = effs;
705
706     while (NULL != eff) {
707       int i;
708       effs_t *curr = eff;
709       eff = eff->next;
710
711       for (i = 0; i < curr->n_effs; i ++) {
712         free (curr->effs [i]);
713       }
714
715       free (curr);
716     }
717   }
718
719   effs = NULL;
720 }
721
722
723 void test_getEffectByName ()
724 {
725   /* test getEffectByName */
726   char *names [] = {
727     "store_unknown_proc",
728     "rise_something",
729     "other_fake_proc",
730     "ret_alloc",
731     "mash_args",
732     "ret_arg",
733     "empty_external",
734     "no_this_doesn't_really_exist",
735     "my_fake_proc",
736     NULL
737   };
738
739   int i = 0;
740
741   while (NULL != names [i]) {
742     effs_t *the_eff = getEffectByName (names [i]);
743
744     if (the_eff) {
745       fprintf (stdout, "Effect for \"%s\" is at 0x%08x\n",
746                names [i], (int) the_eff);
747     } else {
748       fprintf (stdout, "Effect for \"%s\" not found\n",
749                names [i]);
750     }
751     i ++;
752   }
753 }
754
755
756
757 \f
758 /*
759  * $Log$
760  * Revision 1.3  2004/10/13 13:36:28  rubino
761  * fix for strdup
762  *
763  * Revision 1.2  2004/10/11 15:56:09  liekweg
764  * Cleanup, comments ...
765  * Added init func --flo
766  *
767  * Revision 1.1  2004/10/11 09:31:06  liekweg
768  * First Import of XML reading procs --flo
769  *
770  */