0027960: Configuration - fix compilation of OSD_Directory with MinGW-w64
[occt.git] / src / StepFile / recfile.pc
... / ...
CommitLineData
1/*
2 Copyright (c) 1999-2014 OPEN CASCADE SAS
3
4 This file is part of Open CASCADE Technology software library.
5
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.
11
12 Alternatively, this file may be used under the terms of Open CASCADE
13 commercial license or contractual agreement.
14*/
15
16#include "stdio.h"
17#include "string.h"
18#include "stdlib.h"
19#if (!defined(_WIN32) && !defined(__APPLE__))
20#include "malloc.h"
21#endif
22#include "recfile.ph"
23/* enregistrement d'un fichier d'interface sous forme de records
24 gere les scopes
25
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
30*/
31
32
33/* ROUTINES UTILITAIRES de traitement des textes (char*) */
34
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
40*/
41
42#define Maxcar 50000
43
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 */
48 } *onecarpage;
49
50 static char* restext = NULL ; /* texte courant (allocation dynamique) */
51 /* static int resalloc = 0 ;*/ /* alloue (memoire a liberer) ou non */
52
53static char txt_cart_p[] = "CARTESIAN_POINT";
54
55void rec_restext(char* newtext, int lentext) /* destine a etre appele de l'exterieur */
56{
57 char *res, *text;
58 if(strcmp(newtext,txt_cart_p)==0) {
59 restext = txt_cart_p;
60 return;
61 }
62
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;
69 onecarpage = newpage;
70 onecarpage->used = 0;
71 }
72 restext = onecarpage->cars + onecarpage->used;
73 onecarpage->used += (lentext + 1);
74/* strcpy */
75 res = restext ; text = newtext;
76 while (*text != '\0') { *res=*text ; res++ ; text++ ; }
77 *res = '\0' ;
78}
79
80void rec_gettext(char* *r)
81/* Le resultat retourne (pointeur) est destine a etre inclus dans un struct */
82{ *r = restext; }
83
84void rec_settext(char* s)
85/* substituer le texte courant par un autre deja alloue */
86{ restext = s ; }
87
88char* rec_newtext(char* r)
89/* routine utilitaire creant une chaine dynamique a partir d'un char[] */
90{
91 char* savrestext;
92 char* s0;
93 savrestext = restext;
94 rec_restext(r,(int)strlen(r));
95 s0 = restext;
96 restext = savrestext;
97 return (s0);
98}
99
100
101
102static int modeprint = 0 ; /* CONTROLE D'IMPRESSION (pour appel depuis yacc)*/
103
104/* DECLARATIONS des donnees de travail (en cours d'enregistrement) */
105
106static int typarg ; /* type du dernier argument lu */
107static int nbrec = 0; /* nombre total d'enregistrements de donnees */
108static int nbhead = 0; /* nb de records pris par le Header */
109static int nbpar = 0; /* nb de parametres lus au total */
110static int yarec = 0; /* presence Record deja cree (1 apres Ident) */
111
112static 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 */
120
121#define Maxrec 5000
122static struct recpage {
123 struct recpage* next;
124 int used;
125 struct rec args[Maxrec+1];
126} *onerecpage;
127
128static struct rec* firstrec ; /* 1er record du fichier */
129static struct rec* lastrec ; /* dernier record du fichier */
130
131static char* curtype; /* type dernier record (ou = sublist) */
132static char* subarg ; /* ident dernier record (sub-list eventuel) */
133static int numsub ; /* numero de sous-liste en cours */
134
135
136static 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 */
140} *curarg ;
141
142#define Maxarg 10000
143static struct argpage { /* Allocation optimisee des arguments */
144 struct argpage* next;
145 int used;
146 struct unarg args[Maxarg+1];
147} *oneargpage;
148
149
150static 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 */
155
156
157/* Constantes litterales */
158static char txt_sublist[] = "/* (SUB) */" ;
159static char txt_scope[] = "SCOPE" ;
160static char txt_endscope[] = "ENDSCOPE" ;
161static char txt_nil[] = " " ;
162static char sub1[] = "$1" ; /* optimisation ... */
163static char sub2[] = "$2" ;
164static char argtype1[] = "(IF#TnEHBx"; /* types arguments (2 1es lettres) */
165static char argtype2[] = ")nlIxdnxix";
166static char idzero[] = "#0";
167
168
169/* Trace pour controle */
170void recfile_modeprint(int mode)
171{ modeprint = mode; }
172
173static int lastno;
174extern int steplineno;
175extern int modcom;
176extern int modend;
177
178void rec_inityyll ()
179{
180 steplineno = 0;
181 modcom = 0;
182 modend = 0;
183 lastno = -1;
184}
185
186
187/* INITIALISATION */
188
189void rec_debfile()
190{
191 /*initialization of recpage*/
192 onerecpage = (struct recpage*) malloc ( sizeof(struct recpage) );
193 onerecpage->used = 0; onerecpage->next = NULL;
194
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 ;
200 curscope = NULL ;
201 oneargpage = (struct argpage*) malloc ( sizeof(struct argpage) );
202 oneargpage->next = NULL; oneargpage->used = 0;
203 rec_inityyll();
204}
205
206/* INTERMEDIAIRE : passage de Header a Data */
207void rec_finhead() { nbhead = nbrec; }
208
209/* CONCLUSION : actuellement, ne fait rien */
210
211void rec_finfile() { }
212
213
214/* GESTION DES RECORDS */
215
216/* ENREGISTRER UN RECORD (deja pret) */
217static void rec_new(struct rec* newrec)
218/* nouveau record a enregistrer */
219{
220 nbrec ++ ;
221 if ( firstrec == NULL ) firstrec = newrec ;
222 if ( lastrec != NULL ) lastrec->next = newrec ;
223 lastrec = newrec ;
224}
225
226/* type du dernier argument lu */
227void rec_typarg(int argtype)
228{ typarg = argtype; }
229
230/* ENREGISTRER UNE ENTITE (record courant) */
231void rec_newent()
232{
233 rec_new(currec) ; /* le record courant (currec) est enregistre */
234
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 */
240
241 rec_typarg (rec_argSub) ;
242
243 subarg = currec->ident ; /* si sous-liste, sera argument du contenant */
244/* rec_check(1) ; */
245 currec = currec->next ; /* si nul, c'est qu'une autre entite suit */
246 lastrec->next = NULL ;
247}
248
249
250static struct rec*rec_newrec()
251{
252 struct 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;
259 }
260 newrec = &(onerecpage->args[onerecpage->used]);
261 onerecpage->used++;
262
263 return newrec;
264}
265
266
267/* RECORD COURANT : */
268
269/* creer et preciser l'identifieur */
270void rec_ident()
271{
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 ;*/
277 yarec = 1;
278}
279
280/* preciser le type ; demarrage de la description de l'entite */
281void rec_type()
282{
283/* Pour le header : pas d'ident, donc en simuler un : derive de rec_ident */
284 if (!yarec) {
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 ;*/
290 }
291 rec_gettext(&(currec->type)) ;
292 yarec = numsub = 0 ; /* debut de l'entite */
293}
294
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) /" */
297void rec_listype()
298{ rec_gettext(&(curtype)); }
299
300/* ajouter un argument (type & valeur deja connus) */
301void rec_newarg()
302{
303 struct unarg *newarg;
304 nbpar ++;
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;
313 }
314 newarg = &(oneargpage->args[oneargpage->used]);
315 oneargpage->used ++;
316
317 newarg->type = typarg ;
318 if (typarg == rec_argSub) newarg->val = subarg ;
319 else rec_gettext (&(newarg->val));
320
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;
325 else {
326 struct unarg* nextarg = currec->first;
327 while(nextarg->next != NULL)
328 nextarg = nextarg->next;
329 nextarg->next = newarg;
330
331 }
332 newarg->next = NULL ;
333/* rec_check(0) ; */
334}
335
336/* Ajouter une sous-liste
337
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)
341
342 Elle est enregistree avec un identifieur special : '$' suivi d'un numero
343 de sous-liste dans l'entite en cours.
344
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
350
351 La premiere ouverture de parentheses dans l'entite est celle de la liste
352 principale de parametres et non d'une sous-liste
353*/
354
355void rec_deblist()
356{
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)) ;*/
362 switch (numsub) {
363 case 1: subrec->ident = sub1; break;
364 case 2: subrec->ident = sub2; break;
365 default: {
366 char bufsub[10];
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) ;
370 }
371 }
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 */
380 }
381 numsub ++ ; /* numero de la prochaine sous-liste (la principale est en 0) */
382/* rec_check(0) ; */
383}
384
385
386/* Affichage du contenu d'un record */
387void rec_print(struct rec* unrec)
388{
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) {
396 numa ++;
397 argl = (int)strlen(curarg->val) + 18;
398 numl += argl;
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 ;
403 }
404 if (argl > 0) printf("\n");
405 return ;
406}
407
408/* GESTION DES SCOPES */
409
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
416
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)
420*/
421
422void scope_debut()
423{
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 ;
430
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 ;*/
438 rec_new(unscope) ;
439}
440
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) */
446
447void scope_fin()
448{ struct scope* oldscope ; struct rec* unscope;
449 if (curscope == NULL) return ; /* cela dit, c'est anormal ... */
450
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 ;*/
458
459/* Si on doit prendre en compte une Export List ... */
460 if (subarg[0] == '$') {
461 if (modeprint > 0) {
462 printf("Export List : (List in Record n0 %d) -- ",nbrec);
463 rec_print(lastrec);
464 }
465 currec = unscope;
466 typarg = rec_argSub;
467 rec_newarg();
468 }
469 rec_new(unscope) ;
470
471/* fermeture effective du scope */
472 currec = curscope->rec ; /* restaurer l'entite en cours d'enreg. */
473 yarec = 1;
474 oldscope = curscope ;
475 curscope = oldscope->prev ; /* restauration de l'etat precedent */
476 free (oldscope) ; /* suppression "physique" */
477}
478
479
480/* CONCLUSION : retour des valeurs pour constituer la liste des records,
481 sous forme de directory / tableau
482
483 La liberation de la memoire est faite par lir_file_fin, en une fois
484*/
485
486void lir_file_nbr(int* nbh, int* nbr, int* nbp)
487/* initialise le traitement et retourne la taille du directory et du header */
488{
489 currec = firstrec ;
490/* rec_check(0) ; */
491 *nbh = nbhead; *nbr = nbrec; *nbp = nbpar;
492}
493
494void 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 */
497{
498 if (mode & 1) {
499 while(onerecpage != NULL) {
500 struct recpage* newpage; newpage = onerecpage->next;
501 free(onerecpage);
502 onerecpage = newpage;
503 }
504
505
506/* struct rec* oldrec;
507 oldrec = NULL;
508 currec = firstrec;
509 while (currec != NULL) {
510 oldrec = currec;
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 */
515/* free (oldrec) ;
516 }*/
517 while (oneargpage != NULL) {
518 struct argpage* newpage; newpage = oneargpage->next;
519 free (oneargpage);
520 oneargpage = newpage;
521 }
522 }
523 if (mode & 2) {
524 while (onecarpage != NULL) {
525 struct carpage* newpage; newpage = onecarpage->next;
526 free (onecarpage);
527 onecarpage = newpage;
528 }
529 }
530}
531
532int 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 */
535{
536 if (currec == NULL) return (0) ;
537/* rec_check(2) ; */
538 *ident = currec->ident ;
539 *type = currec->type ;
540 *nbarg = (currec->first != NULL);
541 curarg = currec->first ; /* prepare lecture arg.s */
542 return (1) ;
543}
544
545void 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 ! */
548{
549 currec = currec->next ;
550/* rec_check(2) ; */
551}
552
553int 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) */
557{
558 if (curarg == NULL) return (0) ;
559 *type = curarg->type ;
560 *val = curarg->val ;
561 curarg = curarg->next ;
562 return (1) ;
563}
564
565
566/* Verification de l'integrite des donnees */
567
568/* Affiche ce qui ne va pas, mais aussi accede a tout : ainsi, les adresses
569 verolees aparaissent au grand jour du dbx */
570
571void rec_check(int mode)
572/* mode=1 pas de controle nbrec (en cours d'enregistrement) */
573{
574 struct rec* lerec ; struct unarg* larg ; int nr,na ;
575 lerec = firstrec ;
576 if (mode == 2) lerec = currec ;
577 nr = 0 ;
578 while (lerec != NULL) {
579 nr ++ ;
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);
584 */
585 na = 0 ;
586 larg = lerec->first ;
587 while (larg != NULL) {
588 na ++ ;
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) ;
592 larg = larg->next ;
593 }
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 ;
597 }
598 if (mode == 0 && nr != nbrec) printf
599 ("Liste des records pourrie, nb note %d relu %d\n",nbrec,nr) ;
600}
601
602void steperror (char *mess);
603int steplex (void);
604