2 Copyright (c) 1999-2014 OPEN CASCADE SAS
4 This file is part of Open CASCADE Technology software library.
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
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.
12 Alternatively, this file may be used under the terms of Open CASCADE
13 commercial license or contractual agreement.
23 /* enregistrement d'un fichier d'interface sous forme de records
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
33 /* ROUTINES UTILITAIRES de traitement des textes (char*) */
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
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 */
50 static char* restext = NULL ; /* texte courant (allocation dynamique) */
51 /* static int resalloc = 0 ;*/ /* alloue (memoire a liberer) ou non */
53 static char txt_cart_p[] = "CARTESIAN_POINT";
55 void rec_restext(char* newtext, int lentext) /* destine a etre appele de l'exterieur */
58 if(strcmp(newtext,txt_cart_p)==0) {
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;
72 restext = onecarpage->cars + onecarpage->used;
73 onecarpage->used += (lentext + 1);
75 res = restext ; text = newtext;
76 while (*text != '\0') { *res=*text ; res++ ; text++ ; }
80 void rec_gettext(char* *r)
81 /* Le resultat retourne (pointeur) est destine a etre inclus dans un struct */
84 void rec_settext(char* s)
85 /* substituer le texte courant par un autre deja alloue */
88 char* rec_newtext(char* r)
89 /* routine utilitaire creant une chaine dynamique a partir d'un char[] */
94 rec_restext(r,(int)strlen(r));
102 static int modeprint = 0 ; /* CONTROLE D'IMPRESSION (pour appel depuis yacc)*/
104 /* DECLARATIONS des donnees de travail (en cours d'enregistrement) */
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) */
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 */
122 static struct recpage {
123 struct recpage* next;
125 struct rec args[Maxrec+1];
128 static struct rec* firstrec ; /* 1er record du fichier */
129 static struct rec* lastrec ; /* dernier record du fichier */
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 */
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 */
143 static struct argpage { /* Allocation optimisee des arguments */
144 struct argpage* next;
146 struct unarg args[Maxarg+1];
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 */
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";
169 /* Trace pour controle */
170 void recfile_modeprint(int mode)
171 { modeprint = mode; }
174 extern int steplineno;
191 /*initialization of recpage*/
192 onerecpage = (struct recpage*) malloc ( sizeof(struct recpage) );
193 onerecpage->used = 0; onerecpage->next = NULL;
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 ;
201 oneargpage = (struct argpage*) malloc ( sizeof(struct argpage) );
202 oneargpage->next = NULL; oneargpage->used = 0;
206 /* INTERMEDIAIRE : passage de Header a Data */
207 void rec_finhead() { nbhead = nbrec; }
209 /* CONCLUSION : actuellement, ne fait rien */
211 void rec_finfile() { }
214 /* GESTION DES RECORDS */
216 /* ENREGISTRER UN RECORD (deja pret) */
217 static void rec_new(struct rec* newrec)
218 /* nouveau record a enregistrer */
221 if ( firstrec == NULL ) firstrec = newrec ;
222 if ( lastrec != NULL ) lastrec->next = newrec ;
226 /* type du dernier argument lu */
227 void rec_typarg(int argtype)
228 { typarg = argtype; }
230 /* ENREGISTRER UNE ENTITE (record courant) */
233 rec_new(currec) ; /* le record courant (currec) est enregistre */
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 */
241 rec_typarg (rec_argSub) ;
243 subarg = currec->ident ; /* si sous-liste, sera argument du contenant */
245 currec = currec->next ; /* si nul, c'est qu'une autre entite suit */
246 lastrec->next = NULL ;
250 static struct rec*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;
260 newrec = &(onerecpage->args[onerecpage->used]);
267 /* RECORD COURANT : */
269 /* creer et preciser l'identifieur */
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 ;*/
280 /* preciser le type ; demarrage de la description de l'entite */
283 /* Pour le header : pas d'ident, donc en simuler un : derive de rec_ident */
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 ;*/
291 rec_gettext(&(currec->type)) ;
292 yarec = numsub = 0 ; /* debut de l'entite */
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) /" */
298 { rec_gettext(&(curtype)); }
300 /* ajouter un argument (type & valeur deja connus) */
303 struct unarg *newarg;
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;
314 newarg = &(oneargpage->args[oneargpage->used]);
317 newarg->type = typarg ;
318 if (typarg == rec_argSub) newarg->val = subarg ;
319 else rec_gettext (&(newarg->val));
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;
326 struct unarg* nextarg = currec->first;
327 while(nextarg->next != NULL)
328 nextarg = nextarg->next;
329 nextarg->next = newarg;
332 newarg->next = NULL ;
336 /* Ajouter une sous-liste
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)
342 Elle est enregistree avec un identifieur special : '$' suivi d'un numero
343 de sous-liste dans l'entite en cours.
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
351 La premiere ouverture de parentheses dans l'entite est celle de la liste
352 principale de parametres et non d'une sous-liste
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)) ;*/
363 case 1: subrec->ident = sub1; break;
364 case 2: subrec->ident = sub2; break;
367 if (numsub > 9) sprintf (bufsub,"$%d",numsub) ;
368 else { bufsub[0] = '$'; bufsub[1] = (char)(numsub + 48); bufsub[2] = '\0'; }
369 subrec->ident = rec_newtext(bufsub) ;
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 */
381 numsub ++ ; /* numero de la prochaine sous-liste (la principale est en 0) */
386 /* Affichage du contenu d'un record */
387 void rec_print(struct rec* unrec)
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) {
397 argl = (int)strlen(curarg->val) + 18;
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 ;
404 if (argl > 0) printf("\n");
408 /* GESTION DES SCOPES */
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
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)
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 ;
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 ;*/
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) */
448 { struct scope* oldscope ; struct rec* unscope;
449 if (curscope == NULL) return ; /* cela dit, c'est anormal ... */
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 ;*/
459 /* Si on doit prendre en compte une Export List ... */
460 if (subarg[0] == '$') {
462 printf("Export List : (List in Record n0 %d) -- ",nbrec);
471 /* fermeture effective du scope */
472 currec = curscope->rec ; /* restaurer l'entite en cours d'enreg. */
474 oldscope = curscope ;
475 curscope = oldscope->prev ; /* restauration de l'etat precedent */
476 free (oldscope) ; /* suppression "physique" */
480 /* CONCLUSION : retour des valeurs pour constituer la liste des records,
481 sous forme de directory / tableau
483 La liberation de la memoire est faite par lir_file_fin, en une fois
486 void lir_file_nbr(int* nbh, int* nbr, int* nbp)
487 /* initialise le traitement et retourne la taille du directory et du header */
491 *nbh = nbhead; *nbr = nbrec; *nbp = nbpar;
494 void lir_file_fin(int mode)
495 /* fin du traitement : regroupe les liberations de memoire en une phase */
496 /* mode = 1 : rec+arg. 2 : carpage; 3 : 1+2 */
499 while(onerecpage != NULL) {
500 struct recpage* newpage; newpage = onerecpage->next;
502 onerecpage = newpage;
506 /* struct rec* oldrec;
509 while (currec != NULL) {
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 */
517 while (oneargpage != NULL) {
518 struct argpage* newpage; newpage = oneargpage->next;
520 oneargpage = newpage;
524 while (onecarpage != NULL) {
525 struct carpage* newpage; newpage = onecarpage->next;
527 onecarpage = newpage;
532 int lir_file_rec(char* *ident, char* *type, int *nbarg)
533 /* retourne les parametres du record courant
534 retour de fonction ; 1 si ok, 0 si liste epuisee */
536 if (currec == NULL) return (0) ;
538 *ident = currec->ident ;
539 *type = currec->type ;
540 *nbarg = (currec->first != NULL);
541 curarg = currec->first ; /* prepare lecture arg.s */
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 ! */
549 currec = currec->next ;
553 int lir_file_arg(int* type, char* *val)
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) */
558 if (curarg == NULL) return (0) ;
559 *type = curarg->type ;
561 curarg = curarg->next ;
566 /* Verification de l'integrite des donnees */
568 /* Affiche ce qui ne va pas, mais aussi accede a tout : ainsi, les adresses
569 verolees aparaissent au grand jour du dbx */
571 void rec_check(int mode)
572 /* mode=1 pas de controle nbrec (en cours d'enregistrement) */
574 struct rec* lerec ; struct unarg* larg ; int nr,na ;
576 if (mode == 2) lerec = currec ;
578 while (lerec != NULL) {
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);
586 larg = lerec->first ;
587 while (larg != NULL) {
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) ;
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 ;
598 if (mode == 0 && nr != nbrec) printf
599 ("Liste des records pourrie, nb note %d relu %d\n",nbrec,nr) ;
602 void steperror (char *mess);