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