1: /*
2: ================================================================================
3: RPL/2 (R) version 4.1.19
4: Copyright (C) 1989-2014 Dr. BERTRAND Joël
5:
6: This file is part of RPL/2.
7:
8: RPL/2 is free software; you can redistribute it and/or modify it
9: under the terms of the CeCILL V2 License as published by the french
10: CEA, CNRS and INRIA.
11:
12: RPL/2 is distributed in the hope that it will be useful, but WITHOUT
13: ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14: FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL V2 License
15: for more details.
16:
17: You should have received a copy of the CeCILL License
18: along with RPL/2. If not, write to info@cecill.info.
19: ================================================================================
20: */
21:
22:
23: #include "rpl-conv.h"
24:
25:
26: /*
27: ================================================================================
28: Fonction de transcription d'un arbre en liste chaînée
29: ================================================================================
30: Entrées : pointeur sur une structure struct_processus
31: --------------------------------------------------------------------------------
32: Sorties :
33: --------------------------------------------------------------------------------
34: Effets de bord : néant
35: ================================================================================
36: */
37:
38: static struct_liste_chainee *
39: transcription_arbre(struct_processus *s_etat_processus, struct_arbre *s_arbre)
40: {
41: integer8 i;
42:
43: struct_liste_chainee *l_element_courant;
44: struct_liste_chainee *l_liste;
45: struct_liste_chainee *l_nouvelle_pile_locale;
46: struct_liste_chainee *l_pile_locale;
47:
48: l_pile_locale = NULL;
49:
50: for(i = 0; i < (*s_arbre).nombre_branches; i++)
51: {
52: if ((l_nouvelle_pile_locale = allocation_maillon(s_etat_processus))
53: == NULL)
54: {
55: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
56: return(NULL);
57: }
58:
59: (*l_nouvelle_pile_locale).suivant = l_pile_locale;
60: l_pile_locale = l_nouvelle_pile_locale;
61:
62: if (((*l_pile_locale).donnee = (void *) transcription_arbre(
63: s_etat_processus, (*s_arbre).branches[i])) == NULL)
64: {
65: return(NULL);
66: }
67: }
68:
69: if ((l_liste = allocation_maillon(s_etat_processus)) == NULL)
70: {
71: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
72: return(NULL);
73: }
74:
75: // Ajout de la fonction
76:
77: (*l_liste).suivant = NULL;
78: (*l_liste).donnee = (*s_arbre).feuille;
79:
80: free((*s_arbre).branches);
81: free(s_arbre);
82:
83: // Chaînage des arguments
84:
85: while(l_pile_locale != NULL)
86: {
87: l_element_courant = (void *) (*l_pile_locale).donnee;
88:
89: if (l_element_courant == NULL)
90: {
91: (*s_etat_processus).erreur_systeme = d_es_pile_vide;
92: return(NULL);
93: }
94:
95: while((*l_element_courant).suivant != NULL)
96: {
97: l_element_courant = (*l_element_courant).suivant;
98: }
99:
100: (*l_element_courant).suivant = l_liste;
101: l_liste = (void *) (*l_pile_locale).donnee;
102:
103: l_nouvelle_pile_locale = (*l_pile_locale).suivant;
104: liberation_maillon(s_etat_processus, l_pile_locale);
105: l_pile_locale = l_nouvelle_pile_locale;
106: }
107:
108: return(l_liste);
109: }
110:
111:
112: /*
113: ================================================================================
114: Fonction 'simplification' (ne libère pas les paramètres)
115: ================================================================================
116: Entrées : pointeur sur une structure struct_processus
117: --------------------------------------------------------------------------------
118: Sorties :
119: --------------------------------------------------------------------------------
120: Effets de bord : néant
121: ================================================================================
122: */
123:
124: struct_objet *
125: simplification(struct_processus *s_etat_processus, struct_objet *s_objet)
126: {
127: struct_objet *s_objet_simplifie;
128:
129: # ifdef EXPERIMENTAL_CODE
130:
131: integer8 i;
132: integer8 nombre_arguments;
133:
134: struct_arbre *s_arbre;
135:
136: struct_liste_chainee *l_element_courant;
137:
138: // Attention : l_liste_locale et l_ancienne_liste_locale ne contiennent pas
139: // un pointeur sur une struct_objet, mais sur une struct_arbre.
140:
141: struct_liste_chainee *l_liste_locale;
142: struct_liste_chainee *l_ancienne_liste_locale;
143:
144: if ((*s_objet).type == ALG)
145: {
146: /*
147: * Transcription de l'expression algébrique en arbre q-aire
148: */
149:
150: l_liste_locale = NULL;
151: l_element_courant = (*s_objet).objet;
152:
153: while(l_element_courant != NULL)
154: {
155: switch((*(*l_element_courant).donnee).type)
156: {
157: // Toutes les fonctions (intrinsèques, extrinsèques et
158: // utilisateurs).
159:
160: case FCT:
161: {
162: // Il s'agit d'un objet de type ALG. Nous pouvons donc
163: // sauter les délimiteurs d'expression.
164:
165: if ((l_element_courant != (*s_objet).objet) &&
166: ((*l_element_courant).suivant != NULL))
167: {
168: nombre_arguments = (*((struct_fonction *)
169: (*(*l_element_courant).donnee).objet))
170: .nombre_arguments;
171:
172: // Si le nombre d'arguments vaut 0, la fonction
173: // apparaît en notation algébrique comme une fonction
174: // infixe.
175:
176: if (nombre_arguments == 0)
177: {
178: nombre_arguments = 2;
179: }
180:
181: if ((s_arbre = malloc(sizeof(struct_arbre))) == NULL)
182: {
183: (*s_etat_processus).erreur_systeme =
184: d_es_allocation_memoire;
185: return(NULL);
186: }
187:
188: (*s_arbre).inversion = d_faux;
189: (*s_arbre).nombre_branches = nombre_arguments;
190:
191: if (((*s_arbre).branches = malloc(((size_t) (*s_arbre)
192: .nombre_branches) * sizeof(struct_arbre *)))
193: == NULL)
194: {
195: (*s_etat_processus).erreur_systeme =
196: d_es_allocation_memoire;
197: return(NULL);
198: }
199:
200: for(i = 0; i < nombre_arguments; i++)
201: {
202: if (l_liste_locale == NULL)
203: {
204: (*s_etat_processus).erreur_execution =
205: d_ex_manque_argument;
206: return(NULL);
207: }
208:
209: if (((*s_arbre).branches[i] = malloc(
210: sizeof(struct_arbre))) == NULL)
211: {
212: (*s_etat_processus).erreur_systeme =
213: d_es_allocation_memoire;
214: return(NULL);
215: }
216:
217: (*(*s_arbre).branches[i]).feuille =
218: (*l_liste_locale).donnee;
219: (*(*s_arbre).branches[i]).inversion = d_faux;
220: (*(*s_arbre).branches[i]).nombre_branches = 0;
221: (*(*s_arbre).branches[i]).branches = NULL;
222:
223: l_ancienne_liste_locale = l_liste_locale;
224: l_liste_locale = (*l_liste_locale).suivant;
225:
226: liberation_maillon(s_etat_processus,
227: l_ancienne_liste_locale);
228: }
229:
230: // Introduction de l'arbre dans la pile locale
231:
232: l_ancienne_liste_locale = l_liste_locale;
233:
234: if ((l_liste_locale = allocation_maillon(
235: s_etat_processus)) == NULL)
236: {
237: (*s_etat_processus).erreur_systeme =
238: d_es_allocation_memoire;
239: return(NULL);
240: }
241:
242: (*l_liste_locale).suivant = l_ancienne_liste_locale;
243: (*l_liste_locale).donnee = (void *) s_arbre;
244: }
245:
246: break;
247: }
248:
249: default:
250: {
251: l_ancienne_liste_locale = l_liste_locale;
252:
253: if ((l_liste_locale = allocation_maillon(s_etat_processus))
254: == NULL)
255: {
256: (*s_etat_processus).erreur_systeme =
257: d_es_allocation_memoire;
258: return(NULL);
259: }
260:
261: (*l_liste_locale).suivant = l_ancienne_liste_locale;
262:
263: if ((s_arbre = malloc(sizeof(struct_arbre))) == NULL)
264: {
265: (*s_etat_processus).erreur_systeme =
266: d_es_allocation_memoire;
267: return(NULL);
268: }
269:
270: (*s_arbre).feuille = copie_objet(s_etat_processus,
271: (*l_element_courant).donnee, 'P');
272: (*s_arbre).inversion = d_faux;
273: (*s_arbre).nombre_branches = 0;
274: (*s_arbre).branches = NULL;
275:
276: (*l_liste_locale).donnee = (void *) s_arbre;
277: break;
278: }
279: }
280:
281: l_element_courant = (*l_element_courant).suivant;
282: }
283:
284: // Toute l'expression a été balayée. On ne doit plus avoir qu'un
285: // seul niveau dans la pile locale, ce niveau contenant l'arbre
286: // à réduire.
287:
288: if (l_liste_locale == NULL)
289: {
290: (*s_etat_processus).erreur_execution = d_ex_erreur_evaluation;
291: return(NULL);
292: }
293: else if ((*l_liste_locale).suivant != NULL)
294: {
295: (*s_etat_processus).erreur_execution = d_ex_erreur_evaluation;
296: return(NULL);
297: }
298:
299: s_arbre = (void *) (*l_liste_locale).donnee;
300:
301: liberation_maillon(s_etat_processus, l_liste_locale);
302: l_liste_locale = NULL;
303:
304: /*
305: * Simplification de l'arbre
306: */
307:
308: # if 0
309: simplification_arbre();
310: # endif
311:
312: /*
313: * Transcription de l'arbre q-aire simplifié en expression algébrique.
314: * Seule une fonction récursive permet de faire cette conversion
315: * simplement.
316: */
317:
318: l_liste_locale = transcription_arbre(s_etat_processus, s_arbre);
319:
320: if ((s_objet_simplifie = allocation(s_etat_processus, ALG))
321: == NULL)
322: {
323: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
324: return(NULL);
325: }
326:
327: // Ajout des délimiteurs '<<' et '>>' à la liste d'instructions
328:
329: if (((*s_objet_simplifie).objet = allocation_maillon(s_etat_processus))
330: == NULL)
331: {
332: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
333: return(NULL);
334: }
335:
336: l_element_courant = (*s_objet_simplifie).objet;
337:
338: if (((*l_element_courant).donnee = allocation(s_etat_processus,
339: FCT)) == NULL)
340: {
341: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
342: return(NULL);
343: }
344:
345: (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
346: .nombre_arguments = 0;
347: (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
348: .fonction = instruction_vers_niveau_superieur;
349:
350: if (((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
351: .nom_fonction = malloc(3 * sizeof(unsigned char))) == NULL)
352: {
353: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
354: return(NULL);
355: }
356:
357: strcpy((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
358: .nom_fonction, "<<");
359:
360: (*l_element_courant).suivant = l_liste_locale;
361:
362: while((*l_element_courant).suivant != NULL)
363: {
364: l_element_courant = (*l_element_courant).suivant;
365: }
366:
367: if (((*l_element_courant).suivant =
368: allocation_maillon(s_etat_processus)) == NULL)
369: {
370: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
371: return(NULL);
372: }
373:
374: l_element_courant = (*l_element_courant).suivant;
375: (*l_element_courant).suivant = NULL;
376:
377: if (((*l_element_courant).donnee = allocation(s_etat_processus,
378: FCT)) == NULL)
379: {
380: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
381: return(NULL);
382: }
383:
384: (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
385: .nombre_arguments = 0;
386: (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
387: .fonction = instruction_vers_niveau_inferieur;
388:
389: if (((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
390: .nom_fonction = malloc(3 * sizeof(unsigned char))) == NULL)
391: {
392: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
393: return(NULL);
394: }
395:
396: strcpy((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
397: .nom_fonction, ">>");
398: }
399: else
400: # endif
401: {
402: s_objet_simplifie = copie_objet(s_etat_processus, s_objet, 'P');
403: }
404:
405: return(s_objet_simplifie);
406: }
407:
408: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>