1: /*
2: ================================================================================
3: RPL/2 (R) version 4.0.11
4: Copyright (C) 1989-2010 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: Procédure d'estimation de la longueur du tampon
29: ================================================================================
30: Entrée :
31: --------------------------------------------------------------------------------
32: Sortie :
33: --------------------------------------------------------------------------------
34: Effets de bord : néant
35: ================================================================================
36: */
37:
38: static inline void
39: estimation_taille_pile(struct_processus *s_etat_processus)
40: {
41: /*
42: * Cette fonction permet d'estimer un volant de structures de maillons
43: * de liste chaînée pour le programme courant et évite un certain nombre
44: * d'allocations de mémoire lors des manipulations de la pile. Cette taille
45: * est estimée au travers d'une chaîne de Markov.
46: */
47:
48: (*s_etat_processus).estimation_taille_pile_tampon =
49: ((*s_etat_processus).estimation_taille_pile_tampon *
50: ((double) 0.9)) + ((*s_etat_processus)
51: .hauteur_pile_operationnelle * ((double) 0.1));
52: return;
53: }
54:
55:
56: /*
57: ================================================================================
58: Procédure d'empilement d'un nouvel élément
59: ================================================================================
60: Entrée :
61: --------------------------------------------------------------------------------
62: Sortie :
63: --------------------------------------------------------------------------------
64: Effets de bord : néant
65: ================================================================================
66: */
67:
68: logical1
69: empilement(struct_processus *s_etat_processus,
70: struct_liste_chainee **l_base_pile, struct_objet *s_objet)
71: {
72: struct_liste_chainee *l_ancienne_base_liste;
73: struct_liste_chainee *l_nouvelle_base_liste;
74:
75: logical1 erreur;
76:
77: l_ancienne_base_liste = *l_base_pile;
78:
79: if ((*s_etat_processus).pile_tampon == NULL)
80: {
81: // Tampon vide, on alloue un élément.
82:
83: if ((l_nouvelle_base_liste = malloc(sizeof(struct_liste_chainee)))
84: == NULL)
85: {
86: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
87: return(d_erreur);
88: }
89: }
90: else
91: {
92: // Tampon utilisable, on retire un élément du tampon.
93:
94: l_nouvelle_base_liste = (*s_etat_processus).pile_tampon;
95: (*s_etat_processus).pile_tampon = (*l_nouvelle_base_liste).suivant;
96: (*s_etat_processus).taille_pile_tampon--;
97: }
98:
99: *l_base_pile = l_nouvelle_base_liste;
100: (**l_base_pile).donnee = s_objet;
101: (**l_base_pile).suivant = l_ancienne_base_liste;
102:
103: erreur = d_absence_erreur;
104:
105: /*
106: -- Ne considère que la pile opérationnelle -------------------------------------
107: */
108:
109: if ((*s_etat_processus).l_base_pile == *l_base_pile)
110: {
111: (*s_etat_processus).hauteur_pile_operationnelle++;
112: estimation_taille_pile(s_etat_processus);
113:
114: if ((*s_etat_processus).debug == d_vrai)
115: if (((*s_etat_processus).type_debug &
116: d_debug_pile_utilisateur) != 0)
117: {
118: if ((*s_etat_processus).langue == 'F')
119: {
120: printf("[%d] Empilement de type %d "
121: "(profondeur %lu)\n", (int) getpid(),
122: (*s_objet).type,
123: (*s_etat_processus).hauteur_pile_operationnelle);
124: }
125: else
126: {
127: printf("[%d] Pushing a type %d object "
128: "(depth %lu)\n", (int) getpid(), (*s_objet).type,
129: (*s_etat_processus).hauteur_pile_operationnelle);
130: }
131:
132: fflush(stdout);
133: }
134: }
135:
136: return erreur;
137: }
138:
139:
140: /*
141: ================================================================================
142: Procédure de dépilement d'un élément. L'emplacement est libéré dans la pile.
143: ================================================================================
144: Entrée :
145: --------------------------------------------------------------------------------
146: Sortie :
147: --------------------------------------------------------------------------------
148: Effets de bord : néant
149: ================================================================================
150: */
151:
152: logical1
153: depilement(struct_processus *s_etat_processus,
154: struct_liste_chainee **l_base_pile, struct_objet **s_objet)
155: {
156: struct_liste_chainee *l_ancienne_base_liste;
157: struct_liste_chainee *l_nouvelle_base_liste;
158:
159: logical1 erreur;
160:
161: if (*l_base_pile == NULL)
162: {
163: (*s_etat_processus).erreur_execution = d_ex_pile_vide;
164: erreur = d_erreur;
165: }
166: else
167: {
168:
169: /*
170: -- Ne considère que la pile opérationnelle -------------------------------------
171: */
172:
173: l_ancienne_base_liste = *l_base_pile;
174: *s_objet = (*l_ancienne_base_liste).donnee;
175:
176: if ((*s_etat_processus).l_base_pile == *l_base_pile)
177: {
178: if ((*s_etat_processus).debug == d_vrai)
179: if (((*s_etat_processus).type_debug &
180: d_debug_pile_utilisateur) != 0)
181: {
182: if ((*s_etat_processus).langue == 'F')
183: {
184: printf("[%d] Dépilement de type %d "
185: "(profondeur %lu)\n", (int) getpid(),
186: (*(*s_objet)).type,
187: (*s_etat_processus).hauteur_pile_operationnelle);
188: }
189: else
190: {
191: printf("[%d] Pulling a type %d object "
192: "(depth %lu)\n", (int) getpid(), (*(*s_objet)).type,
193: (*s_etat_processus).hauteur_pile_operationnelle);
194: }
195:
196: fflush(stdout);
197: }
198:
199: (*s_etat_processus).hauteur_pile_operationnelle--;
200: estimation_taille_pile(s_etat_processus);
201: }
202:
203: l_nouvelle_base_liste = (*l_ancienne_base_liste).suivant;
204:
205: *l_base_pile = l_nouvelle_base_liste;
206: erreur = d_absence_erreur;
207:
208: if ((*s_etat_processus).taille_pile_tampon <= (10 * ((*s_etat_processus)
209: .estimation_taille_pile_tampon + 1)))
210: {
211: // Enregistrement de la structure pour usage ultérieur.
212:
213: (*l_ancienne_base_liste).donnee = NULL;
214: (*l_ancienne_base_liste).suivant = (*s_etat_processus).pile_tampon;
215: (*s_etat_processus).pile_tampon = l_ancienne_base_liste;
216: (*s_etat_processus).taille_pile_tampon++;
217: }
218: else
219: {
220: // Libération car le tampon est plein.
221:
222: free(l_ancienne_base_liste);
223: }
224: }
225:
226: return erreur;
227: }
228:
229:
230: /*
231: ================================================================================
232: Procédures affichant la pile opérationnelle
233: ================================================================================
234: Entrée :
235: --------------------------------------------------------------------------------
236: Sortie :
237: --------------------------------------------------------------------------------
238: Effets de bord : néant
239: ================================================================================
240: */
241:
242: void
243: affichage_pile(struct_processus *s_etat_processus, struct_liste_chainee
244: *l_element_courant, unsigned long niveau_courant)
245: {
246: unsigned char registre;
247:
248: registre = (*s_etat_processus).autorisation_conversion_chaine;
249: (*s_etat_processus).autorisation_conversion_chaine = 'N';
250:
251: ecriture_pile(s_etat_processus, stdout, l_element_courant, niveau_courant);
252:
253: (*s_etat_processus).autorisation_conversion_chaine = registre;
254: return;
255: }
256:
257: void
258: ecriture_pile(struct_processus *s_etat_processus, file *flux,
259: struct_liste_chainee *l_element_courant, unsigned long niveau_courant)
260: {
261: unsigned char *chaine;
262: unsigned char *registre;
263: unsigned char tampon[32 + 1];
264:
265: if (l_element_courant != NULL)
266: {
267: if (setjmp(contexte) == 0)
268: {
269: (*s_etat_processus).var_volatile_recursivite = -1;
270: ecriture_pile(s_etat_processus, flux,
271: (*l_element_courant).suivant, niveau_courant + 1);
272:
273: if ((*s_etat_processus).var_volatile_recursivite > 0)
274: {
275: (*s_etat_processus).var_volatile_recursivite--;
276:
277: if ((*s_etat_processus).var_volatile_recursivite == 0)
278: {
279: if (fprintf(flux, "%lu: ...\n", niveau_courant) < 0)
280: {
281: (*s_etat_processus).erreur_systeme =
282: d_es_erreur_fichier;
283: return;
284: }
285:
286: while(l_element_courant != NULL)
287: {
288: l_element_courant = (*l_element_courant).suivant;
289: }
290: }
291:
292: return;
293: }
294:
295: (*s_etat_processus).var_volatile_recursivite = 0;
296: }
297: else
298: {
299: // Libération de n appels de la pile système qui permet de
300: // terminer la récursion sans autre dépassement de pile.
301:
302: (*s_etat_processus).var_volatile_recursivite = 64;
303: return;
304: }
305:
306: sprintf(tampon, "%lu: ", niveau_courant);
307:
308: if ((chaine = formateur(s_etat_processus, strlen(tampon),
309: (*l_element_courant).donnee)) == NULL)
310: {
311: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
312: return;
313: }
314:
315: if ((*(*l_element_courant).donnee).type == CHN)
316: {
317: registre = chaine;
318:
319: if ((chaine = (unsigned char *) malloc((strlen(registre) + 3) *
320: sizeof(unsigned char))) == NULL)
321: {
322: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
323: return;
324: }
325:
326: sprintf(chaine, "\"%s\"", registre);
327: free(registre);
328: }
329:
330: if (fprintf(flux, "%lu: %s\n", niveau_courant, chaine) < 0)
331: {
332: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
333: return;
334: }
335:
336: free(chaine);
337: }
338:
339: return;
340: }
341:
342:
343: /*
344: ================================================================================
345: Procédure imprimant la pile opérationnelle
346: ================================================================================
347: Entrée : méthode 'C' = compacte, 'E' = étendue
348: --------------------------------------------------------------------------------
349: Sortie :
350: --------------------------------------------------------------------------------
351: Effets de bord : néant
352: ================================================================================
353: */
354:
355: void
356: impression_pile(struct_processus *s_etat_processus,
357: struct_liste_chainee *l_element_courant, unsigned char methode,
358: unsigned long niveau_courant)
359: {
360: struct_objet s_objet;
361:
362: unsigned char *chaine;
363: unsigned char *registre;
364: unsigned char tampon[32 + 1];
365:
366: if (l_element_courant != NULL)
367: {
368: if (setjmp(contexte) == 0)
369: {
370: (*s_etat_processus).var_volatile_recursivite = -1;
371: impression_pile(s_etat_processus, (*l_element_courant).suivant,
372: methode, niveau_courant + 1);
373:
374: if ((*s_etat_processus).var_volatile_recursivite > 0)
375: {
376: (*s_etat_processus).var_volatile_recursivite--;
377:
378: if ((*s_etat_processus).var_volatile_recursivite == 0)
379: {
380: while(l_element_courant != NULL)
381: {
382: l_element_courant = (*l_element_courant).suivant;
383: }
384: }
385:
386: return;
387: }
388:
389: (*s_etat_processus).var_volatile_recursivite = 0;
390: }
391: else
392: {
393: (*s_etat_processus).var_volatile_recursivite = 16;
394: return;
395: }
396:
397: if (methode == 'C')
398: {
399: s_objet.type = CHN;
400: sprintf(tampon, "%lu: ", niveau_courant);
401:
402: if ((chaine = formateur(s_etat_processus, strlen(tampon),
403: (*l_element_courant).donnee)) == NULL)
404: {
405: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
406: return;
407: }
408:
409: if ((*(*l_element_courant).donnee).type == CHN)
410: {
411: registre = chaine;
412:
413: if ((chaine = (unsigned char *) malloc((strlen(registre) + 3) *
414: sizeof(unsigned char))) == NULL)
415: {
416: (*s_etat_processus).erreur_systeme =
417: d_es_allocation_memoire;
418: return;
419: }
420:
421: sprintf(chaine, "\"%s\"", registre);
422: free(registre);
423: }
424:
425: if ((s_objet.objet = malloc((strlen(chaine) + 64) *
426: sizeof(unsigned char))) == NULL)
427: {
428: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
429: return;
430: }
431:
432: sprintf((unsigned char *) s_objet.objet,
433: "\n\\noindent\\begin{verbatim}\n%lu: %s\n\\end{verbatim}",
434: niveau_courant, chaine);
435: free(chaine);
436:
437: formateur_tex(s_etat_processus, &s_objet, 'V');
438: free(s_objet.objet);
439: }
440: else
441: {
442: formateur_tex(s_etat_processus, (*l_element_courant).donnee, 'N');
443: }
444: }
445:
446: return;
447: }
448:
449: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>