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