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