/* XBlockOut a 3D Tetris Copyright (C) 1992,1993,1994 Thierry EXCOFFIER This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Contact: Thierry.EXCOFFIER@liris.univ-lyon1.fr */ /* * Acces aux options d'un programme * * Vous devez : * - Inclure ce fichier * - Definir les options : * int verbose ; * char *fichierin ; * ... * struct options toto[] = { { "v" , 'b' , (void*)&verbose, * "Affiche des messages d'explication" } , * { "infile" , 's' , (void*)&fichierin, * "Nom du fichier en entree" } , * .... * { "" , ' ' , 0 , "" } * } ; * * Les types sont les suivants : * 'b' int Booleen (rien derriere) * 's' char* Chaine de caracteres * 'i' int Entier ecrit apres de type "int" * * - L'appel : prendoptions( &toto , &argc , argv ) ; * Les options restantes sont retournees. * * - Le texte de help permet de definir des bornes, il verifit : * .......... (choix_1,choix_2,choix_3) ..... * Le contenu de chaque groupe de parenthese trouve. * Les separateurs etant ' ' ',' '/' '|' * Ce qui est entre un separateur et un ':' * Pour un nombre #...# ou #-# decrit l'interval. * Par exemple : * "Affichage du texte (gauche,droite,centre)" * "g:Texte cadre a gauche, d:A droite et c:centre" * "1-31: Jour du mois, 0: jour inconnu" * "Jour d'ouverture (lun,mar,mer,jeu,ven,sam,dim,1-7)" * S'il y a aucun critere, aucun test n'est fait * */ #define DECALAGE_DROITE " " /* Decalage a droite */ #define NB_DIGIT_MAX 10 /* Nombre Maxi de chiffre dans un entier*/ #define MAXLINE 132 #define V(X) ((void*)&(X)) #define NB_MAX_ARGS 100 #include #if HAVE_STDLIB_H #include #endif #if HAVE_STRING_H #include #else #include #endif #ifdef HAVE_MALLOC_H #include "malloc.h" #endif #include #include "options.h" void prendoptions(struct options *t, int *argc, char **argv) { int i,j,l,nbo ; char **wr ; char *pc ; int options_correctes(char *val, char *help, char *nom) ; wr = argv ; nbo = *argc ; for(i=1;i= t[j].buffer_size-1 ) { fprintf(stderr, "Buffer overflow\n") ; exit(1) ; } strcpy( (char*)t[j].valeur , pc ) ; break ; case 'f' : if ( sscanf(pc,"%g",(float*)(t[j].valeur)) != 1 ) { fprintf(stderr,"<%s> must be a float\n", t[j].nom) ; proptions(t) ; exit(1) ; } break ; case 'i' : if ( sscanf(pc,"%d",(int*)(t[j].valeur)) != 1 ) { fprintf(stderr,"<%s> must be an integer\n", t[j].nom) ; proptions(t) ; exit(1) ; } } (*argc)-- ; break ; default : fprintf(stderr,"Option class '%c' unknown\n",t[j].type) ; exit(1) ; break ; } /* Fin switch */ break ; } /* Fin du if qui etait ok */ j++ ; /* Passage au test suivant */ } /* On n'a pas trouve l'option */ /* On la conserve dans la liste */ *wr++ = argv[i] ; } } void proptions(struct options *t) { int i,j ; /* Pour les boucle */ char *type ; /* Indique le type courant */ char *valeur ; /* Valeur courante */ char v[NB_DIGIT_MAX] ; /* Pour stocker l'entier */ char buf[MAXLINE] ; /* Pour un stockage temporaire */ int ldd ; /* Longueur decalage droite */ ldd = strlen(DECALAGE_DROITE) ; fprintf(stderr,"\nOptions are :\n\n") ; for(i=0;t[i].nom[0]!='\0';i++) { switch(t[i].type) { case 'b' : type="" ; break ; case 's' : type="" ; break ; case 'i' : type=""; break ; case 'f' : type=""; break ; default : fprintf(stderr,"Option type '%c' inconnu\n",t[i].type) ; exit(1) ; break ; } switch(t[i].type) { case 'b' : if (*((int*)(t[i].valeur))) valeur="TRUE" ; else valeur="FALSE" ; break ; case 's' : valeur = (char*)(t[i].valeur) ; break ; case 'i' : valeur=v ; sprintf(v,"%d",*((int*)(t[i].valeur))) ; break ; case 'f' : valeur=v ; sprintf(v,"%g",*((float*)(t[i].valeur))) ; break ; default : fprintf(stderr,"Option type '%c' inconnu\n",t[i].type) ; exit(1) ; break ; } sprintf(buf,"-%s %s [%s]",t[i].nom,type,valeur) ; if ( strlen(buf) >= ldd ) fprintf(stderr,"%s\n%s",buf,DECALAGE_DROITE) ; else fprintf(stderr,"%s%s",buf,&DECALAGE_DROITE[strlen(buf)]) ; valeur = t[i].help ; j = 0 ; while ( valeur[j]=='\n' || valeur[j]==' ' || valeur[j]=='\t' ) j++ ; for(;valeur[j]!='\0';j++) if ( valeur[j]=='\n' ) { fprintf(stderr,"\n%s",DECALAGE_DROITE) ; while( valeur[j]=='\n' || valeur[j]==' ' || valeur[j]=='\t' ) j++ ; j-- ; } else { fputc(valeur[j],stderr) ; } fputc('\n',stderr) ; } } int options_correctes(char *val, char *help, char *nom) { int unchoix ; int inpar ; int debutmot ; int chic ; int l ; int i ; char *choixpossibles ; unchoix = 0 ; /* Il n'y a rien pour choisir */ inpar = 0 ; /* On est a l'exterieur de parenthese */ debutmot= 0 ; /* Le help peut commence par un choix */ chic = 0 ; /* Passe a 1 si j'ai trouve */ l = strlen(val); choixpossibles = (char*) malloc( 2*strlen(help)+1 ) ; choixpossibles[0] = '\0' ; for(i=0;help[i]!='\0';i++) { switch( help[i] ) { case '(' : case '[' : case '{' : inpar++ ; debutmot = i+1 ; break ; case ')' : case ']' : case '}' : if ( inpar!=0 ) inpar-- ; case '|' : case ':' : strncat(choixpossibles,&help[debutmot],(size_t)(i-debutmot)) ; strcat(choixpossibles," ") ; if ( comparok(val,l,&help[debutmot]) ) { chic = 1 ; break ; } unchoix = 1 ; debutmot = i+1 ; break ; case ' ' : case ',' : case '/' : case '\t' : case '\n' : if ( inpar!=0 ) { strncat(choixpossibles,&help[debutmot],(size_t)(i-debutmot)) ; strcat(choixpossibles," ") ; if ( comparok(val,l,&help[debutmot]) ) { chic = 1 ; break ; } unchoix = 1 ; } debutmot = i+1 ; break ; } } if ( unchoix && chic==0 ) { fprintf(stderr,"Possibles choices for <%s> are : %s\n", nom,choixpossibles) ; } else chic = 1 ; free((void*)choixpossibles) ; return(chic) ; } int comparok(char *v, int lv, char *h) /* Valeur a tester */ /* Longueur de "v" */ /* Debut de la chaine decriptive*/ { int min,max,val ; if ( strncmp( h,v,(size_t)lv ) == 0 ) return(1) ; if ( strncmp( h,"...",3 ) == 0 ) return(1) ; if ( sscanf(v,"%d",&val)!=1 ) return(0) ; if ( sscanf(h,"%d%*[-.]%d",&min,&max) == 2 ) { if ( val>=min && val<=max ) return(1) ; else return(0) ; } return(0) ; } void stringoption(struct options *o, char *s) { char *argv[NB_MAX_ARGS] ; char *b ; int i ; int bet ; int num ; char *pc ; i = 1 ; bet = 0 ; b = (char*) malloc( strlen(s)+NB_MAX_ARGS ) ; pc = b ; argv[0] = "XblResource" ; argv[i] = pc ; while ( *s==' ' || *s=='\t' ) s++ ; do { switch( *s ) { case '\t' : case ' ' : if ( bet==1 ) { *pc++ = *s ; break ; } case '\0' : while ( *s==' ' || *s=='\t' ) s++ ; if ( *s!='\0' ) s-- ; *pc++ = '\0' ; argv[++i] = pc ; if ( i>=NB_MAX_ARGS ) { fprintf(stderr,"Too many args\n") ; exit(1) ; } break ; case '\\' : if ( isdigit(s[1]) ) { s++ ; num = *s-'0' ; if ( isdigit(s[1]) ) { s++ ; num = num*8+*s-'0' ; if ( isdigit(s[1]) ) { s++ ; num = num*8+*s-'0' ; } } *pc++ = num ; break ; } if ( s[1]=='n' ) { s++ ; *pc++ = '\n' ; break ; } if ( s[1]=='t' ) { s++ ; *pc++ = '\t' ; break ; } if ( s[1]=='b' ) { s++ ; *pc++ = '\b' ; break ; } *pc++ = s[1] ; if ( s[1]!='\0' ) s++ ; break ; case '"' : bet = 1-bet ; break ; default : *pc++ = *s ; break ; } } while( *s++ ) ; /* printf("i=%d\n",i) ; for(bet=0;bet ",argv[bet]) ; printf("i=%d\n",i) ; */ prendoptions( o,&i,argv ) ; free( (void*)b ) ; }