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(char* newtext, int lentext) /* destine a etre appele de l'exterieur */
63 if(strcmp(newtext,txt_cart_p)==0) {
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;
77 restext = onecarpage->cars + onecarpage->used;
78 onecarpage->used += (lentext + 1);
80 res = restext ; text = newtext;
81 while (*text != '\0') { *res=*text ; res++ ; text++ ; }
85 void rec_gettext(char* *r)
86 /* Le resultat retourne (pointeur) est destine a etre inclus dans un struct */
89 void rec_settext(char* s)
90 /* substituer le texte courant par un autre deja alloue */
93 char* rec_newtext(char* r)
94 /* routine utilitaire creant une chaine dynamique a partir d'un char[] */
99 rec_restext(r,(int)strlen(r));
101 restext = savrestext;
107 static int modeprint = 0 ; /* CONTROLE D'IMPRESSION (pour appel depuis yacc)*/
109 /* DECLARATIONS des donnees de travail (en cours d'enregistrement) */
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) */
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 */
127 static struct recpage {
128 struct recpage* next;
130 struct rec args[Maxrec+1];
133 static struct rec* firstrec ; /* 1er record du fichier */
134 static struct rec* lastrec ; /* dernier record du fichier */
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 */
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 */
148 static struct argpage { /* Allocation optimisee des arguments */
149 struct argpage* next;
151 struct unarg args[Maxarg+1];
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 */
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";
174 /* Trace pour controle */
175 void recfile_modeprint(int mode)
176 { modeprint = mode; }
179 extern int steplineno;
196 /*initialization of recpage*/
197 onerecpage = (struct recpage*) malloc ( sizeof(struct recpage) );
198 onerecpage->used = 0; onerecpage->next = NULL;
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 ;
206 oneargpage = (struct argpage*) malloc ( sizeof(struct argpage) );
207 oneargpage->next = NULL; oneargpage->used = 0;
211 /* INTERMEDIAIRE : passage de Header a Data */
212 void rec_finhead() { nbhead = nbrec; }
214 /* CONCLUSION : actuellement, ne fait rien */
216 void rec_finfile() { }
219 /* GESTION DES RECORDS */
221 /* ENREGISTRER UN RECORD (deja pret) */
222 void static rec_new(struct rec* newrec)
223 /* nouveau record a enregistrer */
226 if ( firstrec == NULL ) firstrec = newrec ;
227 if ( lastrec != NULL ) lastrec->next = newrec ;
231 /* type du dernier argument lu */
232 void rec_typarg(int argtype)
233 { typarg = argtype; }
235 /* ENREGISTRER UNE ENTITE (record courant) */
238 rec_new(currec) ; /* le record courant (currec) est enregistre */
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 */
246 rec_typarg (rec_argSub) ;
248 subarg = currec->ident ; /* si sous-liste, sera argument du contenant */
250 currec = currec->next ; /* si nul, c'est qu'une autre entite suit */
251 lastrec->next = NULL ;
255 static struct rec*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;
265 newrec = &(onerecpage->args[onerecpage->used]);
272 /* RECORD COURANT : */
274 /* creer et preciser l'identifieur */
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 ;*/
285 /* preciser le type ; demarrage de la description de l'entite */
288 /* Pour le header : pas d'ident, donc en simuler un : derive de rec_ident */
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 ;*/
296 rec_gettext(&(currec->type)) ;
297 yarec = numsub = 0 ; /* debut de l'entite */
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) /" */
303 { rec_gettext(&(curtype)); }
305 /* ajouter un argument (type & valeur deja connus) */
308 struct unarg *newarg;
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;
319 newarg = &(oneargpage->args[oneargpage->used]);
322 newarg->type = typarg ;
323 if (typarg == rec_argSub) newarg->val = subarg ;
324 else rec_gettext (&(newarg->val));
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;
331 struct unarg* nextarg = currec->first;
332 while(nextarg->next != NULL)
333 nextarg = nextarg->next;
334 nextarg->next = newarg;
337 newarg->next = NULL ;
341 /* Ajouter une sous-liste
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)
347 Elle est enregistree avec un identifieur special : '$' suivi d'un numero
348 de sous-liste dans l'entite en cours.
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
356 La premiere ouverture de parentheses dans l'entite est celle de la liste
357 principale de parametres et non d'une sous-liste
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)) ;*/
368 case 1: subrec->ident = sub1; break;
369 case 2: subrec->ident = sub2; break;
372 if (numsub > 9) sprintf (bufsub,"$%d",numsub) ;
373 else { bufsub[0] = '$'; bufsub[1] = (char)(numsub + 48); bufsub[2] = '\0'; }
374 subrec->ident = rec_newtext(bufsub) ;
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 */
386 numsub ++ ; /* numero de la prochaine sous-liste (la principale est en 0) */
391 /* Affichage du contenu d'un record */
392 void rec_print(struct rec* unrec)
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) {
402 argl = (int)strlen(curarg->val) + 18;
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 ;
409 if (argl > 0) printf("\n");
413 /* GESTION DES SCOPES */
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
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)
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 ;
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 ;*/
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) */
453 { struct scope* oldscope ; struct rec* unscope;
454 if (curscope == NULL) return ; /* cela dit, c'est anormal ... */
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 ;*/
464 /* Si on doit prendre en compte une Export List ... */
465 if (subarg[0] == '$') {
467 printf("Export List : (List in Record n0 %d) -- ",nbrec);
476 /* fermeture effective du scope */
477 currec = curscope->rec ; /* restaurer l'entite en cours d'enreg. */
479 oldscope = curscope ;
480 curscope = oldscope->prev ; /* restauration de l'etat precedent */
481 free (oldscope) ; /* suppression "physique" */
485 /* CONCLUSION : retour des valeurs pour constituer la liste des records,
486 sous forme de directory / tableau
488 La liberation de la memoire est faite par lir_file_fin, en une fois
491 void lir_file_nbr(int* nbh, int* nbr, int* nbp)
492 /* initialise le traitement et retourne la taille du directory et du header */
496 *nbh = nbhead; *nbr = nbrec; *nbp = nbpar;
499 void lir_file_fin(int mode)
500 /* fin du traitement : regroupe les liberations de memoire en une phase */
501 /* mode = 1 : rec+arg. 2 : carpage; 3 : 1+2 */
504 while(onerecpage != NULL) {
505 struct recpage* newpage; newpage = onerecpage->next;
507 onerecpage = newpage;
511 /* struct rec* oldrec;
514 while (currec != NULL) {
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 */
522 while (oneargpage != NULL) {
523 struct argpage* newpage; newpage = oneargpage->next;
525 oneargpage = newpage;
529 while (onecarpage != NULL) {
530 struct carpage* newpage; newpage = onecarpage->next;
532 onecarpage = newpage;
537 int lir_file_rec(char* *ident, char* *type, int *nbarg)
538 /* retourne les parametres du record courant
539 retour de fonction ; 1 si ok, 0 si liste epuisee */
541 if (currec == NULL) return (0) ;
543 *ident = currec->ident ;
544 *type = currec->type ;
545 *nbarg = (currec->first != NULL);
546 curarg = currec->first ; /* prepare lecture arg.s */
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 ! */
554 currec = currec->next ;
558 int lir_file_arg(int* type, char* *val)
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) */
563 if (curarg == NULL) return (0) ;
564 *type = curarg->type ;
566 curarg = curarg->next ;
571 /* Verification de l'integrite des donnees */
573 /* Affiche ce qui ne va pas, mais aussi accede a tout : ainsi, les adresses
574 verolees aparaissent au grand jour du dbx */
576 void rec_check(int mode)
577 /* mode=1 pas de controle nbrec (en cours d'enregistrement) */
579 struct rec* lerec ; struct unarg* larg ; int nr,na ;
581 if (mode == 2) lerec = currec ;
583 while (lerec != NULL) {
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);
591 larg = lerec->first ;
592 while (larg != NULL) {
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) ;
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 ;
603 if (mode == 0 && nr != nbrec) printf
604 ("Liste des records pourrie, nb note %d relu %d\n",nbrec,nr) ;
607 void steperror (char *mess);