1 /*********************************************************
2  * cc90hfe (c) Teo Developers
3  *********************************************************
4  *
5  *  Copyright (C) 2012-2017 Fran�ois Mouret
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 
22 /*
23  *  Module     : option.c
24  *  Version    : 0.7.0
25  *  Cr�� par   : Fran�ois Mouret 27/02/2013
26  *  Modifi� par: Fran�ois Mouret 31/05/2015
27  *
28  *  Management of the command line.
29  */
30 
31 
32 #ifndef SCAN_DEPEND
33    #include <stdio.h>
34    #include <stdlib.h>
35    #include <string.h>
36    #include <ctype.h>
37    #include <sys/stat.h>
38    #include <unistd.h>
39 #endif
40 
41 #include "defs.h"
42 #include "main.h"
43 #include "std.h"
44 #include "option.h"
45 #include "ini.h"
46 #include "encode.h"
47 #include "errors.h"
48 
49 
50 enum {
51   WRONG_OPTION = 0,
52   SHORT_OPTION,
53   LONG_OPTION
54 };
55 
56 struct OPTION_ENTRY *help_option = NULL;
57 struct OPTION_ENTRY *prog_option = NULL;
58 
59 
60 
61 /* help_display:
62  *  Affiche une liste d'aide.
63  */
help_display(struct OPTION_ENTRY option[])64 static void help_display (struct OPTION_ENTRY option[])
65 {
66     int i;
67     size_t size;
68 
69     for (i=0; option[i].long_name!=NULL; i++)
70     {
71         size = 0;
72         printf ("  ");
73         if (option[i].short_name != '\0')
74             size += printf ("-%c, ", option[i].short_name);
75         size += printf ("--%s", option[i].long_name);
76         if (option[i].argument != NULL)
77             size += printf (" <%s>",option[i].argument);
78         if (option[i].comment != NULL) {
79            do { size += printf (" "); } while (size < 19);
80            (void)printf (" %s", encode_String(option[i].comment));
81         }
82         (void)printf ("\n");
83     }
84 }
85 
86 
87 
88 /* help:
89  *  Affiche l'aide.
90  */
help(char * program_name)91 static void help (char *program_name)
92 {
93     printf ("\n%s:\n", is_fr?"Utilisation":"Usage");
94     printf ("    %s [OPTION...] %s\n\n", program_name,
95                            is_fr?"[FICHIER HFE]":"[HFE FILE]");
96     printf ("%s:\n", is_fr?"Options de l'aide":"Help Options");
97     help_display (help_option);
98     printf ("\n");
99     printf ("%s:\n", is_fr?"Options de l'application":"Application Options");
100     help_display (prog_option);
101     printf ("\n");
102     main_FreeAll ();
103     exit (EXIT_SUCCESS);
104 }
105 
106 
107 
108 /* get_string:
109  *  Traite une liste d'options.
110  */
get_string(struct OPTION_ENTRY * option,char * str)111 static char *get_string (struct OPTION_ENTRY *option, char *str)
112 {
113     char *p, *s, *tmp_s;
114     char **reg;
115 
116     if (str != NULL)
117     {
118         s = std_strdup_printf ("%s", str);
119         if ((s != NULL)
120          && (*s == '"')
121          && ((p = strrchr (s, '"')) != NULL)
122          && (p > s))
123         {
124             *p = '\0';
125             tmp_s = std_strdup_printf ("%s", s+1);
126             s = std_free (s);
127             s = tmp_s;
128         }
129         reg = option->reg;
130         *reg = (char*)std_free (*reg);
131         *reg = std_strdup_printf ("%s",s);
132     }
133     return str;
134 }
135 
136 
137 
138 /* option_check:
139  *  Traite une liste d'options.
140  */
option_check(int argc,char * argv[],char * internal_prog_name,struct OPTION_ENTRY option[],struct STRING_LIST ** remain_option)141 static char *option_check (int argc, char *argv[],
142                           char *internal_prog_name,
143                           struct OPTION_ENTRY option[],
144                           struct STRING_LIST **remain_option)
145 {
146     char *s = NULL;
147     int i, op;
148     int *d;
149     int option_size;
150     int option_i = 0;
151     int arg_i;
152 
153     for (i=1; i<argc; i++)
154     {
155         if (argv[i][0] == '-')
156         {
157             option_size = WRONG_OPTION;
158             for (op=0; (option[op].long_name != NULL) && (option_size == WRONG_OPTION); op++)
159             {
160                 option_i = op;
161                 if (strlen(argv[i]) == 2)
162                 {
163                     if (argv[i][1] == option[op].short_name)
164                         option_size = SHORT_OPTION;
165                 }
166                 else
167                 if (argv[i][1] == '-')
168                 {
169                     if (strncmp (&argv[i][2], option[op].long_name,
170                              strlen (option[op].long_name)) == 0)
171                         option_size = LONG_OPTION;
172                 }
173             }
174 
175             if (option_size == WRONG_OPTION)
176                 return std_strdup_printf ("%s : %s", argv[i],
177                               is_fr?"Option inconnue":"Unknown option");
178 
179             switch (option[option_i].type) {
180             case OPTION_ARG_FILENAME :
181             case OPTION_ARG_STRING :
182                 if (option_size == SHORT_OPTION) {
183                     s = std_free(s);
184                     if (++i < argc)
185                         s = get_string (&option[option_i], argv[i]);
186                 } else {
187                    arg_i = strlen (option[option_i].long_name) + 2;
188                    if (argv[i][arg_i] == '=')
189                        s = get_string (&option[option_i], std_strdup_printf ("%s", &argv[i][arg_i+1]));
190                 }
191                 if (s==NULL)
192                      return std_strdup_printf ("%s %s",
193                               is_fr?"Argument manquant pour":"Missing argument for",
194                               argv[i]);
195                 break;
196 
197             case OPTION_ARG_INT :
198                 d = option[option_i].reg;
199                 *d = (int)strtol (argv[i+1],NULL,10);
200                 if ((*d < option[option_i].min_value)
201                  || (*d > option[option_i].max_value))
202                      return std_strdup_printf ("%s %s (%d,%d)",
203                               is_fr?"Mauvaise valeur pour":"Bad value for",
204                               argv[i],
205                               option[option_i].min_value,
206                               option[option_i].max_value
207                               );
208                 i++;
209                 break;
210 
211             case OPTION_ARG_BOOL :
212                 d = option[option_i].reg;
213                 *d = TRUE;
214                 break;
215 
216             case OPTION_ARG_HELP :
217                 help (internal_prog_name);
218                 break;
219 
220             default : return std_strdup_printf ("%s %s",
221                               is_fr?"Type inconnu pour":"Unknown type for",
222                               argv[i]);
223             }
224         }
225         else
226             *remain_option = std_StringListAppend (*remain_option, argv[i]);
227     }
228     return NULL;
229 }
230 
231 
232 /* ------------------------------------------------------------------------- */
233 
234 
235 /* option_Parse:
236  *  Traite les options.
237  */
option_Parse(int argc,char * argv[],char * internal_prog_name,struct OPTION_ENTRY prog_option_list[],struct STRING_LIST ** remain_option)238 char *option_Parse (int argc, char *argv[],
239                           char *internal_prog_name,
240                           struct OPTION_ENTRY prog_option_list[],
241                           struct STRING_LIST **remain_option)
242 {
243     struct OPTION_ENTRY help_option_list[] = {
244         { "help", 'h', OPTION_ARG_HELP, NULL,
245           is_fr?"Aide de ce programme":"Help of this program", NULL },
246         { NULL, 0, 0, NULL, NULL, NULL }
247     };
248 
249     help_option = help_option_list;
250     prog_option = prog_option_list;
251 
252     error_msg = std_free (error_msg);
253     error_msg = option_check (argc, argv, internal_prog_name,
254                               help_option, remain_option);
255     if (error_msg != NULL) {
256         error_msg = std_free (error_msg);
257         error_msg = option_check (argc, argv, internal_prog_name,
258                                       prog_option, remain_option);
259     }
260     return error_msg;
261 }
262 
263