0024180: Eliminate CLang / GCC compiler warning -Wswitch
[occt.git] / src / StepFile / recfile.pc
CommitLineData
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
58static char txt_cart_p[] = "CARTESIAN_POINT";
59
498ce76b 60void 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 85void 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 89void rec_settext(char* s)
90/* substituer le texte courant par un autre deja alloue */
7fd59977 91{ restext = s ; }
92
498ce76b 93char* 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
107static int modeprint = 0 ; /* CONTROLE D'IMPRESSION (pour appel depuis yacc)*/
108
109/* DECLARATIONS des donnees de travail (en cours d'enregistrement) */
110
111static int typarg ; /* type du dernier argument lu */
112static int nbrec = 0; /* nombre total d'enregistrements de donnees */
113static int nbhead = 0; /* nb de records pris par le Header */
114static int nbpar = 0; /* nb de parametres lus au total */
115static int yarec = 0; /* presence Record deja cree (1 apres Ident) */
116
117static 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
127static struct recpage {
128 struct recpage* next;
129 int used;
130 struct rec args[Maxrec+1];
131} *onerecpage;
132
133static struct rec* firstrec ; /* 1er record du fichier */
134static struct rec* lastrec ; /* dernier record du fichier */
135
136static char* curtype; /* type dernier record (ou = sublist) */
137static char* subarg ; /* ident dernier record (sub-list eventuel) */
138static int numsub ; /* numero de sous-liste en cours */
139
140
141static 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
148static struct argpage { /* Allocation optimisee des arguments */
149 struct argpage* next;
150 int used;
151 struct unarg args[Maxarg+1];
152} *oneargpage;
153
154
155static 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 */
163static char txt_sublist[] = "/* (SUB) */" ;
164static char txt_scope[] = "SCOPE" ;
165static char txt_endscope[] = "ENDSCOPE" ;
166static char txt_nil[] = " " ;
167static char sub1[] = "$1" ; /* optimisation ... */
168static char sub2[] = "$2" ;
169static char argtype1[] = "(IF#TnEHBx"; /* types arguments (2 1es lettres) */
170static char argtype2[] = ")nlIxdnxix";
171static char idzero[] = "#0";
172
173
174/* Trace pour controle */
498ce76b 175void recfile_modeprint(int mode)
7fd59977 176{ modeprint = mode; }
177
178static int lastno;
179extern int steplineno;
180extern int modcom;
181extern int modend;
182
183void rec_inityyll ()
184{
185 steplineno = 0;
186 modcom = 0;
187 modend = 0;
188 lastno = -1;
189}
190
191
192/* INITIALISATION */
193
194void 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 */
212void rec_finhead() { nbhead = nbrec; }
213
214/* CONCLUSION : actuellement, ne fait rien */
215
216void rec_finfile() { }
217
218
219/* GESTION DES RECORDS */
220
221/* ENREGISTRER UN RECORD (deja pret) */
f24125b9 222static 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 232void rec_typarg(int argtype)
7fd59977 233{ typarg = argtype; }
234
235/* ENREGISTRER UNE ENTITE (record courant) */
236void 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
255static 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 */
275void 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 */
286void 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) /" */
302void rec_listype()
303{ rec_gettext(&(curtype)); }
304
305/* ajouter un argument (type & valeur deja connus) */
306void 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
360void 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 392void 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
427void 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
452void 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 491void 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 499void 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 537int 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
550void 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 558int 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 576void 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
607void steperror (char *mess);
608int steplex (void);
609