]> Creatis software - gdcm.git/blob - src/gdcmArgMgr.cxx
ENH: Some more const correctness...until I hit strtok
[gdcm.git] / src / gdcmArgMgr.cxx
1 /*=========================================================================
2   
3   Program:   gdcm
4   Module:    $RCSfile: gdcmArgMgr.cxx,v $
5   Language:  C++
6   Date:      $Date: 2006/01/26 16:01:04 $
7   Version:   $Revision: 1.18 $
8   
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
12   
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16   
17 =========================================================================*/
18
19 #include <stdio.h>
20 #include <iostream>
21 #include <ctype.h>
22 #include <string.h>  // For strlen
23
24 #include <string.h>  // For strtok and strlen
25 #include <stdlib.h>  // For strtol and strtod
26
27 #include "gdcmArgMgr.h"
28
29 namespace gdcm 
30 {
31 //-------------------------------------------------------------------------
32 // Constructor / Destructor
33
34 /**
35  * \brief   constructor
36  * @param argc arguments count, as passed to main()
37  * @param argv  pointers array on the arguments passed to main()  
38  */
39  ArgMgr::ArgMgr(int argc, char **argv)
40  {
41    int i;
42    int nblettre;
43    ArgUsed = NULL;
44    Appel   = NULL;
45   
46    /* Read the parameters of the command line *************************/
47    for ( ArgCount=0, nblettre=1 , i=0; i<argc; i++) 
48    {
49       if ( FiltreLong(argv[i]) ) 
50       { 
51           std::cout << "Argument too long ( > "
52                     << ARG_LONG_MAX << ")" << std::endl;
53           return;
54       }
55       if ( argv[i][0] == '@' )
56       {                       
57          nblettre  += ArgLoadFromFile ( &argv[i][1] );   
58       }
59       else
60       {                                         
61          ArgLab [ArgCount] = strcpy ( (char *)malloc(strlen(argv[i])+1), argv[i] ) ;
62          nblettre  += 1 + strlen(ArgLab[ArgCount]);     
63          ArgCount++;                               
64       }
65       if (ArgCount >= ARGMAXCOUNT )      
66       {
67           std::cout << "Too many Arguments ( more than "
68                     << ARGMAXCOUNT << ")" << std::endl; 
69           return;
70       }
71    }
72
73    /* Fills an array with the already used parameters ****/
74    ArgUsed = (char *)calloc (1, ArgCount );
75
76    /* Builds the full string with all the parameters  **************/
77    Appel = (char *) calloc (1, nblettre );
78
79    for ( *Appel = '\0', i=0; i<ArgCount; i++)
80    {
81       strcat ( Appel, ArgLab [i] ) ;
82       strcat ( Appel, " " ) ;
83    }
84
85    /* Splitting label from label value *************************************/
86    for ( i=0; i<ArgCount; i++) 
87    {
88       char * egaloufin = ArgLab[i] ;
89       while ( (*egaloufin != '\0') && (*egaloufin != '=') ) 
90          egaloufin ++ ;
91       if ( *egaloufin ) *(egaloufin++) = '\0';
92       ArgStr[i]= egaloufin;
93    }
94
95    /* Set labels to upper-case (labels are not case sensitive ) *********/
96    for ( i=0; i<ArgCount; i++)
97       ArgLab[i] = Majuscule ( ArgLab[i] ) ;
98
99   /* Standard arguments are managed by ArgStdArgs **********************/
100    ArgStdArgs(); 
101  }
102
103 /**
104  * \brief  canonical destructor
105  */
106 ArgMgr::~ArgMgr()
107 {
108    for(int i=0;i<ArgCount;i++)
109       if ( ArgLab[i] )
110          free(ArgLab[i]);
111    if ( ArgUsed )
112       free(ArgUsed);
113    if ( Appel )
114       free(Appel);
115 }
116  
117 /**
118  * \brief  checks if a parameter exists in the command line
119  * @param param  label name
120  * @return   0 if label is not found
121  *           else, returns the number of the spot it was found last time.
122  */
123 int ArgMgr::ArgMgrDefined( const char *param )
124 {
125   int i;
126   bool trouve;
127   char *temp;
128   temp = Majuscule ( param ) ;
129   for ( i = ArgCount-1; i>0; i-- )
130   { 
131     trouve = ( strcmp( ArgLab[i], temp )==0 ) ;
132     if ( trouve )
133     {
134       ArgUsed[i] = true ;           
135       for ( int j=1; j<i; j++)
136       {                     
137          if ( (!ArgUsed[j])&&(!strcmp(ArgLab[i],ArgLab[j])) )
138             ArgUsed[j] = i ;
139       }
140       return i ;
141     }
142   }
143   return 0 ;
144 }
145
146 /**
147  * \brief  Gets the parameter value, read on the command line
148  * @param param   name of the searched parameter label
149  * @return   Value, as a char array, of the parameter
150  *            whose label is given.
151  */
152 char *ArgMgr::ArgMgrValue ( const char *param )
153 {
154    int trouve ;
155    if ( (trouve = ArgMgrDefined ( param )) != false )
156       return ArgStr[trouve] ;
157    else
158       return NULL ;
159 }
160
161 /**
162  * \brief  Search for the first not yet used label
163  * @return Pointer to the char array holding the first non used label
164  */
165 const char *ArgMgr::ArgMgrUnused ( )
166 {
167    int i ;
168    for ( i=ArgCount-1; i>0; i-- )
169    {
170       if ( ! ArgUsed[i] )
171       {
172          ArgMgrDefined(ArgLab[i]);
173          return ArgLab[i] ;
174       }
175   }
176   return NULL ;
177 }
178
179 /**
180  * \brief  Prints unused labels, if any
181  * @return number of unused labels
182  */
183 int ArgMgr::ArgMgrPrintUnusedLabels ()
184 {
185    const char *label;
186    int i=0;
187    while ( (label=ArgMgrUnused())!=0 )
188    {
189       if (i==0)
190          std::cout << "\n Unused Labels:" << std::endl
191                    << "=============="    << std::endl;
192       std::cout << "Label : " << label << " = " 
193                 << ArgMgrValue(label) << std::endl;
194       i++;
195    }
196    return i;
197 }
198
199 /**
200  * \brief  Prints program usage
201  * @param usage  array of pointers to the documentation lines of the program.
202  * @return exception code
203  */
204 int ArgMgr::ArgMgrUsage(const char **usage )
205 {
206    while ( *usage ) 
207       std::cout << std::endl << *(usage++);
208    std::cout << std::endl; 
209    return (0);
210 }
211
212 /**
213  * \brief Forget it, right now ... 
214  * Saves a char. array in a parameter file
215  *         whose name is given on command line by : PARAMOUT=???
216  *         or, as a default, by ARG_DEFAULT_PARAMOUT
217  * @param param  char. array that defines the parameter
218  * @return   Entier correspondant au rang dans la liste de labels
219  */
220 int ArgMgr::ArgMgrSave ( const char *param )
221 {
222    static int   deja = 0;
223    FILE         *fd;
224    if ( *ArgParamOut == '\0' )
225       return 0;
226    if ( deja ) 
227    {
228       fd = fopen ( ArgParamOut, "a+" );
229    }
230    else
231    {
232       deja = 1;
233       fd = fopen ( ArgParamOut, "w" );
234    } 
235    if ( !fd ) 
236       return 0;
237    fprintf ( fd, "%s\n", param );
238    fclose  ( fd );
239    return 1;
240 }
241
242 /**
243  * \brief  Gets an int value passed as an argument to a program
244  *         (use default value if not found)
245  *         EXAMPLE:     int dimx = ArgMgrGetInt ( "DIMX", 256 );
246  * @param label   label name 
247  * @param defaultVal default value
248  * @return parameter value
249  */
250 int ArgMgr::ArgMgrGetInt(const char *label, int defaultVal)
251 {
252    return ( (ArgMgrDefined(label))
253             ? (atoi(ArgMgrValue(label)))
254             : (defaultVal) );
255 }
256
257 /**
258  * \brief  Gets a float value passed as an argument to a program
259  *         (use default value if not found)
260  *         EXAMPLE:     float scale = ArgMgrGetFloat ( "SCALE", 0.33 );
261  * @param param   label name 
262  * @param defaultVal default value
263  * @return parameter value
264  */
265 float ArgMgr::ArgMgrGetFloat(const char *param, float defaultVal)
266 {
267    return     ( (ArgMgrDefined(param))
268                ? ((float)atof(ArgMgrValue(param)))
269                : (defaultVal) );
270 }
271
272 /**
273  * \brief  Gets a 'string' value passed as an argument to a program
274  *         (use default value if not found)
275  *         EXAMPLE :  char *imageName = ArgMgrGetString( "NAME", "test.dcm" );
276  * @param param   label name 
277  * @param defaultVal default value
278  * @return parameter value
279  */
280 const char *ArgMgr::ArgMgrGetString(const char *param, const char *defaultVal)
281 {
282    return    ( (ArgMgrDefined(param)) 
283               ? (ArgMgrValue(param))
284               : (defaultVal) );
285 }
286
287 /**
288  * \brief  Gets a value amongst a set of values
289  *         (use default value if not found) 
290  *         EXAMPLE:     int nlab = ArgMgrGetLabel("CONFIRM","NO\\YES", 0); 
291  * @param param   label name 
292  * @param liste  character Chain describing the various values.
293  *               Value are separated by '\\'.
294  *               Not case sensitive.
295  * @param val  number of default value
296  * @return   int : range of value amongst the values list
297  */
298 int ArgMgr::ArgMgrGetLabel (const char *param, const char *liste, int val )
299 {
300   char *lab;
301   const char *vallab;
302   int i = 1;
303   char *tmp;
304   tmp = (char *) malloc(strlen(liste)+1);
305   strcpy(tmp,liste);
306
307   if ( (vallab = ArgMgrGetString(param,(const char *)NULL)) != 0 ) 
308   { 
309      for ( lab = strtok (tmp,"\\"); 
310            lab != 0; 
311            lab = strtok(0L,"\\"), i++ )
312      { 
313         // strcmp ignoring case
314         if( strcasecmp(lab, vallab) == 0)
315            return i;
316      } 
317      val=0;
318    }
319    free(tmp);
320    return val;
321 }
322
323 /**
324  * \brief  Demands a value amongst a set of values (abort if not found)
325  *         EXaMPLE:     int nlab = ArgMgrWantLabel("CONFIRM","NO\\YES", usage); 
326  * @param param   label name 
327  * @param liste  character Chain describing the various values.
328  *               Labels are separated by  '\\'.
329  *               No case sensitive.
330  *               WARNING this will be changed (not const)
331  * @param usage Usage program (displayed if label not found)
332  * @return   int : range of value amongst the values list
333  */
334 int ArgMgr::ArgMgrWantLabel (const char *param, char *liste, const char **usage )
335 {
336    char *lab;
337    const char *vallab;
338    int i = 1;
339    if ( (vallab = ArgMgrGetString(param,0)) != 0 ) 
340    {
341       for ( lab = strtok (liste,"\\"); lab != 0; lab = strtok(0L,"\\"), i++ )
342         if ( strcasecmp(lab,vallab)==0) 
343            return i;
344       return 0;
345    }
346    ArgMgrUsage(usage);
347    return 0;
348 }
349
350 /**
351  * \brief  Demands an int value passed as an argument to a program
352  *         If not found usage is displayed and the prog aborted
353  *  EXAMPLE:     int dimx = ArgMgrWantInt ( "DIMX", usage );
354  * @param label   label name 
355  * @param usage Usage program (displayed if label not found)
356  * @return parameter value
357  */
358 int ArgMgr::ArgMgrWantInt (const char *label, const char **usage)
359 {
360    return        ( (ArgMgrDefined(label) ) 
361                  ? (atoi(ArgMgrValue(label) ) ) 
362                  : (ArgMgrUsage(usage),1) );
363 }
364
365 /**
366  * \brief  Demands a float value passed as an argument to a program
367  *         If not found usage is displayed and the prog aborted
368  *  EXAMPLE:     float scale = ArgMgrWantFloat ( "SCALE", usage );
369  * @param label   label name 
370  * @param usage Usage program (displayed if label not found)
371  * @return parameter value
372  */
373 float ArgMgr::ArgMgrWantFloat (const char *label, const char **usage)
374 {
375    return       ( (ArgMgrDefined(label) ) 
376                 ? ((float)atof(ArgMgrValue(label) ) ) 
377                 : (ArgMgrUsage(usage),(float)1.0) );
378 }
379
380 /**
381  * \brief  Demands a 'string' value passed as an argument to a program
382  *         If not found usage is displayed and the prog aborted
383  *  EXAMPLE:     char *code = ArgMgrWantString ( "CODE", usage );
384  * @param label   Parameter label
385  * @param usage Usage program (displayed if label not found)
386  * @return parameter value
387  */
388 char *ArgMgr::ArgMgrWantString(const char *label, const char **usage)
389 {
390    return      ( (ArgMgrDefined(label) ) 
391                ? (ArgMgrValue(label) ) 
392                : (ArgMgrUsage(usage),(char*)0) );
393 }
394
395 /**
396  * \brief  decodes and returns an array of 'STRING'
397  *  EXAMPLE:     char **codes = ArgMgrGetListOfString ( "CODES", &nbOfCodes ); 
398  * @param label   label name 
399  * @param number  nb of found 'STRINGs'
400  * @return   Pointer to the 'STRING' array; NULL if error
401  */
402 char **ArgMgr::ArgMgrGetListOfString ( const char *label, int *number )
403 {
404   int taille;
405   char  *value = ArgMgrValue(label);
406   char **liste;
407   char **elem;
408   char  *chainecur; 
409   if (!value)
410   {
411      *number = 0;
412      return 0;
413   }
414   *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
415   taille = *number;
416   liste = (char **) malloc (sizeof(char*) * taille + strlen(value)+1);
417   if ( !liste )
418      return 0;
419   value = strcpy( ((char*)liste)+sizeof(char*) * taille, value );
420   for ( elem = liste, chainecur = strtok(value,", ");
421         taille>0;
422         taille--, chainecur = (chainecur) ? strtok ( 0, ", " ) : 0 )
423   {
424     *(elem++) = chainecur;
425   }
426   return liste;
427 }
428
429 /**
430  * \brief  decodes and returns an array of 'INT'
431  *  EXAMPLE:     int *points = ArgMgrGetListOfInt ( "POINTS", &nbOfPoints );  
432  * @param label   label name 
433  * @param number  nb of found INT
434  * @return   Pointer to the INT array; NULL if error
435  */
436 int *ArgMgr::ArgMgrGetListOfInt ( const char *label, int *number )
437 {
438   char *value = ArgMgrValue(label);
439   int *liste;
440   int *elem;
441   int taille;
442   if (!value)
443   {
444      *number = 0;
445      return 0;
446   }          
447   *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */ 
448   taille= *number;
449   liste = (int *) calloc (1,sizeof(int)*taille );
450   if ( !liste )
451      return 0;
452   elem = liste;
453   //*number = 1;
454
455   while ( taille>0 ) 
456   {
457     *(elem++) = (int) strtol ( value, &value, 10 );      
458     if ( *value == '\0' )
459        return liste;
460     if ( *(value++) != ',' ) 
461     {
462       free (liste);
463       return 0;
464     }
465     taille --;
466   }
467 return liste;
468 }
469
470 /**
471  * \brief  decodes and returns an array of 'FLOAT'
472  * @param label   label name 
473  * @param number  number of found FLOATs
474  * @return   Pointer to the FLOAT array; NULL if error
475  */
476 float *ArgMgr::ArgMgrGetListOfFloat ( const char *label, int *number )
477 {
478   char *value = ArgMgrValue(label);
479   float *liste;
480   float *elem;
481   int taille;
482   if (!value)
483     return 0;
484   *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
485   taille= *number;
486   liste = (float *) calloc (1,sizeof(float)*taille );
487   if ( !liste )
488   {
489      *number = 0;
490      return 0;
491   }
492   elem = liste;
493   //*number = 1;
494
495   while ( taille>0 ) 
496   {
497     *(elem++) = (float) strtod ( value, &value );      
498     if ( *value == '\0' )
499        return liste;
500     if ( *(value++) != ',' )
501     {
502       free (liste);
503       return 0;
504     }
505     taille --;
506   }
507 return liste;
508 }
509
510 /**
511  * \brief  decodes and returns an array of 'INT pairs', passed in decimal
512  * @param param   label name 
513  * @param number   nb of found pairs
514  * @return        pointer to the array of 'INT pairs'; NULL if fail
515  */
516 int *ArgMgr::ArgMgrGetIntEnum ( const char *param, int *number )
517 {
518    char *value = ArgMgrValue(param);
519    int *liste;
520    if (!value) 
521    {
522       *number = 0; 
523       return 0;
524    }
525    liste = IdStrIntEnum(value, number);
526    return liste;
527 }
528
529 /**
530  * \brief  decodes and returns an array of 'INT16 pairs', passed in hexadecimal
531  * @param param   label name 
532  * @param number   nb of found pairs
533  * @return        pointer to the array of 'INT16 pairs'; NULL if fail
534  */
535 uint16_t *ArgMgr::ArgMgrGetXInt16Enum ( const char *param, int *number )
536 {
537    char *value = ArgMgrValue(param);
538    uint16_t *liste;
539    if (!value) 
540    {
541       *number = 0; 
542       return 0;
543    }
544    liste = IdStrXInt16Enum(value, number);
545    return liste;
546 }
547 /**
548  * \brief  decodes and returns an array of 'FLOAT pairs'
549  * @param param   label name 
550  * @param number   nb of found pairs
551  * @return        pointer to the array of 'FLOAT pairs'; NULL if fail
552
553  */
554 float *ArgMgr::ArgMgrGetFloatEnum ( const char *param, int *number )
555 {
556    char  *value = ArgMgrValue(param);
557    float *liste;
558    if (!value) 
559    {
560       *number = 0; 
561       return 0;
562    }
563    liste = IdStrFloatEnum(value, number);
564    return liste;
565 }
566
567 // ------------------------ Those are 'service functions' ---------------------
568 // ------------------------       internal use only       ---------------------
569
570 /**
571  * \brief     Counts the nb of occurrences of a given charact within a 'string' 
572  * @param chaine     Pointer to the 'string'
573  * @param caract     charact to count
574  * @return       occurence number
575  */
576 int ArgMgr::IdStrCountChar (char *chaine, int caract)
577 {
578   int i=0;
579   char *ptr;
580   for ( ptr = chaine ; *ptr!='\0' ; ptr ++ ) 
581      if (*ptr==caract) 
582         i++;  
583   return i;
584 }
585
586 /**
587  * \brief     returns an array of 'INT pairs'
588  * @param value  char array decribing a set of 'INT pairs' (f1-l1, f2-l2, ...)
589  * @param number nb of found INT pairs
590  * @return       pointer to the array of 'INT pairs'
591  */
592 int *ArgMgr::IdStrIntEnum ( char* value, int *number)
593 {
594    int* liste;
595    int taille;
596    int i;
597
598    *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
599    taille= *number;
600    liste = (int *) calloc (1,sizeof(int)*2*taille );
601    if ( !liste )
602    {
603       return 0;
604    }
605    i=0;
606    while ( taille>0 ) 
607    {
608       liste[i] = (int) strtol ( value, &value, 10 );
609       if ( *value == '\0' ) 
610       {
611          liste[i+1]=liste[i];
612          return liste;
613       }
614       if ( *(value++) != '-' ) 
615       {
616          liste[i+1]=liste[i];
617          value--;
618        }
619        else
620        {
621           liste[i+1] = (int) strtol ( value, &value, 10 );
622        }
623        if ( *value == '\0' )
624           return liste;
625        if ( *(value++) != ',' )
626        {
627           free (liste);
628           return 0;
629        }
630        taille --; i+=2;
631    }
632    return liste;
633 }
634
635 /**
636  * \brief     returns an array of set of 'INT16 pairs', passed in Hexadecimal
637  * @param value  char array decribing a set of 'INT16 pairs' (f1-l1, f2-l2, ...)
638  *               coded in hexadecimal e.g. 0x0008,0x00ac
639  * @param number nb of found pairs
640  * @return        array of set of 'INT16 pairs'
641  */
642 uint16_t *ArgMgr::IdStrXInt16Enum ( char *value, int *number)
643 {
644    uint16_t *liste;
645    int taille;
646    int i;
647
648    *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
649    taille= *number;
650    liste = (uint16_t *) calloc (1,sizeof(uint16_t)*2*taille );
651    if ( !liste )
652    {
653       return 0;
654    }
655    i=0;
656    while ( taille>0 ) 
657    {
658       liste[i] = (uint16_t) strtol ( value, &value, 16 );
659       if ( *value == '\0' ) 
660       {
661          liste[i+1]=liste[i];
662          return liste;
663       }
664       if ( *(value++) != '-' ) 
665       {
666          liste[i+1]=liste[i];
667          value--;
668        }
669        else
670        {
671           liste[i+1] = (uint16_t) strtol ( value, &value, 16 );
672        }
673        if ( *value == '\0' )
674           return liste;
675        if ( *(value++) != ',' )
676        {
677           free (liste);
678           return 0;
679        }
680        taille --; i+=2;
681    }
682    return liste;
683
684 /**
685  * \brief     returns an array of 'FLOAT pairs'
686  * @param value  char array decribing a set of 'FLOAT pairs' (f1-l1, f2-l2, ...)
687  * @param number nb of found pairs
688  * @return       pointer to the array of 'FLOAT pairs'; NULL if fail
689  */
690 float *ArgMgr::IdStrFloatEnum (char *value, int *number)
691 {
692    float *liste;
693    int taille;
694    int i;
695    *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
696    taille= *number;
697    liste = (float *) calloc (1,sizeof(float)*2*taille );
698    if ( !liste )
699       return 0;
700    i=0;
701    while ( taille>0 ) 
702    {
703       liste[i] = (float) strtod ( value, &value );      
704       if ( *value == '\0' ) 
705       {
706          liste[i+1]=liste[i];
707          return liste;
708       }
709       if ( *(value++) != '-' ) 
710       {
711          liste[i+1]=liste[i];
712          value--;
713       }
714       else
715       {
716           liste[i+1] = (float) strtod ( value, &value );
717       }
718       if ( *value == '\0' ) 
719          return liste;
720       if ( *(value++) != ',' )
721       {
722          free (liste);
723          return 0;
724       }
725       taille --; i+=2;
726    }
727    return liste;
728 }
729
730 //-----------------------------------------------------------------------------
731 // Protected
732
733 //-----------------------------------------------------------------------------
734 // Private
735
736 /**************************************************************************
737 *                                                                         *
738 * Nom de la fonction : Majuscule                                          *
739 * Role ............. : Creates a new Upper case char array.               *
740 * parameters ....... : Pointer to the initial char array.                 *                           *
741 * Valeur retournee . : Pointer to the new Upper case char array.          *
742 *                                                                         *
743 **************************************************************************/
744 char *ArgMgr::Majuscule (const char *chaine )
745 {
746   char *ptr, *ptr2, *ptr3;
747   ptr2 = (char *)malloc(strlen(chaine)*sizeof(char)+1);
748   ptr3=ptr2;
749   for ( ptr = (char *)chaine ; *ptr!='\0' ; ptr ++ ) 
750    {  
751        *ptr3 = toupper ( * ptr ); ptr3++; 
752    }
753   *ptr3='\0'; 
754   return ptr2;
755 }
756
757 /**************************************************************************
758 *                                                                         *
759 * Nom de la fonction : FiltreLong                                         *
760 * Role ............. : Stops the program if argument is too long.         *
761 *                      ARG_LONG_MAX defines max length.                   *
762 * parameters ....... : Pointer to the argument.                           *
763 * Valeur retournee . : false if OK.                                       *
764 *                      true if KO.                                        *
765 **************************************************************************/
766 int ArgMgr::FiltreLong ( const char *arg  )
767 {
768   int  n = 0 ;
769   while ( (n++<ARG_LONG_MAX) && (*(arg++) != '\0') ) ;
770   return (n>=ARG_LONG_MAX) ;
771 }
772
773 /*------------------------------------------------------------------------
774  | Role       : Reads a parameter from a file
775  | Return     : Type   : char *
776  |              Role   : pointer to the label
777  | parameters : param  : char *
778  |              Role   : one where the parameter will be stored
779  |              fd     : FILE *
780  |              Role   : File description (assumed to be open)
781  +------------------------------------------------------------------------*/
782 const char *ArgMgr::LoadedParam ( const char *param, FILE *fd )
783 {
784   int    carlu;
785   char  *car = (char *)param;
786   int    quote = false;
787   int    nbcar = 0;
788
789   /* remove spaces at the beginning****/
790   while ( isspace(carlu=fgetc (fd)) );
791   if (carlu==EOF)
792      return 0;
793   /* Search for a " */
794   if ( carlu=='\"' ) 
795   {
796     carlu=fgetc(fd);
797     quote=true;
798   /* Read all the characters */
799   }
800   while (  (carlu!=EOF)
801         && (  ( (!quote)&&(!isspace(carlu)) )
802          ||( (quote)&& !(carlu=='\"')   ) ) ) 
803   {
804      *(car++) = (char) carlu;
805      nbcar ++;
806   /* sans depasser la taille max*/
807      if ( nbcar >= ARG_LONG_MAX ) 
808      {
809         std::cout << "\nError: Argument too long ( > "
810                   << ARG_LONG_MAX << ")in parameter file."
811                   << std::endl;
812         break;
813      }
814      carlu = fgetc(fd);
815   }
816   *car = '\0';
817   return param;
818 }
819
820 /*------------------------------------------------------------------------
821  | Role       : Reading of arguments in a parameter file
822  |              (this function is recursive).
823  | Return     : Type   : int
824  |              Role   : length needed to store all the parameters
825  | parameters : filename : char *
826  |              Role     : parameter File name
827  |
828  +------------------------------------------------------------------------*/
829 int ArgMgr::ArgLoadFromFile ( const char *filename )
830 {
831   int   nbl = 0;
832   char  param[ARG_LONG_MAX+1];
833   FILE  *fch;
834
835   fch = fopen ( filename, ID_RFILE_TEXT );
836   while ( LoadedParam (param, fch ) )
837   {
838     int n = strlen(param);
839     if ( param[0]=='@' )
840     {
841       nbl  += ArgLoadFromFile ( &param[1] );
842     }
843     else
844     {
845       ArgLab [ArgCount] = strcpy ((char *) malloc(n+1), param ) ;
846       nbl += n + 1 ;
847       ArgCount++;
848       if ( ArgCount >= ARGMAXCOUNT ) 
849          break;
850     }
851   }
852   fclose ( fch );
853   return nbl;
854 }
855
856 /*------------------------------------------------------------------------
857  | Role       : Standard parameters management (on command line)
858  | Return     : Type   : void
859  | parameters : none
860  +------------------------------------------------------------------------*/
861 void ArgMgr::ArgStdArgs()
862 {
863   char *logfile;
864   FILE *fd;
865
866   if ( (ArgParamOut=ArgMgrValue((char*)ARG_LABEL_PARAMOUT))==0 )
867     ArgParamOut = ARG_DEFAULT_PARAMOUT;
868   if ( (logfile = ArgMgrValue((char*)ARG_LABEL_LOGFILE))!=0) 
869   {
870     if ( *logfile == '\0' )
871        logfile = (char *)ARG_DEFAULT_LOGFILE;
872     fd = fopen ( logfile, "a+" );
873     if ( fd ) 
874     {
875       fprintf ( fd, "%s\n", Appel );
876       fclose  ( fd );
877     }
878   }
879 }
880
881 /*------------------------------------------------------------------------
882  | Role       : Sets in Upper Case.
883  | Return     : Type   : char *
884  | parameters : char *
885  +------------------------------------------------------------------------*/
886 char *ArgMgr::maj ( char *a )
887 {
888    char *b = a;
889    while ( *b !=0 ) 
890    {
891       if ( *b<='z' && *b>='a' ) *b = *b+'A'-'a';
892       b++;
893    }
894    return a;
895 }
896 //-----------------------------------------------------------------------------
897 // Print
898
899 //-----------------------------------------------------------------------------
900 } // end namespace gdcm