/*
COMGETOPT.C
Analyse et interprétation des options de la ligne de commande.
Possible types of options:
Single char (GETOPT_CHAR)
One *or more* text strings (GETOPT_TEXTE)
One *or more* 32-bit integers (GETOPT_INT32)
Toggle (32-bit integer), (GETOPT_INT32TOGL)
possibly followed by another value, text, double or int.
(for parameter couples: one YES/NO + one additional value if YES)
Separator (GETOPT_SEPARATEUR, for help display)
Any different option names admitted, no confusion if one name
includes another. (This features makes use of abbreviations
impossible)
Option explanations automatically formatted ;
no rightmost zeroes after a decimal point ;
correct plurals
Functions:
Options display with pause after each screenful,
whatever the screen height. Also works under Windoze.
Thorough argument presence, error and type checking, with choice to
continue or not in case of error.
File redirection (option @)
Special maintenance options :
@? checks for duplicates.
@* outputs all options and their values in a form suitable for re-reading.
Possibility to ask if a variable was mentioned in the command line,
by name or by address (function com_go_option_was_used_p).
Saving, restoring and resetting options'values, with possibility to
output/save only the diff. useful when very many options.
Example of definition :
struct _getopt_option sx_gbp_options[] = {
{ "", GETOPT_SEPARATEUR, NULL, sxopt_sep_rpg },
{ "+", GETOPT_INT32TOGL, (void *) &autosave_best_p, sxopt_plus, 1 },
{ "R", GETOPT_INT32TOGL, (void *) &v1, sxopt_r,
GETOPT_TEXTE, (void *) v_path, 1 },
// if options /r is used, v1 will be set to 1 and
what follows /r will be copied to v_path.
{ "P", GETOPT_INT32, (void *) array_of_five_int32s, sxopt_p, 5 },
{ "B", GETOPT_DOUBLE, (void *) &beta_start_coef, sxopt_b },
{ "MS", GETOPT_INT32TOGL, (void *) &update_thresholds_p, sxopt_j, 1 },
{ "", GETOPT_SEPARATEUR, NULL, sxopt_sep_rpga },
{ "T", GETOPT_DOUBLE, (void *) &size_factor, sxopt_t },
{ "BP", GETOPT_INT32, (void *) &nb_passes_backprp, sxopt_BP, 1 },
} ;
The sxopt_xxx strings are what you see when typing "myprog ?"
Example of use :
MYPROG /k /path"c:\my progs" /N2,4,2 /tryontest1.dat&test2.dat
Options are /k, /path, /n and /tryon, resp of types GETOPT_INT32TOGL,
GETOPT_TEXTE (1 value), GETOPT_INT32 (array of 3), etc.
For arrays of values, numbers may be separated by any nondigit,
text strings need to be separated by ',' or '&' (the console eats commas)
*/
#define xSHOW_WAS_USED
#define xSHOW_LIRE_REDIR
#define xSHOW_SAVE_OPTIONS
#define xSHOW_OUTPUT_OPTIONS
#define xSHOW_OUTPUT_OPTIONS2
#include <conio.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "common.h"
#include "comgetop.h"
#ifdef TARGET_DOS
#include <graph.h>
#endif
/* Internals, not declared in getopt.h */
void com_complete_a_largeur_opt ( char *bufg, char *bufd, char *dest, int largeur ) ;
void com_complete_a_largeur_sep ( char *bufg, char *dest, int largeur ) ;
int get_text_ext_system_Win ( char *text ) ;
void com_go_show_sorted_options ( struct _getopt_option *opts, int nbo );
int sort_name_alpha ( void const *e1, void const *e2);
int sort_opt_by_length ( void const *e1,void const *e2);
int sort_opt_by_name ( void const *e1,void const *e2);
int sort_opt_by_original_order ( void const *e1,void const *e2);
int com_go_verify_options ( struct _getopt_option *opts, int nbo ) ;
int com_getopt_display_error_msg ( struct _getopt_option *opts, int nbo, char *usage ) ;
#ifdef FRANCAIS
static char
#ifdef TARGET_DOS
com_getopt_str_Esc_or_key[] = "Appuyez sur <Escape> pour finir, ou sur une autre touche pour continuer
",
com_getopt_str_imprime_DOS[] = "Pour imprimer cette liste d'options, tapez \"%s ? > PRN\" dans une console.",
#endif
com_getopt_str_press_space_DOS2[] = "Voulez-vous voir les Options ?\n"
"Non continue en ignorant l'erreur, <Escape> termine l'exécution.",
com_getopt_str_no_other_option[] = "Aucune autre option pour ce logiciel.",
com_getopt_str_no_option[] = "Aucune option pour ce logiciel.",
com_go_error_no_val_char[] = "Il faut indiquer une valeur après l'option \"/%s\" (Err%d).\n",
com_go_error_wrong_val_toggle[] = ": Les seules valeurs admises après l'option bascule \"/%s\" sont 0(Non) ou 1(Oui).\n",
com_go_error_no_val_int32[] = ": Il faut indiquer un nombre (entier) après l'option \"/%s\", sans espace.\n",
com_go_error_no_val_text[] = "Il faut indiquer un texte après l'option \"/%s\", sans espace.\n",
com_go_error_no_val_double[] = ": Il faut indiquer un nombre (avec ou sans point décimal)\n\taprès l'option \"/%s\", sans espace.\n",
com_go_error_nbv_vaut_zero[] = "Option \"/%s\": nbv_or_type2 est nul ?!\n",
com_go_error_in_enum[] = "Option \"/%s\": erreur dans l'énumération \"%s\": '%c'.\n",
com_go_error_unknown_option[] = "Option inconnue: \"%s\".\n",
com_go_error_opt_file[] = "Option @%s: ligne N°%d, col %d, \"%s\" ignorée. \n\tMettez tout sur une seule ligne.\n",
com_go_error_cant_find_opt_file[] = "Option @: fichier \"%s\" introuvable.\n",
com_getopt_str_options_de[] = "\n\nOptions de %s:",
com_getopt_str_valeurs_act[] = "[valeurs actuelles]",
com_getopt_str_toggle_on[] = "OUI",
com_getopt_str_toggle_off[] = "NON",
com_getopt_str_nb_errors[] = "%d erreur%s dans les options."
;
#endif
#ifdef ANGLAIS
char
#ifdef TARGET_DOS
com_getopt_str_Esc_or_key[] = "Hit <Escape> to end, or any other key to continue
",
com_getopt_str_imprime_DOS[] = "To print this option list, type \"%s ? > PRN\" in a console.",
#endif
com_getopt_str_press_space_DOS2[] = "Do you want to see the Options ?\n"
"No : ignore the error, <Escape> ends.",
com_getopt_str_no_other_option[] = "No other options available for this software.",
com_getopt_str_no_option[] = "No options available for this software.",
com_go_error_no_val_char[] = "A value must be given after option \"/%s\" (Err%d).\n",
com_go_error_wrong_val_toggle[] = ": The only allowed values after option \"/%s\" are 0 (No) or 1 (Yes).\n",
com_go_error_no_val_int32[] = ": An integer value must be given right after option \"/%s\".\n",
com_go_error_no_val_text[] = "A text value must be given right after option \"/%s\".\n",
com_go_error_no_val_double[] = ": A number (with or without point) must be given right after option \"/%s\".\n",
com_go_error_nbv_vaut_zero[] = "Option %s: nbv_or_type2 is 0 ?!\n",
com_go_error_in_enum[] = "Error in enumeration \"%s\": '%c'.\n",
com_go_error_unknown_option[] = "Unrecognized option: \"%s\".\n",
com_go_error_opt_file[] = "Option @%s: line #%d, col %d, \"%s\" ignored. \n\tWrite everything on an unbroken line.\n",
com_go_error_cant_find_opt_file[] = "Option @: cannot find file \"%s\".\n",
com_getopt_str_options_de[] = "\n\nOptions of %s:",
com_getopt_str_valeurs_act[] = "[default values]",
com_getopt_str_toggle_on[] = "ON",
com_getopt_str_toggle_off[] = "OFF",
com_getopt_str_nb_errors[] = "%d error%s in the options."
;
#endif
#define NB_MAX_ERR 8
static char com_getopt_error_msg[NB_MAX_ERR*90] = "" ;
static char *pmsg = com_getopt_error_msg ;
static int nb_erreurs = 0 ;
static char *exec_name ;
struct com_options com_options = { 0, "", NULL, 0, NULL, 0, NULL, 0 } ;
/* com_go_getopt ****************************************************** */
int com_go_getopt ( char *usage, unsigned int options ) {
/* Entry point - interprets args according to opts */
/* Returns GETOPT_OK: OK, GETOPT_ERROR: erreurs, GETOPT_INFO: help,exit */
/* May be called many times, put NULL & 0 in argc and old_argv */
int i, new_i, j, ok_p, k, l, nbo, first_char, second_char, ignore_p = 0 ;
char *p, *start_valeur_arg, *start_nom_arg, buf_nom_option[40] ;
char *oldp, *p2, **doublep ;
struct _getopt_option *opts ;
com_options.new_argc = 0 ;
com_options.help = usage ;
opts = com_options.options ;
nbo = com_options.nb_options ;
/* module-wide reference to the option struct */
/* ] must use com_go_add_options to fill this */
nb_erreurs = com_go_verify_options ( opts, nbo ) ;
if ( nb_erreurs )
return com_getopt_display_error_msg ( opts, nbo, usage ) ;
/*
if ( com_options.orig_argc > GETOPT_NB_MAX_IN_ARGV ) {
pmsg += sprintf ( pmsg, "GETOPT: Too many (%d) options.", com_options.orig_argc ) ;
++nb_erreurs ;
com_getopt_display_error_msg ( opts, nbo, usage ) ;
exit ( EXIT_FAILURE ) ;
} ;
*/
memset ( com_options.new_argv, 0, sizeof ( com_options.new_argv ) ) ;
com_options.new_argv[0] = strdup ( com_options.orig_argv[0] ) ;
exec_name = com_options.new_argv[0] ;
j = 0 ;
#ifdef SHOW_LIRE_REDIR
fprintf ( stderr, "Entrée dans com_go_getopt : exec_name = \"%s\", com_options.orig_argc = %d.\n",
exec_name, com_options.orig_argc ) ;
#endif
for ( i = new_i = 1 ; i < com_options.orig_argc ; ++i, ++new_i ) {
/* le num. 0 contient le path !! */
first_char = com_options.orig_argv[i][0] ;
second_char = com_options.orig_argv[i][1] ;
com_options.new_argv[new_i] = strdup ( com_options.orig_argv[i] ) ;
#ifdef SHOW_LIRE_REDIR
fprintf ( stderr, "Ajouté argument \"%s\", pris en pos. %d, au rang %d.\n",
com_options.new_argv[new_i], i, new_i ) ;
#endif
l = strlen ( com_options.orig_argv[i] ) ;
if ( first_char == '@' && second_char == '*' && (l == 2) ) {
/* option @* maintenance: output options to file */
com_go_output_options ( NULL, 0, 0 ) ;
#ifndef NO_UI
com_message ( "GetOpt", com_big_buffer ) ;
#endif
return GETOPT_INFO ;
} ;
if ( first_char == '@' && second_char == '?' && (l == 2) ) {
/* option @? maintenance: show sorted list,
check for duplicate options */
com_go_show_sorted_options ( opts, nbo ) ;
#ifndef NO_UI
com_message ( "GetOpt", com_big_buffer ) ;
#endif
com_go_display_options ( opts, nbo, usage ) ;
return GETOPT_INFO ;
} ;
if ( (first_char == '?' && (l == 1))
|| ((first_char == '/' || first_char == '-')
&& second_char == '?' && (l == 2))
|| !stricmp ( com_options.orig_argv[i]+1, "help" )
|| !stricmp ( com_options.orig_argv[i]+1, "aide" ) ) {
/* lancement with ? or /?: see options list */
com_go_display_options ( opts, nbo, usage ) ;
return GETOPT_INFO ;
} ;
if ( first_char == '@' && second_char != '@' ) {
/* file redirection: @<filename> */
k = com_go_lire_redir ( com_options.orig_argv[i]+1, com_options.new_argv+i ) ;
if ( k == -1 ) {
com_message ( "GetOpt", com_error_message ) ;
return com_getopt_display_error_msg ( opts, nbo, usage ) ;
} ;
new_i += k-1 ;
} ;
} ;
if ( j )
return GETOPT_INFO ;
com_options.new_argc = new_i ;
#ifdef SHOW_LIRE_REDIR
fprintf ( stderr, "Fin épluchage : com_options.new_argc = %d. com_options.orig_argc = %d.\n",
com_options.new_argc, com_options.orig_argc ) ;
#endif
qsort ( opts, (size_t) nbo, sizeof ( struct _getopt_option ),
sort_opt_by_length ) ;
for ( i = 1 ; i < com_options.new_argc ; ++i ) { /* # 0 contains path !! */
#ifdef SHOW_LIRE_REDIR
fprintf ( stderr, "Vu \"%s\"\n", com_options.new_argv[i] ) ;
#endif
if ( (options & GETOPT_STOP_AT_FIRST_NONOPT)
&& com_options.new_argv[i][0] != '/' && com_options.new_argv[i][0] != '-' )
ignore_p = 1 ;
if ( com_options.new_argv[i][0] != '/' && com_options.new_argv[i][0] != '-' )
continue ;
/* Dash or slash admitted */
ok_p = 0 ;
start_nom_arg = com_options.new_argv[i] + 1 ;
/*if ( com_options.new_argv[i][0] == com_options.new_argv[i][1] )
continue ; ??? */
if ( !ignore_p ) {
for ( j = 0 ; j < nbo && !ok_p ; ++j ) {
if ( opts[j].type == GETOPT_SEPARATEUR )
/* separator, no option contained */
continue ;
strncpy ( buf_nom_option, start_nom_arg, opts[j].lg_nom ) ;
buf_nom_option[opts[j].lg_nom] = 0 ;
if ( stricmp ( buf_nom_option, opts[j].nom ) )
continue ;
start_valeur_arg = start_nom_arg + opts[j].lg_nom ;
ok_p = 1 ;
opts[j].used_p = 1 ;
switch ( opts[j].type ) {
case GETOPT_CHAR:
if ( !*start_valeur_arg ) {
pmsg += sprintf ( pmsg, com_go_error_no_val_char, opts[j].nom, 1 ) ;
++nb_erreurs ;
break ;
}
((char *)opts[j].valeur)[0] = *start_valeur_arg ;
break ;
case GETOPT_TEXTE:
if ( !*start_valeur_arg ) {
pmsg += sprintf ( pmsg, com_go_error_no_val_text, opts[j].nom ) ;
++nb_erreurs ;
break ;
}
if ( opts[j].nbv_or_type2 <= 0 ) {
pmsg += sprintf ( pmsg, com_go_error_nbv_vaut_zero, opts[j].nom ) ;
opts[j].nbv_or_type2 = 1 ;
++nb_erreurs ;
/*break ;*/
} ;
p = start_valeur_arg ;
if ( opts[j].nbv_or_type2 == 1 ) {
p = start_valeur_arg ;
l = 0 ;
if ( *p == '"' )
++p ;
l = strlen ( p ) ;
if ( p[l-1] == '"' )
p[l-1] = 0 ;
strcpy ( (char *) opts[j].valeur, p ) ;
break ;
} ;
/* sinon désosser et chercher les separateurs */
oldp = p ;
doublep = ((char **) opts[j].valeur) ;
for ( k = 0 ; k < opts[j].nbv_or_type2 ; ++k ) {
p2 = doublep[k] ;
l = 0 ;
while ( *p && (*p != ',') && (*p != '&') ) {
++p ;
++l ;
} ;
if ( *oldp == '"' ) /* chaine entre guillemets */
++oldp ;
strncpy ( p2, oldp, (size_t) l ) ;
p2[l] = 0 ;
if ( l && p2[l-1] == '"' )
p2[l-1] = 0 ;
if ( !l )
continue ;
if ( !l && !*p )
break ;
oldp = p+1 ;
++p ;
} ;
for ( ; k < opts[j].nbv_or_type2 ; ++k )
*doublep[k] = 0 ;
break ;
case GETOPT_INT32:
p = start_valeur_arg ;
if ( !*p || !isdigit(*p) ) {
pmsg += sprintf ( pmsg, "\"/%s\"", start_nom_arg ) ;
*start_valeur_arg = 0 ;
pmsg += sprintf ( pmsg, com_go_error_no_val_int32, opts[j].nom ) ;
++nb_erreurs ;
break ;
}
if ( opts[j].nbv_or_type2 < 1 )
opts[j].nbv_or_type2 = 1 ;
for ( k = l = 0 ; k < opts[j].nbv_or_type2 ; ++k ) {
((int32 *)opts[j].valeur)[k] = (int32) atol ( p ) ;
while ( isdigit ( *p ) )
++p ;
if ( !*p )
break ;
++p ; /* separateur */
if ( !*p )
break ; /* on tolere que ca se termine par un separateur */
if ( !isdigit(*p) ) {
pmsg += sprintf ( pmsg, com_go_error_in_enum, opts[j].nom, start_valeur_arg, *p ) ;
++nb_erreurs ;
break ;
} ;
} ;
break ;
case GETOPT_INT32TOGL:
p = start_valeur_arg ;
if ( !*p ) {
/* pas d'args, basculer */
*((int32 *)opts[j].valeur) = (int32)
(1 - *((int32 *)opts[j].valeur)) ;
break ;
} ;
if ( p[0] == ':' && (p[1] == '0' || p[1] == '1') ) {
/* si valeur mentionnee l'imposer */
*((int32 *)opts[j].valeur) = (int32) atol ( p+1 ) ;
break ;
} ;
/* Read second option's value(s), three types: */
switch ( opts[j].nbv_or_type2 ) {
case GETOPT_INT32:
*((int32 *)opts[j].valeur) = 1 ;
if ( !opts[j].nbv2 )
opts[j].nbv2 = 1 ;
for ( k = l = 0 ; k < opts[j].nbv2 ; ++k ) {
((int32 *)opts[j].valeur2)[k] = (int32) atol ( p ) ;
while ( isdigit ( *p ) )
++p ;
if ( !*p )
break ;
++p ; /* separateur */
if ( !*p )
break ; /* on tolere que ca se termine par un separateur */
if ( !isdigit(*p) ) {
pmsg += sprintf ( pmsg, com_go_error_in_enum, opts[j].nom, start_valeur_arg, *p ) ;
++nb_erreurs ;
break ;
} ;
} ;
break ;
case GETOPT_DOUBLE :
*((int32 *)opts[j].valeur) = 1 ;
for ( k = l = 0 ; k < opts[j].nbv2 ; ++k ) {
((double *)opts[j].valeur2)[k] = (double) atof ( p ) ;
while ( isdigit ( *p ) || *p == '.' )
++p ;
if ( !*p )
break ;
++p ; /* separateur */
if ( !*p )
break ; /* on tolere que ca se termine par un separateur */
if ( !isdigit(*p) && *p != '.' ) {
pmsg += sprintf ( pmsg, com_go_error_in_enum, opts[j].nom, start_valeur_arg, *p ) ;
++nb_erreurs ;
break ;
} ;
} ;
break ;
case GETOPT_TEXTE :
*((int32 *)opts[j].valeur) = 1 ;
strcpy ( (char *) opts[j].valeur2, start_valeur_arg ) ;
break ;
default :
pmsg += sprintf ( pmsg, com_go_error_wrong_val_toggle, opts[j].nom ) ;
++nb_erreurs ;
break ;
} ;
/*
pmsg += sprintf ( pmsg, com_go_error_no_val_char, opts[j].nom, 5 ) ;
*start_valeur_arg = 0 ;
*/
break ;
case GETOPT_DOUBLE:
p = start_valeur_arg ;
if ( !*p || (!isdigit(*p) && *p != '.' && *p != '-') ) {
*start_valeur_arg = 0 ;
pmsg += sprintf ( pmsg, com_go_error_no_val_double, opts[j].nom ) ;
++nb_erreurs ;
break ;
}
*((double *)opts[j].valeur) = (double) atof ( start_valeur_arg ) ;
break ;
default:
++nb_erreurs ;
break ;
} ;
/*com_options.new_argv[i][0] = 0 ;*/
com_options.new_argv[i] = NULL ;
break ;
} ;
if ( !ok_p ) {
pmsg += sprintf ( pmsg, com_go_error_unknown_option, com_options.new_argv[i] ) ;
++nb_erreurs ;
*com_options.new_argv[i] = 0 ;
} ;
} ;
} ;
new_i = 1 ;
for ( i = 1 ; i < com_options.new_argc ; ++i )
if ( com_options.new_argv[i] && *com_options.new_argv[i] )
new_i = i+1 ; /* dernier arg non nul */
#ifdef SHOW_LIRE_REDIR
fprintf ( stderr, "dernier arg non nul = %d.\n", new_i ) ;
#endif
for ( i = 1 ; i < new_i ; ++i ) {
/* copy remaining, uninterpreted args (maybe data file name etc.) */
/* eh non car peut être trop petit ! cas de @fichier */
if ( !com_options.new_argv[i] || !*com_options.new_argv[i] ) {
for ( j = i ; j < new_i-1 ; ++j )
com_options.new_argv[j] = com_options.new_argv[j+1] ;
com_options.new_argv[new_i-1] = NULL ;
--new_i ;
--i ;
} ;
} ;
for ( i = 1 ; i < new_i ; ++i )
if ( com_options.new_argv[i] && *com_options.new_argv[i] )
com_options.orig_argc = i+1 ; /* dernier arg non nul après élim */
com_options.new_argc = new_i ;
#ifdef SHOW_LIRE_REDIR
fprintf ( stderr, "com_options.new_argc = %d. Arguments restants :\n", com_options.new_argc ) ;
for ( i = 1 ; i < com_options.new_argc ; ++i )
fprintf ( stderr, "%s ", com_options.new_argv[i] ) ;
if ( getch ( ) == 27 )
exit ( 0 ) ;
#endif
if ( nb_erreurs )
return com_getopt_display_error_msg ( opts, nbo, usage ) ;
return GETOPT_OK ;
}
void com_transfere_args ( int argc, char *argv[] ) {
int i ;
if ( argc && argv ) {
for ( i = 0 ; i < argc ; ++i ) {
com_options.orig_argv[i] = strdup ( argv[i] ) ;
if ( !com_options.orig_argv[i] ) {
perror ( "ENOMEM in getopt" ) ;
exit ( EXIT_FAILURE ) ;
} ;
} ;
com_options.orig_argc = argc ;
} ;
}
/* Diaplays ************************************************************* */
void com_go_show_sorted_options ( struct _getopt_option *opts, int nbo ) {
/* option @@ maintenance: show sorted list,
check for duplicate options */
char *buf[GETOPT_NB_MAX_IN_ARGV], *p = com_big_buffer ;
int i, n = 0 ;
p += sprintf ( p, "%d option%s:\n", nbo, COM_PLURIEL(nbo,"s") ) ;
for ( i = 0 ; i < nbo && i < GETOPT_NB_MAX_IN_ARGV ; ++i ) {
if ( opts[i].type != GETOPT_SEPARATEUR ) {
buf[n] = opts[i].nom ;
++n ;
} ;
} ;
qsort ( buf, (size_t) n, (size_t) sizeof ( char * ), sort_name_alpha ) ;
for ( i = 0 ; i < n ; ++i ) {
p += sprintf ( p, "%s ", buf[i] ) ;
if ( i && !stricmp ( buf[i-1], buf[i] ) )
p += sprintf ( p, "dupliquée " ) ;
} ;
p += sprintf ( p, "\n\n" ) ;
qsort ( opts, (size_t) nbo, sizeof ( struct _getopt_option ),
sort_opt_by_name ) ;
}
#define DISPLAY_WIDTH 80
#define DISPLAY_WIDTH_Win 63
#define FILL_CHAR2 ' '
void com_go_display_options ( struct _getopt_option *opts, int nbo,
char *usage ) {
char buf[800], bufg[3*DISPLAY_WIDTH+1], bufd[3*DISPLAY_WIDTH+1], buf2[3*DISPLAY_WIDTH+1],
*p, *pbig ;
int i, nbl_this_opt, nbbn, largeur = DISPLAY_WIDTH, nbl_total = 1 ;
/* 1 car qd on écrit 1 ligne le curseur est sur la suivante = 2 */
#ifdef TARGET_DOS
int j, nbl_par_page ;
struct videoconfig v ;
_getvideoconfig ( &v ) ;
nbl_par_page = v.numtextrows ;
#endif
#ifdef TARGET_Win
char type[81] ;
memset ( type, 'n', DISPLAY_WIDTH_Win ) ;
type[DISPLAY_WIDTH_Win] = 0 ;
largeur = get_text_ext_system_Win ( type ) ;
#endif
/*
fprintf ( stderr, "nbo=%d\nusage=%s\npath=%s\n", nbo, usage, com_options.orig_argv[0] ) ;
*/
*com_big_buffer = 0 ;
if ( usage && *usage ) {
sprintf ( com_big_buffer, usage, com_state.prog_exec_nom, com_state.prog_exec_nom ) ;
nbl_total += com_str_length_in_80_lines ( usage, 8 ) ;
/*
fprintf ( stderr, "nbl usage vaut %d", nbl_total-1 ) ;
getch ( ) ;
*/
} ;
if ( !nbo ) {
strcat ( com_big_buffer,
(strchr ( usage, '<' )
? com_getopt_str_no_other_option
: com_getopt_str_no_option) ) ;
/* if usage is "MYPROG <data file name>" there is actually an option */
return ;
} ;
pbig = com_big_buffer+strlen(com_big_buffer) ;
nbl_total += 3 ; /* ??? */
sprintf ( buf, com_getopt_str_options_de, com_options.orig_argv[0] ) ;
nbbn = DISPLAY_WIDTH-strlen(buf)-strlen(com_getopt_str_valeurs_act)-0 ;
p = buf + strlen ( buf ) ;
while ( nbbn-- > 0 )
*p++ = ' ' ;
*p = 0 ;
pbig += sprintf ( pbig, "%s%s\n", buf, com_getopt_str_valeurs_act ) ;
++nbl_total ;
#ifndef NO_UI
fprintf ( stdout, "%s", com_big_buffer ) ;
#endif
for ( i = 0 ; i < nbo ; ++i ) {
#ifdef TARGET_Win
if ( i > 40 ) {
break ;
} ;
#endif
*buf = 0 ;
*buf2 = 0 ;
*bufd = 0 ;
if ( opts[i].type == GETOPT_SEPARATEUR ) {
com_complete_a_largeur_sep ( opts[i].explication, buf2, largeur ) ;
nbl_this_opt = com_str_length_in_80_lines ( buf2, 8 )-1 ;
}
else {
sprintf ( bufg, " %s: ", opts[i].nom ) ;
nbl_this_opt = com_str_length_in_80_lines ( opts[i].explication, 8 ) ;
switch ( opts[i].type ) {
case GETOPT_CHAR:
sprintf ( bufd, "[%c]", *((char *) opts[i].valeur) ) ;
break ;
case GETOPT_DOUBLE:
com_format_dbl_with_sig_digits (
(double) *((double *) opts[i].valeur), 2, buf2 ) ;
sprintf ( bufd, "[%s]", buf2 ) ;
break ;
case GETOPT_INT32:
sprintf ( bufd, "[%ld]", (long) *((int32 *) opts[i].valeur) ) ;
break ;
case GETOPT_INT32TOGL:
sprintf ( bufd, "[%s]",
(*((int32 *) opts[i].valeur) ? com_getopt_str_toggle_on: com_getopt_str_toggle_off ) ) ;
p = bufd + strlen ( bufd ) - 1 ;
switch ( opts[i].nbv_or_type2 ) {
case GETOPT_DOUBLE:
com_format_dbl_with_sig_digits (
(double) *((double *) opts[i].valeur2), 2, buf2 ) ;
sprintf ( p, ",%s]", buf2 ) ;
break ;
case GETOPT_INT32:
sprintf ( p, ",%ld]", (long) *((int32 *) opts[i].valeur2) ) ;
break ;
case GETOPT_TEXTE:
sprintf ( p, ",\"%s\"]", (char *) opts[i].valeur2 ) ;
break ;
default:
/*
OK, pas de 2ème var
sprintf ( com_error_message, "Type inconnu: %d", (int) opts[i].nbv_or_type2 ) ;
( "COMGETOP: Erreur 1" ) ;
*/
break ;
} ;
break ;
case GETOPT_TEXTE:
sprintf ( bufd, "[\"%s\"]",
( opts[i].nbv_or_type2 > 1 ? ((char **) opts[i].valeur)[0]:
((char *) opts[i].valeur) ) ) ;
break ;
default:
sprintf ( com_error_message, "Type inconnu: %d", (int) opts[i].type ) ;
com_message ( "GetOpt", com_error_message ) ;
exit ( EXIT_FAILURE ) ;
break ;
} ;
sprintf ( buf, "%s%s", bufg, opts[i].explication ) ;
com_complete_a_largeur_opt ( buf, bufd, buf2, largeur ) ;
} ;
#ifdef TARGET_DOS
if ( nbl_total + nbl_this_opt >= nbl_par_page ) {
/* + 1 ligne pour pouvoir mettre le message */
/* et + 1 autre parce qu'on est à la ligne à ce point */
while ( kbhit () )
getch ( ) ;
fprintf ( stderr, com_error_message ) ;
fprintf ( stderr, com_getopt_str_Esc_or_key ) ;
j = getch ( ) ;
while ( kbhit () ) getch ( ) ;
if ( j == 27 )
return ;
fprintf ( stderr, "\n" ) ;
nbl_total = 0 ;
} ;
#endif
#ifdef TARGET_Win
pbig += sprintf ( pbig, "%s\n", buf2 ) ;
#endif
#ifdef TARGET_DOS
fprintf ( stdout, "%s\n", buf2 ) ;
#endif
nbl_total += nbl_this_opt ;
} ;
#ifdef TARGET_DOS
COM_STRNCPY0 ( bufg, com_str_get_fname(com_options.orig_argv[0]), 20 ) ;
p = strchr ( bufg, '.' ) ;
if ( p )
*p = 0 ;
sprintf ( buf2, com_getopt_str_imprime_DOS, bufg ) ;
++nbl_total ;
fprintf ( stdout, "%s\n", buf2 ) ;
#endif
#ifdef TARGET_Win
com_message ( "GetOpt", com_big_buffer ) ;
exit ( EXIT_SUCCESS ) ;
#endif
}
int com_getopt_display_error_msg ( struct _getopt_option *opts, int nbo,
char *usage ) {
int res ;
char *p = com_big_buffer ;
if ( !opts || !nbo ) {
opts = com_options.options ;
nbo = com_options.nb_options ;
} ;
p += sprintf ( p, "%s : ", com_options.new_argv[0] ) ;
p += sprintf ( p, "%s\n", com_getopt_error_msg ) ;
sprintf ( com_error_message, com_getopt_str_nb_errors,
nb_erreurs, COM_PLURIEL(nb_erreurs,"s") ) ;
p += sprintf ( p, "%s\n", com_error_message ) ;
p += sprintf ( p, "%s\n", com_getopt_str_press_space_DOS2 ) ;
res = com_message_yesno ( "GetOpt", com_big_buffer ) ;
if ( res == -1 )
return GETOPT_ERROR ;
if ( res == 1 ) {
/*
*/
qsort ( opts, (size_t) nbo, sizeof ( struct _getopt_option ),
sort_opt_by_original_order ) ;
com_go_display_options ( opts, nbo, usage ) ;
return GETOPT_INFO ;
} ;
return GETOPT_OK ;
}
void com_go_backup_options ( struct _getopt_option *opts, int nbo ) {
/* Copy values pointed to by the options to their <copy_old_value> fields
for later comparison ("has the value changed ?") */
char *p ;
int i ;
if ( !opts || !nbo ) {
opts = com_options.options ;
nbo = com_options.nb_options ;
} ;
for ( i = 0 ; i < nbo ; ++i ) {
if ( opts[i].type != GETOPT_SEPARATEUR ) {
switch ( opts[i].type ) {
case GETOPT_CHAR:
memcpy ( opts[i].copy_old_value, opts[i].valeur, 1 ) ;
break ;
case GETOPT_DOUBLE:
memcpy ( opts[i].copy_old_value, opts[i].valeur, 8 ) ;
break ;
case GETOPT_INT32:
memcpy ( opts[i].copy_old_value, opts[i].valeur, 4 ) ;
break ;
case GETOPT_INT32TOGL:
memcpy ( opts[i].copy_old_value, opts[i].valeur, 4 ) ;
p = (char *) opts[i].valeur2 ;
opts[i].value_storage_size = 4 ;
switch ( opts[i].nbv_or_type2 ) {
case GETOPT_DOUBLE:
memcpy ( opts[i].copy_old_value+4, p, 8 ) ;
opts[i].value_storage_size += 8 ;
break ;
case GETOPT_INT32:
memcpy ( opts[i].copy_old_value+4, p, 4 ) ;
opts[i].value_storage_size += 4 ;
break ;
case GETOPT_TEXTE:
strncpy ( opts[i].copy_old_value+4, p, min(strlen(p),80) ) ;
opts[i].value_storage_size += min(strlen(p),80) ;
break ;
default:
break ;
} ;
break ;
case GETOPT_TEXTE:
p = (char *) opts[i].valeur ;
strncpy ( opts[i].copy_old_value, p, min(strlen(p),80) ) ;
break ;
default:
sprintf ( com_error_message, "Type inconnu: %d", (int) opts[i].type ) ;
com_message ( "GetOpt", com_error_message ) ;
exit ( EXIT_FAILURE ) ;
break ;
} ;
#ifdef SHOW_SAVE_OPTIONS
switch ( opts[i].type ) {
case GETOPT_DOUBLE:
sprintf ( com_error_message, "%s : %f, size %d bytes.",
opts[i].nom,
(double) *((double *) opts[i].copy_old_value),
opts[i].value_storage_size ) ;
com_message ( "save_opt", com_error_message ) ;
break ;
case GETOPT_INT32:
case GETOPT_INT32TOGL:
sprintf ( com_error_message, "%s : %ld, size %d bytes.",
opts[i].nom,
(long) *((int32 *) opts[i].copy_old_value),
opts[i].value_storage_size ) ;
com_message ( "save_opt", com_error_message ) ;
break ;
default:
break ;
} ;
#endif
} ;
} ;
}
void com_go_restore_options ( struct _getopt_option *opts, int nbo ) {
/* The reverse of com_go_backup_options
This gives you one-line "Reset initial values" capability */
char *p ;
int i ;
if ( !opts || !nbo ) {
opts = com_options.options ;
nbo = com_options.nb_options ;
} ;
for ( i = 0 ; i < nbo ; ++i ) {
if ( opts[i].type != GETOPT_SEPARATEUR ) {
switch ( opts[i].type ) {
case GETOPT_CHAR:
memcpy ( opts[i].valeur, opts[i].copy_old_value, 1 ) ;
break ;
case GETOPT_DOUBLE:
memcpy ( opts[i].valeur, opts[i].copy_old_value, 8 ) ;
break ;
case GETOPT_INT32:
memcpy ( opts[i].valeur, opts[i].copy_old_value, 4 ) ;
break ;
case GETOPT_INT32TOGL:
memcpy ( opts[i].valeur, opts[i].copy_old_value, 4 ) ;
p = (char *) opts[i].valeur2 ;
switch ( opts[i].nbv_or_type2 ) {
case GETOPT_DOUBLE:
memcpy ( p, opts[i].copy_old_value+4, 8 ) ;
break ;
case GETOPT_INT32:
memcpy ( p, opts[i].copy_old_value+4, 4 ) ;
break ;
case GETOPT_TEXTE:
strncpy ( p, opts[i].copy_old_value+4, min(strlen(opts[i].copy_old_value+4),80) ) ;
break ;
default:
break ;
} ;
break ;
case GETOPT_TEXTE:
p = (char *) opts[i].valeur ;
strncpy ( p, opts[i].copy_old_value, min(strlen(opts[i].copy_old_value),80) ) ;
break ;
default:
sprintf ( com_error_message, "Type inconnu: %d", (int) opts[i].type ) ;
com_message ( "GetOpt", com_error_message ) ;
exit ( EXIT_FAILURE ) ;
break ;
} ;
} ;
} ;
}
#ifdef SHOW_OUTPUT_OPTIONS
char debug_buf[3000] ;
#endif
void com_go_output_options ( struct _getopt_option *opts, int nbo,
int only_changed_p ) {
/* Outputs all options values to com_big_buffer, in a form suitable
for re-analysis, or saving to a file and loading it via the
@redir.opt functionality */
char *p, bufg[3*DISPLAY_WIDTH+1], bufd[3*DISPLAY_WIDTH+1], buf2[3*DISPLAY_WIDTH+1] ;
int i, skip_p;
if ( !opts || !nbo ) {
opts = com_options.options ;
nbo = com_options.nb_options ;
} ;
#ifdef SHOW_OUTPUT_OPTIONS
*debug_buf = 0 ;
#endif
*com_big_buffer = 0 ;
for ( i = 0 ; i < nbo ; ++i ) {
*buf2 = *bufg = *bufd = 0 ;
if ( opts[i].type == GETOPT_SEPARATEUR )
continue ;
skip_p = 1 ;
if ( !only_changed_p
|| memcmp ( opts[i].valeur, opts[i].copy_old_value,
opts[i].value_storage_size ) )
skip_p = 0 ;
#ifdef SHOW_OUTPUT_OPTIONS
if ( !skip_p )
switch ( opts[i].type ) {
case GETOPT_DOUBLE:
sprintf ( com_error_message, "%s : %f vs. %f, size %d bytes, égaux=%s.",
opts[i].nom,
(double) *((double *) opts[i].copy_old_value),
(double) *((double *) opts[i].valeur),
opts[i].value_storage_size, ( skip_p ? "oui":"**NON**" ) ) ;
strcat ( debug_buf, com_error_message ) ;
break ;
case GETOPT_INT32:
case GETOPT_INT32TOGL:
sprintf ( com_error_message, "%s : %ld vs. %ld, size %d bytes, égaux=%s.",
opts[i].nom,
(long) *((int32 *) opts[i].copy_old_value),
(long) *((int32 *) opts[i].valeur),
opts[i].value_storage_size, ( skip_p ? "oui":"**NON**" ) ) ;
break ;
default:
break ;
} ;
#endif
if ( skip_p )
continue ;
sprintf ( bufg, "/%s", opts[i].nom ) ;
*bufd = 0 ;
switch ( opts[i].type ) {
case GETOPT_CHAR:
sprintf ( bufd, "%c", *((char *) opts[i].valeur) ) ;
break ;
case GETOPT_DOUBLE:
com_format_dbl_with_sig_digits (
(double) *((double *) opts[i].valeur), 2, bufd ) ;
break ;
case GETOPT_INT32:
sprintf ( bufd, "%ld", (long) *((int32 *) opts[i].valeur) ) ;
break ;
case GETOPT_INT32TOGL:
*buf2 = 0 ;
switch ( opts[i].nbv_or_type2 ) {
case GETOPT_DOUBLE:
com_format_dbl_with_sig_digits (
(double) *((double *) opts[i].valeur2), 2, buf2 ) ;
break ;
case GETOPT_INT32:
sprintf ( buf2, "%ld", (long) *((int32 *) opts[i].valeur2) ) ;
break ;
case GETOPT_TEXTE:
p = (char *) opts[i].valeur2 ;
/*
*/
if ( *p )
sprintf ( buf2, "\"%s\"",
((*p||only_changed_p)?p:( *((int32 *) opts[i].valeur) ? ":1" : ":0" )) ) ;
break ;
default:
/*
continue ;
*/
if ( !only_changed_p ) /* CARBASCULE = PAS BESOIN DE PRéCISER */
strcpy ( buf2, ( *((int32 *) opts[i].valeur) ? ":1" : ":0" ) ) ;
break ;
} ;
strcat ( bufd, buf2 ) ;
break ;
case GETOPT_TEXTE:
p = (char *) opts[i].valeur ;
if ( *p ) {
sprintf ( bufd, "\"%s\"",
( opts[i].nbv_or_type2 > 1 ?
((char **) opts[i].valeur)[0] :
((char *) opts[i].valeur) ) ) ;
}
else {
/* ne rien mettre
*bufg = *bufd = 0 ;
*/
continue ;
} ;
break ;
default:
sprintf ( com_error_message, "Type inconnu: %d", (int) opts[i].type ) ;
com_message ( "GetOpt", com_error_message ) ;
exit ( EXIT_FAILURE ) ;
break ;
} ;
strcat ( bufg, bufd ) ;
strcat ( com_big_buffer, bufg ) ;
strcat ( com_big_buffer, "\n" ) ;
} ;
#ifdef SHOW_OUTPUT_OPTIONS
com_message ( "debug_buf", debug_buf ) ;
#endif
#ifdef SHOW_OUTPUT_OPTIONS2
com_message ( "com_big_buffer", com_big_buffer ) ;
#endif
}
/* Utilities ************************************************************* */
void com_complete_a_largeur_opt ( char *bufg, char *bufd, char *dest, int largeur ) {
char *p, buf2[2*DISPLAY_WIDTH+2] = " " ;
int nbbn ;
#ifdef TARGET_Win
char buf[2*DISPLAY_WIDTH+2] = " " ;
int j ;
p = strrchr ( bufg, '\n' ) ;
if ( !p )
p = bufg ;
for ( j = 1 ; j < DISPLAY_WIDTH+60 ; ++j ) {
memset ( buf2+1, FILL_CHAR2, j ) ;
buf2[j] = 0 ;
sprintf ( dest, "%s%s%s", bufg, buf2, bufd ) ;
sprintf ( buf, "%s%s%s", p, buf2, bufd ) ;
nbbn = get_text_ext_system_Win ( buf ) ;
if ( nbbn > largeur )
break ;
} ;
#endif
#ifdef TARGET_DOS
*dest = 0 ;
p = strrchr ( bufg, '\n' ) ;
if ( p ) {
++p ;
nbbn = DISPLAY_WIDTH-strlen(p)-strlen(bufd)-1 ;
while ( *p == '\t' ) {
++p ;
nbbn += 1 ;
nbbn -= 8 ;
} ;
}
else {
p = bufg ;
nbbn = DISPLAY_WIDTH-strlen(p)-strlen(bufd)-1 ;
} ;
p = buf2 ;
while ( nbbn-- > 0 )
*p++ = ' ' ;
*p = 0 ;
sprintf ( dest, "%s%s%s", bufg, buf2, bufd ) ;
#endif
}
void com_complete_a_largeur_sep ( char *bufg, char *dest, int largeur ) {
#ifdef TARGET_Win
int j, l ;
char buf[2*DISPLAY_WIDTH+1] = " " ;
#endif
char *p, tmp[2*DISPLAY_WIDTH+1] ;
strncpy ( tmp, bufg, DISPLAY_WIDTH ) ;
tmp[DISPLAY_WIDTH-1] = 0 ;
p = tmp ;
while ( *p == '\n' )
++p ;
#ifdef TARGET_Win
for ( j = 1 ; j < DISPLAY_WIDTH ; ++j ) {
memset ( buf+1, '-', j ) ;
buf[j] = 0 ;
sprintf ( dest, "%s%s", p, buf ) ;
l = get_text_ext_system_Win ( dest ) ;
if ( l > largeur )
break ;
} ;
#endif
#ifdef TARGET_DOS
strcat ( tmp, " ---------------------------------------------------------------------------" ) ;
p[DISPLAY_WIDTH-1] = 0 ;
strcpy ( dest, tmp ) ;
#endif
}
int com_go_option_was_used_p ( char *nom, void *adresse ) {
int i, res = 0 ;
#ifdef SHOW_WAS_USED
fprintf ( stderr, "Nom=%s, adresse=%X. ", nom, adresse ) ;
#endif
if ( !com_options.nb_options ) {
com_message ( "GetOpt", "ref_opts pas init !!!!\n" ) ;
return 0 ;
} ;
for ( i = 0 ; i < com_options.nb_options ; ++i ) {
if ( !com_options.options[i].nom ) {
sprintf ( com_error_message, "ref_opts[%d].nom pas init !!!!\n", i ) ;
com_message ( "GetOpt", com_error_message ) ;
return 0 ;
} ;
if ( nom && *nom && !stricmp ( com_options.options[i].nom, nom ) )
res = com_options.options[i].used_p ;
if ( adresse && com_options.options[i].valeur == adresse )
res = com_options.options[i].used_p ;
if ( adresse && com_options.options[i].valeur2 == adresse )
res = com_options.options[i].used_p ;
} ;
#ifdef SHOW_WAS_USED
fprintf ( stderr, "Résultat=%d\n", res ) ;
getch ( ) ;
#endif
return res ;
}
/* reading from an options file ******************************************/
#define SEPARATEURS " \t\r\n"
int com_go_lire_redir ( char *filename, char *file_argv[] ) {
char *p, *p2, buffer[3000] ;
int l, nb_opt = 0, nbl = 0 ;
FILE *fp = fopen ( filename, "rt" ) ;
if ( !file_argv )
file_argv = com_options.new_argv ;
if ( !fp ) {
sprintf ( com_error_message, com_go_error_cant_find_opt_file, filename ) ;
return -1 ;
} ;
*com_big_buffer = 0 ;
for ( ;; ) {
if ( !fgets ( buffer, 3000-1, fp ) )
break ;
/*com_str_vire_blancs_trm_et_init ( buffer ) ;*/
strcat ( com_big_buffer, buffer ) ;
} ;
fclose ( fp ) ;
if ( !*com_big_buffer )
return 0 ;
com_protege_blancs_guill ( com_big_buffer ) ;
p = strtok ( com_big_buffer, SEPARATEURS ) ;
while ( p && nb_opt < GETOPT_NB_MAX_IN_ARGV ) {
++nbl ;
p2 = strdup ( p ) ;
l = strlen ( p2 ) ;
if ( (*p2 == '\"') && (p2[l-1] == '\"') ) {
p2[l-1] = 0 ;
++p2 ;
} ;
com_deprotege_blancs_guill ( p2 ) ;
file_argv[nb_opt] = p2 ;
#ifdef SHOW_LIRE_REDIR
fprintf ( stderr, "Ajouté @rgument \"%s\" au rang %d.\n", p2, nb_opt ) ;
#endif
++nb_opt ;
p = strtok ( NULL, SEPARATEURS ) ;
} ;
return nb_opt ;
}
/* Adding & clearing options ******************************************/
void com_go_add_options ( struct _getopt_option *options_src, int nb_options ) {
/* Declaring options for processing by com_go_getopt */
/* options_dest est l'adresse de la 1ère destination, pas du début */
int i ;
#ifdef SHOW_SAVE_OPTIONS
sprintf ( com_error_message, " adding %s
%d optns.",
options_src[0].nom, nb_options ) ;
com_message ( "save_opt", com_error_message ) ;
#endif
for ( i = 0 ; i < nb_options && com_options.nb_options < GETOPT_NB_MAX_OPTNS ;
++com_options.nb_options, ++i ) {
if ( options_src[i].type != GETOPT_SEPARATEUR ) {
/* Completing the option struct */
options_src[i].lg_nom = strlen ( options_src[i].nom ) ;
options_src[i].used_p = 0 ;
switch ( options_src[i].type ) {
case GETOPT_CHAR:
options_src[i].value_storage_size = 1 ;
break ;
case GETOPT_DOUBLE:
options_src[i].value_storage_size = 8 ;
break ;
case GETOPT_INT32:
options_src[i].value_storage_size = 4 ;
break ;
case GETOPT_INT32TOGL:
options_src[i].value_storage_size = 84 ;
break ;
case GETOPT_TEXTE:
options_src[i].value_storage_size = 80 ;
break ;
default:
options_src[i].value_storage_size = 0 ;
break ;
} ;
if ( options_src[i].value_storage_size ) {
options_src[i].copy_old_value = calloc ( sizeof ( char ), options_src[i].value_storage_size ) ;
if ( !options_src[i].copy_old_value )
com_abort ( "!alloc getopt" ) ;
} ;
} ;
com_options.options[com_options.nb_options] = options_src[i] ;
} ;
}
void com_go_clear_options ( void ) {
com_options.nb_options = 0 ;
}
/* Internals ********************************************************** */
int com_go_verify_options ( struct _getopt_option *opts, int nbo ) {
char *buf[GETOPT_NB_MAX_IN_ARGV] ;
int i, n = 0 ;
for ( i = 0 ; i < com_options.nb_options ; ++i )
com_options.options[i].index = i ;
qsort ( buf, (size_t) n, (size_t) sizeof ( char * ), sort_name_alpha ) ;
for ( i = 0 ; i < n ; ++i ) {
if ( i && !stricmp ( buf[i-1], buf[i] ) ) {
pmsg += sprintf ( pmsg, "%s dupliquée\n", buf[i] ) ;
++nb_erreurs ;
} ;
} ;
return nb_erreurs ;
}
int sort_name_alpha ( const void *e1, const void *e2 ) {
char *str1 = * ( ( char ** ) e1 ), *str2 = * ( ( char ** ) e2 ) ;
int n = stricmp ( str1, str2 ) ;
return n ;
}
int sort_opt_by_name ( const void *e1, const void *e2 ) {
/* mettre le + long d'abord, sinon conflit entre /+ et /++ */
struct _getopt_option const *opt1 = e1, *opt2 = e2 ;
return strcmp ( opt1->nom, opt2->nom ) ;
}
int sort_opt_by_length ( const void *e1, const void *e2 ) {
/* mettre le + long d'abord, sinon conflit entre /+ et /++ */
struct _getopt_option const *opt1 = e1, *opt2 = e2 ;
return opt2->lg_nom-(signed)opt1->lg_nom ;
}
int sort_opt_by_original_order ( const void *e1, const void *e2 ) {
/* remettre dans l'ordre de départ avant d'afficher */
struct _getopt_option const *opt1 = e1, *opt2 = e2 ;
return opt1->index-opt2->index ;
}
#define FILL_CHAR ((char) 4)
void com_protege_blancs_guill ( char *buffer ) {
/* Whitespace within quotes protection for strtok */
int in_guill_p = 0 ;
char *p = buffer ;
while ( *p ) {
if ( *p == '\"' )
in_guill_p = 1 - in_guill_p ;
if ( *p == ' ' && in_guill_p )
*p = FILL_CHAR ;
++p ;
} ;
}
void com_deprotege_blancs_guill ( char *buffer ) {
/* Whitespace within quotes deprotection for strtok */
char *p = buffer ;
while ( *p ) {
if ( *p == FILL_CHAR )
*p = ' ' ;
++p ;
} ;
}