0023934: Compiler warnings in MS VC++ 10
[occt.git] / src / StepFile / recfile.pc
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
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
58 static char txt_cart_p[]   = "CARTESIAN_POINT";
59
60 void rec_restext(char* newtext, int lentext)         /* destine a etre appele de l'exterieur */
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
85 void rec_gettext(char* *r)
86 /*  Le resultat retourne (pointeur) est destine a etre inclus dans un struct */
87 { *r = restext; }
88
89 void rec_settext(char* s)
90 /* substituer le texte courant par un autre deja alloue */
91 {  restext = s ;  }
92
93 char* rec_newtext(char* r)
94 /*  routine utilitaire creant une chaine dynamique a partir d'un char[]  */
95 {
96   char* savrestext;
97   char* s0;
98   savrestext = restext;
99   rec_restext(r,(int)strlen(r));
100   s0 = restext;
101   restext = savrestext;
102   return (s0);
103 }
104
105
106
107 static int modeprint = 0 ;  /* CONTROLE D'IMPRESSION (pour appel depuis yacc)*/
108
109 /*      DECLARATIONS des donnees de travail (en cours d'enregistrement)     */
110
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) */
116
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 */
125
126 #define Maxrec 5000
127 static struct recpage {
128   struct recpage*  next;
129   int              used;
130   struct rec       args[Maxrec+1];
131 } *onerecpage;
132
133 static struct rec* firstrec ;  /* 1er record du fichier */
134 static struct rec* lastrec  ;  /* dernier record du fichier */
135
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 */
139
140
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 */
145 }  *curarg ;
146
147 #define Maxarg 10000
148 static struct argpage {        /*  Allocation optimisee des arguments  */
149   struct argpage*  next;
150   int              used;
151   struct unarg     args[Maxarg+1];
152 } *oneargpage;
153
154
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 */
160
161
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";
172
173
174 /*              Trace pour controle            */
175 void recfile_modeprint(int mode)
176 {  modeprint = mode;  }
177
178 static int   lastno;
179 extern int   steplineno;
180 extern int   modcom;
181 extern int   modend;
182
183 void rec_inityyll ()
184 {  
185   steplineno = 0;
186   modcom = 0;
187   modend = 0;
188   lastno = -1;
189 }
190
191
192 /*   INITIALISATION   */
193
194 void 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    */
212 void rec_finhead()  {  nbhead = nbrec;  }
213
214 /*   CONCLUSION  :  actuellement, ne fait rien   */
215
216 void rec_finfile()  {  }
217
218
219 /*   GESTION DES RECORDS   */
220
221 /*   ENREGISTRER UN RECORD (deja pret)    */
222 void static rec_new(struct rec* newrec)
223 /*  nouveau record a enregistrer  */
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  */
232 void rec_typarg(int argtype)
233 {  typarg = argtype;  }
234
235 /*   ENREGISTRER UNE ENTITE (record courant)   */
236 void 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
255 static 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   */
275 void 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  */
286 void 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) /" */
302 void rec_listype()
303 {  rec_gettext(&(curtype));  }
304
305 /*  ajouter un argument (type & valeur deja connus) */
306 void 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
360 void 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) ;
373     else {  bufsub[0] = '$'; bufsub[1] = (char)(numsub + 48); bufsub[2] = '\0';  }
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   */
392 void rec_print(struct rec* unrec)
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) {
401    numa ++;
402    argl = (int)strlen(curarg->val) + 18;
403    numl += argl;
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
427 void 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
452 void 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
491 void lir_file_nbr(int* nbh, int* nbr, int* nbp)
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
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  */
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
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   */
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
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 !   */
553 {
554  currec = currec->next ;
555 /*                                   rec_check(2) ;   */
556 }
557
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)   */
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
576 void rec_check(int mode)
577 /* mode=1 pas de controle nbrec (en cours d'enregistrement) */
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
607 void steperror (char *mess);
608 int  steplex (void);
609