b311480e |
1 | /* |
973c2be1 |
2 | Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
3 | |
973c2be1 |
4 | This file is part of Open CASCADE Technology software library. |
b311480e |
5 | |
d5f74e42 |
6 | This library is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
8 | by the Free Software Foundation, with special exception defined in the file |
9 | OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
10 | distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
11 | |
973c2be1 |
12 | Alternatively, this file may be used under the terms of Open CASCADE |
13 | commercial license or contractual agreement. |
b311480e |
14 | */ |
15 | |
7fd59977 |
16 | #include "stdio.h" |
17 | #include "string.h" |
18 | #include "stdlib.h" |
19 | #if defined(HAVE_MALLOC_H) |
20 | #include "malloc.h" |
21 | #endif |
22 | #include "recfile.ph" |
23 | /* enregistrement d'un fichier d'interface sous forme de records |
24 | gere les scopes |
25 | |
26 | Ce fichier comprend 3 parties |
27 | - les routines traitant les char*, avec la notion de texte courant |
28 | - les declarations des donnees de travail proprement dites pour le fichier |
29 | - le corps des programmes d'enregistrement |
30 | */ |
31 | |
32 | |
33 | /* ROUTINES UTILITAIRES de traitement des textes (char*) */ |
34 | |
35 | /* Gestion du texte courant : c'est un texte alloue dynamiquement |
36 | rec_restext en alloue un (jete le precedent alloue si pas lu) |
37 | rec_gettext lit le texte en cours, qui ne sera pas desalloue ensuite |
38 | rec_settext en force un autre en jetant le precedent (idem rec_newtext) |
39 | tandis que rec_newtext alloue un texte, sans lien avec le courant |
40 | */ |
41 | |
42 | #define Maxcar 50000 |
43 | |
44 | static struct carpage { |
45 | struct carpage* next; /* chainage des pages de caracteres */ |
46 | int used; /* place deja prise */ |
47 | char cars[Maxcar+1]; /* page de caracteres */ |
48 | } *onecarpage; |
49 | |
50 | static char* restext = NULL ; /* texte courant (allocation dynamique) */ |
51 | /* static int resalloc = 0 ;*/ /* alloue (memoire a liberer) ou non */ |
52 | |
53 | static char txt_cart_p[] = "CARTESIAN_POINT"; |
54 | |
498ce76b |
55 | void rec_restext(char* newtext, int lentext) /* destine a etre appele de l'exterieur */ |
7fd59977 |
56 | { |
57 | char *res, *text; |
58 | if(strcmp(newtext,txt_cart_p)==0) { |
59 | restext = txt_cart_p; |
60 | return; |
61 | } |
62 | |
63 | if (onecarpage->used > Maxcar-lentext-1) { /* allouer nouvelle page */ |
64 | struct carpage *newpage; |
65 | int sizepage = sizeof(struct carpage); |
66 | if (lentext >= Maxcar) sizepage += (lentext+1 - Maxcar); |
67 | newpage = (struct carpage*) malloc (sizepage); |
68 | newpage->next = onecarpage; |
69 | onecarpage = newpage; |
70 | onecarpage->used = 0; |
71 | } |
72 | restext = onecarpage->cars + onecarpage->used; |
73 | onecarpage->used += (lentext + 1); |
74 | /* strcpy */ |
75 | res = restext ; text = newtext; |
76 | while (*text != '\0') { *res=*text ; res++ ; text++ ; } |
77 | *res = '\0' ; |
78 | } |
79 | |
498ce76b |
80 | void rec_gettext(char* *r) |
7fd59977 |
81 | /* Le resultat retourne (pointeur) est destine a etre inclus dans un struct */ |
498ce76b |
82 | { *r = restext; } |
7fd59977 |
83 | |
498ce76b |
84 | void rec_settext(char* s) |
85 | /* substituer le texte courant par un autre deja alloue */ |
7fd59977 |
86 | { restext = s ; } |
87 | |
498ce76b |
88 | char* rec_newtext(char* r) |
7fd59977 |
89 | /* routine utilitaire creant une chaine dynamique a partir d'un char[] */ |
7fd59977 |
90 | { |
105aae76 |
91 | char* savrestext; |
92 | char* s0; |
7fd59977 |
93 | savrestext = restext; |
105aae76 |
94 | rec_restext(r,(int)strlen(r)); |
95 | s0 = restext; |
7fd59977 |
96 | restext = savrestext; |
97 | return (s0); |
98 | } |
99 | |
100 | |
101 | |
102 | static int modeprint = 0 ; /* CONTROLE D'IMPRESSION (pour appel depuis yacc)*/ |
103 | |
104 | /* DECLARATIONS des donnees de travail (en cours d'enregistrement) */ |
105 | |
106 | static int typarg ; /* type du dernier argument lu */ |
107 | static int nbrec = 0; /* nombre total d'enregistrements de donnees */ |
108 | static int nbhead = 0; /* nb de records pris par le Header */ |
109 | static int nbpar = 0; /* nb de parametres lus au total */ |
110 | static int yarec = 0; /* presence Record deja cree (1 apres Ident) */ |
111 | |
112 | static struct rec { /* DESCRIPTION D'UN RECORD */ |
113 | char* ident ; /* identifieur du record (en #12345...) ou scope-end */ |
114 | char* type ; /* type du record (peut etre sublist) */ |
115 | /* int nbarg ; nombre de parametres (arguments) du record, not used */ |
116 | struct unarg* first ; /* 1er argument */ |
117 | /* struct unarg* last ;dernier argument, not used */ |
118 | struct rec* next ; /* record suivant */ |
119 | } *currec ; /* currec meme : record courant */ |
120 | |
121 | #define Maxrec 5000 |
122 | static struct recpage { |
123 | struct recpage* next; |
124 | int used; |
125 | struct rec args[Maxrec+1]; |
126 | } *onerecpage; |
127 | |
128 | static struct rec* firstrec ; /* 1er record du fichier */ |
129 | static struct rec* lastrec ; /* dernier record du fichier */ |
130 | |
131 | static char* curtype; /* type dernier record (ou = sublist) */ |
132 | static char* subarg ; /* ident dernier record (sub-list eventuel) */ |
133 | static int numsub ; /* numero de sous-liste en cours */ |
134 | |
135 | |
136 | static struct unarg { /* DESCRIPTION D'UN ARGUMENT */ |
137 | int type ; /* type de l'arg, dans une liste courte : entier, reel ... */ |
138 | char* val ; /* valeur alphanum de l'arg */ |
139 | struct unarg* next ; /* argument suivant dans la liste pour ce record */ |
140 | } *curarg ; |
141 | |
142 | #define Maxarg 10000 |
143 | static struct argpage { /* Allocation optimisee des arguments */ |
144 | struct argpage* next; |
145 | int used; |
146 | struct unarg args[Maxarg+1]; |
147 | } *oneargpage; |
148 | |
149 | |
150 | static struct scope { /* DESCRIPTION D'UN SCOPE */ |
151 | /* les scopes sont empilables sans limite */ |
152 | struct scope* prev; /* scope precedent, auquel il faudra revenir */ |
153 | struct rec* rec; /* record interrompu par le scope (a reprendre) */ |
154 | } *curscope ; /* curscope est le scope en cours */ |
155 | |
156 | |
157 | /* Constantes litterales */ |
158 | static char txt_sublist[] = "/* (SUB) */" ; |
159 | static char txt_scope[] = "SCOPE" ; |
160 | static char txt_endscope[] = "ENDSCOPE" ; |
161 | static char txt_nil[] = " " ; |
162 | static char sub1[] = "$1" ; /* optimisation ... */ |
163 | static char sub2[] = "$2" ; |
164 | static char argtype1[] = "(IF#TnEHBx"; /* types arguments (2 1es lettres) */ |
165 | static char argtype2[] = ")nlIxdnxix"; |
166 | static char idzero[] = "#0"; |
167 | |
168 | |
169 | /* Trace pour controle */ |
498ce76b |
170 | void recfile_modeprint(int mode) |
7fd59977 |
171 | { modeprint = mode; } |
172 | |
173 | static int lastno; |
174 | extern int steplineno; |
175 | extern int modcom; |
176 | extern int modend; |
177 | |
178 | void rec_inityyll () |
179 | { |
180 | steplineno = 0; |
181 | modcom = 0; |
182 | modend = 0; |
183 | lastno = -1; |
184 | } |
185 | |
186 | |
187 | /* INITIALISATION */ |
188 | |
189 | void rec_debfile() |
190 | { |
191 | /*initialization of recpage*/ |
192 | onerecpage = (struct recpage*) malloc ( sizeof(struct recpage) ); |
193 | onerecpage->used = 0; onerecpage->next = NULL; |
194 | |
195 | onecarpage = (struct carpage*) malloc ( sizeof(struct carpage) ); |
196 | onecarpage->used = 0; onecarpage->next = NULL; restext = NULL; |
197 | yarec = 0; nbhead = nbrec = nbpar = 0 ; firstrec = NULL ; lastrec = NULL ; |
198 | curtype = txt_sublist; |
199 | currec = NULL ; curarg = NULL ; |
200 | curscope = NULL ; |
201 | oneargpage = (struct argpage*) malloc ( sizeof(struct argpage) ); |
202 | oneargpage->next = NULL; oneargpage->used = 0; |
203 | rec_inityyll(); |
204 | } |
205 | |
206 | /* INTERMEDIAIRE : passage de Header a Data */ |
207 | void rec_finhead() { nbhead = nbrec; } |
208 | |
209 | /* CONCLUSION : actuellement, ne fait rien */ |
210 | |
211 | void rec_finfile() { } |
212 | |
213 | |
214 | /* GESTION DES RECORDS */ |
215 | |
216 | /* ENREGISTRER UN RECORD (deja pret) */ |
f24125b9 |
217 | static void rec_new(struct rec* newrec) |
498ce76b |
218 | /* nouveau record a enregistrer */ |
7fd59977 |
219 | { |
220 | nbrec ++ ; |
221 | if ( firstrec == NULL ) firstrec = newrec ; |
222 | if ( lastrec != NULL ) lastrec->next = newrec ; |
223 | lastrec = newrec ; |
224 | } |
225 | |
226 | /* type du dernier argument lu */ |
498ce76b |
227 | void rec_typarg(int argtype) |
7fd59977 |
228 | { typarg = argtype; } |
229 | |
230 | /* ENREGISTRER UNE ENTITE (record courant) */ |
231 | void rec_newent() |
232 | { |
233 | rec_new(currec) ; /* le record courant (currec) est enregistre */ |
234 | |
235 | /* gestion des sous-listes : si currec a un suivant note (cf pointeur suite), |
236 | alors c'est une sous-liste et le suivant est son contenant |
237 | EN CE CAS, il faut memoriser cette sous-liste en argument courant |
238 | En effet, d'une part la liste est reconnue comme un argument, d'autre part |
239 | part elle se termine par ")" : c'est donc ici qu'elle sera enregistree */ |
240 | |
241 | rec_typarg (rec_argSub) ; |
242 | |
243 | subarg = currec->ident ; /* si sous-liste, sera argument du contenant */ |
244 | /* rec_check(1) ; */ |
245 | currec = currec->next ; /* si nul, c'est qu'une autre entite suit */ |
246 | lastrec->next = NULL ; |
247 | } |
248 | |
249 | |
250 | static struct rec*rec_newrec() |
251 | { |
252 | struct rec* newrec; |
253 | if (onerecpage->used >= Maxrec) { |
254 | struct recpage* newrecpage; |
255 | newrecpage = (struct recpage*) malloc ( sizeof (struct recpage) ); |
256 | newrecpage->next = onerecpage; |
257 | onerecpage = newrecpage; |
258 | onerecpage->used = 0; |
259 | } |
260 | newrec = &(onerecpage->args[onerecpage->used]); |
261 | onerecpage->used++; |
262 | |
263 | return newrec; |
264 | } |
265 | |
266 | |
267 | /* RECORD COURANT : */ |
268 | |
269 | /* creer et preciser l'identifieur */ |
270 | void rec_ident() |
271 | { |
272 | currec = rec_newrec(); |
273 | /*currec = (struct rec*) malloc (sizeof (struct rec)) ;*/ |
274 | /*currec->nbarg = 0 ;*/ |
275 | rec_gettext(&(currec->ident)) ; |
276 | currec->next = NULL ; currec->first = NULL ; /*currec->last = NULL ;*/ |
277 | yarec = 1; |
278 | } |
279 | |
280 | /* preciser le type ; demarrage de la description de l'entite */ |
281 | void rec_type() |
282 | { |
283 | /* Pour le header : pas d'ident, donc en simuler un : derive de rec_ident */ |
284 | if (!yarec) { |
285 | /*currec = (struct rec*) malloc (sizeof (struct rec)) ;*/ |
286 | currec = rec_newrec(); |
287 | /*currec->nbarg = 0 ;*/ |
288 | currec->ident = idzero; /* Ident bidon (il en faut un ...) */ |
289 | currec->next = NULL ; currec->first = NULL ; /*currec->last = NULL ;*/ |
290 | } |
291 | rec_gettext(&(currec->type)) ; |
292 | yarec = numsub = 0 ; /* debut de l'entite */ |
293 | } |
294 | |
295 | /* type d une liste qui n est pas une entite mais un argument |
296 | par defaut (cf rec_deblist) il n est pas defini donc mis = "/ (SUB) /" */ |
297 | void rec_listype() |
298 | { rec_gettext(&(curtype)); } |
299 | |
300 | /* ajouter un argument (type & valeur deja connus) */ |
301 | void rec_newarg() |
302 | { |
303 | struct unarg *newarg; |
304 | nbpar ++; |
305 | /*currec->nbarg ++ ;*/ |
306 | /* newarg = (struct unarg*) malloc (sizeof (struct unarg)) ; */ |
307 | if (oneargpage->used >= Maxarg) { |
308 | struct argpage* newargpage; |
309 | newargpage = (struct argpage*) malloc ( sizeof(struct argpage) ); |
310 | newargpage->next = oneargpage; |
311 | oneargpage = newargpage; |
312 | oneargpage->used = 0; |
313 | } |
314 | newarg = &(oneargpage->args[oneargpage->used]); |
315 | oneargpage->used ++; |
316 | |
317 | newarg->type = typarg ; |
318 | if (typarg == rec_argSub) newarg->val = subarg ; |
319 | else rec_gettext (&(newarg->val)); |
320 | |
321 | /* if (currec->first == NULL) currec->first = newarg; |
322 | else currec->last->next = newarg; |
323 | currec->last = newarg;*/ |
324 | if (currec->first == NULL) currec->first = newarg; |
325 | else { |
326 | struct unarg* nextarg = currec->first; |
327 | while(nextarg->next != NULL) |
328 | nextarg = nextarg->next; |
329 | nextarg->next = newarg; |
330 | |
331 | } |
332 | newarg->next = NULL ; |
333 | /* rec_check(0) ; */ |
334 | } |
335 | |
336 | /* Ajouter une sous-liste |
337 | |
338 | Une ouverture de parentheses A L'INTERIEUR d'une liste de parametres |
339 | signale une sous-liste : c'est une entite non identifiee, directement |
340 | utilisee comme argument de la liste contenante) d'un type reserve(SUB) |
341 | |
342 | Elle est enregistree avec un identifieur special : '$' suivi d'un numero |
343 | de sous-liste dans l'entite en cours. |
344 | |
345 | Son enregistrement consiste a definir un nouveau record courant, pour la |
346 | sous-liste, qui note comme suivant l'ancien courant, qui est son contenant |
347 | A la fin de la sous-liste, elle est enregistree comme toute entite (cf |
348 | rec_new) mais le suivant devient le nouveau courant dont l'enregistrement |
349 | des parametres continue |
350 | |
351 | La premiere ouverture de parentheses dans l'entite est celle de la liste |
352 | principale de parametres et non d'une sous-liste |
353 | */ |
354 | |
355 | void rec_deblist() |
356 | { |
357 | if (numsub > 0) { /* enregistrement d'une sous-liste */ |
358 | /* int i ; */ struct rec* subrec ; |
359 | /* creation du nouvel enregistrement et chainage au precedent */ |
360 | subrec = rec_newrec(); |
361 | /*subrec = (struct rec*) malloc (sizeof (struct rec)) ;*/ |
362 | switch (numsub) { |
363 | case 1: subrec->ident = sub1; break; |
364 | case 2: subrec->ident = sub2; break; |
365 | default: { |
366 | char bufsub[10]; |
367 | if (numsub > 9) sprintf (bufsub,"$%d",numsub) ; |
8263fcd3 |
368 | else { bufsub[0] = '$'; bufsub[1] = (char)(numsub + 48); bufsub[2] = '\0'; } |
7fd59977 |
369 | subrec->ident = rec_newtext(bufsub) ; |
370 | } |
371 | } |
372 | subrec->type = curtype ; |
373 | curtype = txt_sublist; /* type reserve par defaut */ |
374 | /*subrec->nbarg = 0 ;*/ subrec->next = currec ; |
375 | subrec->first = NULL ; /*subrec->last = NULL ;*/ |
376 | /* les arguments de la sous-liste vont suivre ; |
377 | elle meme est argument de son contenant, ce qui est pris en compte |
378 | a la fermeture de la parenthese */ |
379 | currec = subrec ; /* substitution finale */ |
380 | } |
381 | numsub ++ ; /* numero de la prochaine sous-liste (la principale est en 0) */ |
382 | /* rec_check(0) ; */ |
383 | } |
384 | |
385 | |
386 | /* Affichage du contenu d'un record */ |
498ce76b |
387 | void rec_print(struct rec* unrec) |
7fd59977 |
388 | { |
389 | int numa = 0; int numl = 0; int argl = 0; |
390 | if (unrec == NULL) { printf ("Non defini\n") ; return; } |
391 | printf ("Ident : %s Type : %s Nb.Arg.s : %s\n", |
392 | unrec->ident,unrec->type, (unrec->first ? unrec->first->val : "")) ; |
393 | if (modeprint < 2) return ; |
394 | curarg = unrec->first ; |
395 | while (curarg != NULL) { |
105aae76 |
396 | numa ++; |
397 | argl = (int)strlen(curarg->val) + 18; |
398 | numl += argl; |
7fd59977 |
399 | if (numl > 132) { printf("\n"); numl = argl; } |
400 | printf (" - Arg.%d[%c%c] : %s", |
401 | numa,argtype1[curarg->type],argtype2[curarg->type],curarg->val); |
402 | curarg = curarg->next ; |
403 | } |
404 | if (argl > 0) printf("\n"); |
405 | return ; |
406 | } |
407 | |
408 | /* GESTION DES SCOPES */ |
409 | |
410 | /* Ouverture de scope : |
411 | un scope est un record particulier (pas de type ni d'argument) |
412 | d'une part il est enregistre, d'autre part il faut gerer le record en cours |
413 | En effet, une entite step etait en cours d'enregistrement (ident deja connu), |
414 | mais son type et ses arguments seront fournis apres fermeture du scope ... |
415 | Il faut donc la mettre de cote (c'est currec), pour la restaurer ensuite |
416 | |
417 | Mais ATTENTION, il y a l'EXPORT : au ENDSCOPE, peut etre attachee une liste |
418 | d'Idents : ce sont les idents internes au SCOPE mais declares visibles de |
419 | l'exterieur du SCOPE (en plus de l''entite sur laquelle il porte) |
420 | */ |
421 | |
422 | void scope_debut() |
423 | { |
424 | /* ouverture du scope et sauvegarde de l'entite en cours */ |
425 | struct scope* newscope; struct rec* unscope; |
426 | newscope = (struct scope*) malloc (sizeof (struct scope)) ; |
427 | newscope->rec = currec ; |
428 | newscope->prev = curscope ; |
429 | curscope = newscope ; |
430 | |
431 | /* enregistrement de ce scope comme un record */ |
432 | unscope = rec_newrec(); |
433 | /*unscope = (struct rec*) malloc (sizeof (struct rec)) ;*/ |
434 | unscope->ident = txt_scope ; |
435 | unscope->type = txt_nil ; |
436 | unscope->first = NULL; |
437 | /*unscope->nbarg = 0 ;*/ |
438 | rec_new(unscope) ; |
439 | } |
440 | |
441 | /* Fermeture de scope : |
442 | La fin de scope est, comme son debut, un enregistrement special. |
443 | Il faut donc l'enregistrer. |
444 | Il faut aussi restaurer l'entite concernee par le scope, afin de terminer |
445 | son enregistrement (manquent ses arguments) */ |
446 | |
447 | void scope_fin() |
448 | { struct scope* oldscope ; struct rec* unscope; |
449 | if (curscope == NULL) return ; /* cela dit, c'est anormal ... */ |
450 | |
451 | /* enregistrement de cette fin de scope comme un record */ |
452 | unscope = rec_newrec(); |
453 | /* unscope = (struct rec*) malloc (sizeof (struct rec)) ;*/ |
454 | unscope->ident = txt_endscope ; |
455 | unscope->type = txt_nil ; |
456 | unscope->first = NULL; |
457 | /*unscope->nbarg = 0 ;*/ |
458 | |
459 | /* Si on doit prendre en compte une Export List ... */ |
460 | if (subarg[0] == '$') { |
461 | if (modeprint > 0) { |
462 | printf("Export List : (List in Record n0 %d) -- ",nbrec); |
463 | rec_print(lastrec); |
464 | } |
465 | currec = unscope; |
466 | typarg = rec_argSub; |
467 | rec_newarg(); |
468 | } |
469 | rec_new(unscope) ; |
470 | |
471 | /* fermeture effective du scope */ |
472 | currec = curscope->rec ; /* restaurer l'entite en cours d'enreg. */ |
473 | yarec = 1; |
474 | oldscope = curscope ; |
475 | curscope = oldscope->prev ; /* restauration de l'etat precedent */ |
476 | free (oldscope) ; /* suppression "physique" */ |
477 | } |
478 | |
479 | |
480 | /* CONCLUSION : retour des valeurs pour constituer la liste des records, |
481 | sous forme de directory / tableau |
482 | |
483 | La liberation de la memoire est faite par lir_file_fin, en une fois |
484 | */ |
485 | |
498ce76b |
486 | void lir_file_nbr(int* nbh, int* nbr, int* nbp) |
7fd59977 |
487 | /* initialise le traitement et retourne la taille du directory et du header */ |
488 | { |
489 | currec = firstrec ; |
490 | /* rec_check(0) ; */ |
491 | *nbh = nbhead; *nbr = nbrec; *nbp = nbpar; |
492 | } |
493 | |
498ce76b |
494 | void lir_file_fin(int mode) |
7fd59977 |
495 | /* fin du traitement : regroupe les liberations de memoire en une phase */ |
496 | /* mode = 1 : rec+arg. 2 : carpage; 3 : 1+2 */ |
497 | { |
498 | if (mode & 1) { |
499 | while(onerecpage != NULL) { |
500 | struct recpage* newpage; newpage = onerecpage->next; |
501 | free(onerecpage); |
502 | onerecpage = newpage; |
503 | } |
504 | |
505 | |
506 | /* struct rec* oldrec; |
507 | oldrec = NULL; |
508 | currec = firstrec; |
509 | while (currec != NULL) { |
510 | oldrec = currec; |
511 | currec = currec->next;*/ |
512 | /* liberation memoire pour type & ident : si scope-endscope rien a liberer |
513 | si sous-liste : type pas a liberer, ident partage aussi par l'argument sera |
514 | libere par lui ... donc ici aussi, rien a liberer. CQFD */ |
515 | /* free (oldrec) ; |
516 | }*/ |
517 | while (oneargpage != NULL) { |
518 | struct argpage* newpage; newpage = oneargpage->next; |
519 | free (oneargpage); |
520 | oneargpage = newpage; |
521 | } |
522 | } |
523 | if (mode & 2) { |
524 | while (onecarpage != NULL) { |
525 | struct carpage* newpage; newpage = onecarpage->next; |
526 | free (onecarpage); |
527 | onecarpage = newpage; |
528 | } |
529 | } |
530 | } |
531 | |
498ce76b |
532 | int lir_file_rec(char* *ident, char* *type, int *nbarg) |
7fd59977 |
533 | /* retourne les parametres du record courant |
534 | retour de fonction ; 1 si ok, 0 si liste epuisee */ |
7fd59977 |
535 | { |
536 | if (currec == NULL) return (0) ; |
537 | /* rec_check(2) ; */ |
538 | *ident = currec->ident ; |
539 | *type = currec->type ; |
540 | *nbarg = (currec->first != NULL); |
541 | curarg = currec->first ; /* prepare lecture arg.s */ |
542 | return (1) ; |
543 | } |
544 | |
545 | void lir_file_finrec() |
546 | /* fait le menage et passe au record suivant |
547 | ne pas appeler apres l'indication de fin mais apres chaque record ok ! */ |
548 | { |
549 | currec = currec->next ; |
550 | /* rec_check(2) ; */ |
551 | } |
552 | |
498ce76b |
553 | int lir_file_arg(int* type, char* *val) |
7fd59977 |
554 | /* lit l'argument courant (au debut le 1er), fait le menage, prepare suivant |
555 | retourne 1 si ok, 0 si c'est fini |
556 | attention, suppose que nbarg > 0 ... (bref, pas de protection) */ |
557 | { |
558 | if (curarg == NULL) return (0) ; |
559 | *type = curarg->type ; |
560 | *val = curarg->val ; |
561 | curarg = curarg->next ; |
562 | return (1) ; |
563 | } |
564 | |
565 | |
566 | /* Verification de l'integrite des donnees */ |
567 | |
568 | /* Affiche ce qui ne va pas, mais aussi accede a tout : ainsi, les adresses |
569 | verolees aparaissent au grand jour du dbx */ |
570 | |
498ce76b |
571 | void rec_check(int mode) |
572 | /* mode=1 pas de controle nbrec (en cours d'enregistrement) */ |
7fd59977 |
573 | { |
574 | struct rec* lerec ; struct unarg* larg ; int nr,na ; |
575 | lerec = firstrec ; |
576 | if (mode == 2) lerec = currec ; |
577 | nr = 0 ; |
578 | while (lerec != NULL) { |
579 | nr ++ ; |
580 | if (lerec->ident == NULL) printf("Record %d : ident null\n",nr) ; |
581 | if (lerec->type == NULL) printf("Record %d : type null\n",nr) ; |
582 | /*if (mode < 2 && (lerec->nbarg < 0 || lerec->nbarg > 10) ) printf |
583 | ("N.B.: Record %d : nbarg pas entre 0 & 10, vaut %d\n",nr,lerec->nbarg); |
584 | */ |
585 | na = 0 ; |
586 | larg = lerec->first ; |
587 | while (larg != NULL) { |
588 | na ++ ; |
589 | if (larg->type < 0 || larg->type > 9) printf |
590 | ("Record %d , Arg. %d : type incorrect : %d\n",nr,na,larg->type) ; |
591 | if (larg->val == NULL) printf("Record %d , Arg %d : val null\n",nr,na) ; |
592 | larg = larg->next ; |
593 | } |
594 | /*if (na != lerec->nbarg) printf |
595 | ("Record %d : arglist pourrie, nb note %d relu %d\n",nr,lerec->nbarg,na) ;*/ |
596 | lerec = lerec->next ; |
597 | } |
598 | if (mode == 0 && nr != nbrec) printf |
599 | ("Liste des records pourrie, nb note %d relu %d\n",nbrec,nr) ; |
600 | } |
601 | |
602 | void steperror (char *mess); |
603 | int steplex (void); |
604 | |