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