2 Copyright (c) 1999-2012 OPEN CASCADE SAS
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.
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.
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.
24 #if defined(HAVE_MALLOC_H)
28 /* enregistrement d'un fichier d'interface sous forme de records
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
38 /* ROUTINES UTILITAIRES de traitement des textes (char*) */
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
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 */
55 static char* restext = NULL ; /* texte courant (allocation dynamique) */
56 /* static int resalloc = 0 ;*/ /* alloue (memoire a liberer) ou non */
58 static char txt_cart_p[] = "CARTESIAN_POINT";
60 void rec_restext(newtext,lentext) /* destine a etre appele de l'exterieur */
61 char* newtext; int lentext;
64 if(strcmp(newtext,txt_cart_p)==0) {
69 if (onecarpage->used > Maxcar-lentext-1) { /* allouer nouvelle page */
70 struct carpage *newpage;
71 int sizepage = sizeof(struct carpage);
72 if (lentext >= Maxcar) sizepage += (lentext+1 - Maxcar);
73 newpage = (struct carpage*) malloc (sizepage);
74 newpage->next = onecarpage;
78 restext = onecarpage->cars + onecarpage->used;
79 onecarpage->used += (lentext + 1);
81 res = restext ; text = newtext;
82 while (*text != '\0') { *res=*text ; res++ ; text++ ; }
89 /* Le resultat retourne (pointeur) est destine a etre inclus dans un struct */
92 char* s ; /* substituer le texte courant par un autre deja alloue */
96 /* routine utilitaire creant une chaine dynamique a partir d'un char[] */
99 char* savrestext; char* s0;
100 savrestext = restext;
101 rec_restext(r,strlen(r)); s0 = restext;
102 restext = savrestext;
108 static int modeprint = 0 ; /* CONTROLE D'IMPRESSION (pour appel depuis yacc)*/
110 /* DECLARATIONS des donnees de travail (en cours d'enregistrement) */
112 static int typarg ; /* type du dernier argument lu */
113 static int nbrec = 0; /* nombre total d'enregistrements de donnees */
114 static int nbhead = 0; /* nb de records pris par le Header */
115 static int nbpar = 0; /* nb de parametres lus au total */
116 static int yarec = 0; /* presence Record deja cree (1 apres Ident) */
118 static struct rec { /* DESCRIPTION D'UN RECORD */
119 char* ident ; /* identifieur du record (en #12345...) ou scope-end */
120 char* type ; /* type du record (peut etre sublist) */
121 /* int nbarg ; nombre de parametres (arguments) du record, not used */
122 struct unarg* first ; /* 1er argument */
123 /* struct unarg* last ;dernier argument, not used */
124 struct rec* next ; /* record suivant */
125 } *currec ; /* currec meme : record courant */
128 static struct recpage {
129 struct recpage* next;
131 struct rec args[Maxrec+1];
134 static struct rec* firstrec ; /* 1er record du fichier */
135 static struct rec* lastrec ; /* dernier record du fichier */
137 static char* curtype; /* type dernier record (ou = sublist) */
138 static char* subarg ; /* ident dernier record (sub-list eventuel) */
139 static int numsub ; /* numero de sous-liste en cours */
142 static struct unarg { /* DESCRIPTION D'UN ARGUMENT */
143 int type ; /* type de l'arg, dans une liste courte : entier, reel ... */
144 char* val ; /* valeur alphanum de l'arg */
145 struct unarg* next ; /* argument suivant dans la liste pour ce record */
149 static struct argpage { /* Allocation optimisee des arguments */
150 struct argpage* next;
152 struct unarg args[Maxarg+1];
156 static struct scope { /* DESCRIPTION D'UN SCOPE */
157 /* les scopes sont empilables sans limite */
158 struct scope* prev; /* scope precedent, auquel il faudra revenir */
159 struct rec* rec; /* record interrompu par le scope (a reprendre) */
160 } *curscope ; /* curscope est le scope en cours */
163 /* Constantes litterales */
164 static char txt_sublist[] = "/* (SUB) */" ;
165 static char txt_scope[] = "SCOPE" ;
166 static char txt_endscope[] = "ENDSCOPE" ;
167 static char txt_nil[] = " " ;
168 static char sub1[] = "$1" ; /* optimisation ... */
169 static char sub2[] = "$2" ;
170 static char argtype1[] = "(IF#TnEHBx"; /* types arguments (2 1es lettres) */
171 static char argtype2[] = ")nlIxdnxix";
172 static char idzero[] = "#0";
175 /* Trace pour controle */
176 void recfile_modeprint(mode)
178 { modeprint = mode; }
181 extern int steplineno;
198 /*initialization of recpage*/
199 onerecpage = (struct recpage*) malloc ( sizeof(struct recpage) );
200 onerecpage->used = 0; onerecpage->next = NULL;
202 onecarpage = (struct carpage*) malloc ( sizeof(struct carpage) );
203 onecarpage->used = 0; onecarpage->next = NULL; restext = NULL;
204 yarec = 0; nbhead = nbrec = nbpar = 0 ; firstrec = NULL ; lastrec = NULL ;
205 curtype = txt_sublist;
206 currec = NULL ; curarg = NULL ;
208 oneargpage = (struct argpage*) malloc ( sizeof(struct argpage) );
209 oneargpage->next = NULL; oneargpage->used = 0;
213 /* INTERMEDIAIRE : passage de Header a Data */
214 void rec_finhead() { nbhead = nbrec; }
216 /* CONCLUSION : actuellement, ne fait rien */
218 void rec_finfile() { }
221 /* GESTION DES RECORDS */
223 /* ENREGISTRER UN RECORD (deja pret) */
224 void static rec_new(newrec)
225 struct rec* newrec ; /* nouveau record a enregistrer */
228 if ( firstrec == NULL ) firstrec = newrec ;
229 if ( lastrec != NULL ) lastrec->next = newrec ;
233 /* type du dernier argument lu */
234 void rec_typarg(argtype)
236 { typarg = argtype; }
238 /* ENREGISTRER UNE ENTITE (record courant) */
241 rec_new(currec) ; /* le record courant (currec) est enregistre */
243 /* gestion des sous-listes : si currec a un suivant note (cf pointeur suite),
244 alors c'est une sous-liste et le suivant est son contenant
245 EN CE CAS, il faut memoriser cette sous-liste en argument courant
246 En effet, d'une part la liste est reconnue comme un argument, d'autre part
247 part elle se termine par ")" : c'est donc ici qu'elle sera enregistree */
249 rec_typarg (rec_argSub) ;
251 subarg = currec->ident ; /* si sous-liste, sera argument du contenant */
253 currec = currec->next ; /* si nul, c'est qu'une autre entite suit */
254 lastrec->next = NULL ;
258 static struct rec*rec_newrec()
261 if (onerecpage->used >= Maxrec) {
262 struct recpage* newrecpage;
263 newrecpage = (struct recpage*) malloc ( sizeof (struct recpage) );
264 newrecpage->next = onerecpage;
265 onerecpage = newrecpage;
266 onerecpage->used = 0;
268 newrec = &(onerecpage->args[onerecpage->used]);
275 /* RECORD COURANT : */
277 /* creer et preciser l'identifieur */
280 currec = rec_newrec();
281 /*currec = (struct rec*) malloc (sizeof (struct rec)) ;*/
282 /*currec->nbarg = 0 ;*/
283 rec_gettext(&(currec->ident)) ;
284 currec->next = NULL ; currec->first = NULL ; /*currec->last = NULL ;*/
288 /* preciser le type ; demarrage de la description de l'entite */
291 /* Pour le header : pas d'ident, donc en simuler un : derive de rec_ident */
293 /*currec = (struct rec*) malloc (sizeof (struct rec)) ;*/
294 currec = rec_newrec();
295 /*currec->nbarg = 0 ;*/
296 currec->ident = idzero; /* Ident bidon (il en faut un ...) */
297 currec->next = NULL ; currec->first = NULL ; /*currec->last = NULL ;*/
299 rec_gettext(&(currec->type)) ;
300 yarec = numsub = 0 ; /* debut de l'entite */
303 /* type d une liste qui n est pas une entite mais un argument
304 par defaut (cf rec_deblist) il n est pas defini donc mis = "/ (SUB) /" */
306 { rec_gettext(&(curtype)); }
308 /* ajouter un argument (type & valeur deja connus) */
311 struct unarg *newarg;
313 /*currec->nbarg ++ ;*/
314 /* newarg = (struct unarg*) malloc (sizeof (struct unarg)) ; */
315 if (oneargpage->used >= Maxarg) {
316 struct argpage* newargpage;
317 newargpage = (struct argpage*) malloc ( sizeof(struct argpage) );
318 newargpage->next = oneargpage;
319 oneargpage = newargpage;
320 oneargpage->used = 0;
322 newarg = &(oneargpage->args[oneargpage->used]);
325 newarg->type = typarg ;
326 if (typarg == rec_argSub) newarg->val = subarg ;
327 else rec_gettext (&(newarg->val));
329 /* if (currec->first == NULL) currec->first = newarg;
330 else currec->last->next = newarg;
331 currec->last = newarg;*/
332 if (currec->first == NULL) currec->first = newarg;
334 struct unarg* nextarg = currec->first;
335 while(nextarg->next != NULL)
336 nextarg = nextarg->next;
337 nextarg->next = newarg;
340 newarg->next = NULL ;
344 /* Ajouter une sous-liste
346 Une ouverture de parentheses A L'INTERIEUR d'une liste de parametres
347 signale une sous-liste : c'est une entite non identifiee, directement
348 utilisee comme argument de la liste contenante) d'un type reserve(SUB)
350 Elle est enregistree avec un identifieur special : '$' suivi d'un numero
351 de sous-liste dans l'entite en cours.
353 Son enregistrement consiste a definir un nouveau record courant, pour la
354 sous-liste, qui note comme suivant l'ancien courant, qui est son contenant
355 A la fin de la sous-liste, elle est enregistree comme toute entite (cf
356 rec_new) mais le suivant devient le nouveau courant dont l'enregistrement
357 des parametres continue
359 La premiere ouverture de parentheses dans l'entite est celle de la liste
360 principale de parametres et non d'une sous-liste
365 if (numsub > 0) { /* enregistrement d'une sous-liste */
366 /* int i ; */ struct rec* subrec ;
367 /* creation du nouvel enregistrement et chainage au precedent */
368 subrec = rec_newrec();
369 /*subrec = (struct rec*) malloc (sizeof (struct rec)) ;*/
371 case 1: subrec->ident = sub1; break;
372 case 2: subrec->ident = sub2; break;
375 if (numsub > 9) sprintf (bufsub,"$%d",numsub) ;
376 else { bufsub[0] = '$'; bufsub[1] = numsub + 48; bufsub[2] = '\0'; }
377 subrec->ident = rec_newtext(bufsub) ;
380 subrec->type = curtype ;
381 curtype = txt_sublist; /* type reserve par defaut */
382 /*subrec->nbarg = 0 ;*/ subrec->next = currec ;
383 subrec->first = NULL ; /*subrec->last = NULL ;*/
384 /* les arguments de la sous-liste vont suivre ;
385 elle meme est argument de son contenant, ce qui est pris en compte
386 a la fermeture de la parenthese */
387 currec = subrec ; /* substitution finale */
389 numsub ++ ; /* numero de la prochaine sous-liste (la principale est en 0) */
394 /* Affichage du contenu d'un record */
395 void rec_print(unrec)
398 int numa = 0; int numl = 0; int argl = 0;
399 if (unrec == NULL) { printf ("Non defini\n") ; return; }
400 printf ("Ident : %s Type : %s Nb.Arg.s : %s\n",
401 unrec->ident,unrec->type, (unrec->first ? unrec->first->val : "")) ;
402 if (modeprint < 2) return ;
403 curarg = unrec->first ;
404 while (curarg != NULL) {
405 numa ++; argl = strlen(curarg->val) + 18; numl += argl;
406 if (numl > 132) { printf("\n"); numl = argl; }
407 printf (" - Arg.%d[%c%c] : %s",
408 numa,argtype1[curarg->type],argtype2[curarg->type],curarg->val);
409 curarg = curarg->next ;
411 if (argl > 0) printf("\n");
415 /* GESTION DES SCOPES */
417 /* Ouverture de scope :
418 un scope est un record particulier (pas de type ni d'argument)
419 d'une part il est enregistre, d'autre part il faut gerer le record en cours
420 En effet, une entite step etait en cours d'enregistrement (ident deja connu),
421 mais son type et ses arguments seront fournis apres fermeture du scope ...
422 Il faut donc la mettre de cote (c'est currec), pour la restaurer ensuite
424 Mais ATTENTION, il y a l'EXPORT : au ENDSCOPE, peut etre attachee une liste
425 d'Idents : ce sont les idents internes au SCOPE mais declares visibles de
426 l'exterieur du SCOPE (en plus de l''entite sur laquelle il porte)
431 /* ouverture du scope et sauvegarde de l'entite en cours */
432 struct scope* newscope; struct rec* unscope;
433 newscope = (struct scope*) malloc (sizeof (struct scope)) ;
434 newscope->rec = currec ;
435 newscope->prev = curscope ;
436 curscope = newscope ;
438 /* enregistrement de ce scope comme un record */
439 unscope = rec_newrec();
440 /*unscope = (struct rec*) malloc (sizeof (struct rec)) ;*/
441 unscope->ident = txt_scope ;
442 unscope->type = txt_nil ;
443 unscope->first = NULL;
444 /*unscope->nbarg = 0 ;*/
448 /* Fermeture de scope :
449 La fin de scope est, comme son debut, un enregistrement special.
450 Il faut donc l'enregistrer.
451 Il faut aussi restaurer l'entite concernee par le scope, afin de terminer
452 son enregistrement (manquent ses arguments) */
455 { struct scope* oldscope ; struct rec* unscope;
456 if (curscope == NULL) return ; /* cela dit, c'est anormal ... */
458 /* enregistrement de cette fin de scope comme un record */
459 unscope = rec_newrec();
460 /* unscope = (struct rec*) malloc (sizeof (struct rec)) ;*/
461 unscope->ident = txt_endscope ;
462 unscope->type = txt_nil ;
463 unscope->first = NULL;
464 /*unscope->nbarg = 0 ;*/
466 /* Si on doit prendre en compte une Export List ... */
467 if (subarg[0] == '$') {
469 printf("Export List : (List in Record n0 %d) -- ",nbrec);
478 /* fermeture effective du scope */
479 currec = curscope->rec ; /* restaurer l'entite en cours d'enreg. */
481 oldscope = curscope ;
482 curscope = oldscope->prev ; /* restauration de l'etat precedent */
483 free (oldscope) ; /* suppression "physique" */
487 /* CONCLUSION : retour des valeurs pour constituer la liste des records,
488 sous forme de directory / tableau
490 La liberation de la memoire est faite par lir_file_fin, en une fois
493 void lir_file_nbr(nbh,nbr,nbp)
494 int* nbh; int* nbr; int* nbp;
495 /* initialise le traitement et retourne la taille du directory et du header */
499 *nbh = nbhead; *nbr = nbrec; *nbp = nbpar;
502 void lir_file_fin(mode)
504 /* fin du traitement : regroupe les liberations de memoire en une phase */
505 /* mode = 1 : rec+arg. 2 : carpage; 3 : 1+2 */
508 while(onerecpage != NULL) {
509 struct recpage* newpage; newpage = onerecpage->next;
511 onerecpage = newpage;
515 /* struct rec* oldrec;
518 while (currec != NULL) {
520 currec = currec->next;*/
521 /* liberation memoire pour type & ident : si scope-endscope rien a liberer
522 si sous-liste : type pas a liberer, ident partage aussi par l'argument sera
523 libere par lui ... donc ici aussi, rien a liberer. CQFD */
526 while (oneargpage != NULL) {
527 struct argpage* newpage; newpage = oneargpage->next;
529 oneargpage = newpage;
533 while (onecarpage != NULL) {
534 struct carpage* newpage; newpage = onecarpage->next;
536 onecarpage = newpage;
541 int lir_file_rec(ident,type,nbarg)
542 /* retourne les parametres du record courant
543 retour de fonction ; 1 si ok, 0 si liste epuisee */
544 char* *ident ; char* *type ; int *nbarg ;
546 if (currec == NULL) return (0) ;
548 *ident = currec->ident ;
549 *type = currec->type ;
550 *nbarg = (currec->first != NULL);
551 curarg = currec->first ; /* prepare lecture arg.s */
555 void lir_file_finrec()
556 /* fait le menage et passe au record suivant
557 ne pas appeler apres l'indication de fin mais apres chaque record ok ! */
559 currec = currec->next ;
563 int lir_file_arg(type,val)
564 int* type ; char* *val ;
565 /* lit l'argument courant (au debut le 1er), fait le menage, prepare suivant
566 retourne 1 si ok, 0 si c'est fini
567 attention, suppose que nbarg > 0 ... (bref, pas de protection) */
569 if (curarg == NULL) return (0) ;
570 *type = curarg->type ;
572 curarg = curarg->next ;
577 /* Verification de l'integrite des donnees */
579 /* Affiche ce qui ne va pas, mais aussi accede a tout : ainsi, les adresses
580 verolees aparaissent au grand jour du dbx */
583 int mode ; /* =1 pas de controle nbrec (en cours d'enregistrement) */
585 struct rec* lerec ; struct unarg* larg ; int nr,na ;
587 if (mode == 2) lerec = currec ;
589 while (lerec != NULL) {
591 if (lerec->ident == NULL) printf("Record %d : ident null\n",nr) ;
592 if (lerec->type == NULL) printf("Record %d : type null\n",nr) ;
593 /*if (mode < 2 && (lerec->nbarg < 0 || lerec->nbarg > 10) ) printf
594 ("N.B.: Record %d : nbarg pas entre 0 & 10, vaut %d\n",nr,lerec->nbarg);
597 larg = lerec->first ;
598 while (larg != NULL) {
600 if (larg->type < 0 || larg->type > 9) printf
601 ("Record %d , Arg. %d : type incorrect : %d\n",nr,na,larg->type) ;
602 if (larg->val == NULL) printf("Record %d , Arg %d : val null\n",nr,na) ;
605 /*if (na != lerec->nbarg) printf
606 ("Record %d : arglist pourrie, nb note %d relu %d\n",nr,lerec->nbarg,na) ;*/
607 lerec = lerec->next ;
609 if (mode == 0 && nr != nbrec) printf
610 ("Liste des records pourrie, nb note %d relu %d\n",nbrec,nr) ;
613 void steperror (char *mess);