1 /*
2   File autogenerated by gengetopt version 2.23
3   generated with the following command:
4   /usr/bin/gengetopt -i RNAheat.ggo --file-name=RNAheat_cmdl --include-getopt --default-optional --unamed-opts --func-name=RNAheat_cmdline_parser --arg-struct-name=RNAheat_args_info
5 
6   The developers of gengetopt consider the fixed text that goes in all
7   gengetopt output files to be in the public domain:
8   we make no copyright claims on it.
9 */
10 
11 /* If we use autoconf.  */
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 
20 #ifndef FIX_UNUSED
21 #define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */
22 #endif
23 
24 
25 #include "RNAheat_cmdl.h"
26 
27 const char *RNAheat_args_info_purpose = "calculate specific heat of RNAs";
28 
29 const char *RNAheat_args_info_usage = "Usage: RNAheat [OPTIONS] [<input0>] [<input1>]...";
30 
31 const char *RNAheat_args_info_versiontext = "";
32 
33 const char *RNAheat_args_info_description = "Reads RNA sequences from stdin or input files and calculates their specific\nheat in the temperature range t1 to t2, from the partition function by numeric\ndifferentiation. The result is written to stdout as a list of pairs of\ntemperature in C and specific heat in Kcal/(Mol*K).\nThe program will continue to read new sequences until a line consisting of the\nsingle character \"@\" or an end of file condition is encountered.\n";
34 
35 const char *RNAheat_args_info_detailed_help[] = {
36   "  -h, --help                 Print help and exit",
37   "      --detailed-help        Print help, including all details and hidden\n                               options, and exit",
38   "      --full-help            Print help, including hidden options, and exit",
39   "  -V, --version              Print version and exit",
40   "\nGeneral Options:",
41   "  Below are command line options which alter the general behavior of this\n  program\n\n",
42   "      --Tmin=t1              Lowest temperature\n\n                                 (default=`0')",
43   "      --Tmax=t2              Highest temperature\n\n                                 (default=`100')",
44   "      --stepsize=FLOAT       Calculate partition function every stepsize\n                               degrees C\n\n                                 (default=`1.')",
45   "  -m, --ipoints=ipoints      The program fits a parabola to 2*ipoints+1 data\n                               points to calculate 2nd derivatives. Increasing\n                               this parameter produces a smoother curve\n\n                                 (default=`2')",
46   "      --noconv               Do not automatically substitude nucleotide \"T\"\n                               with \"U\"\n\n                                 (default=off)",
47   "  -j, --jobs[=number]        Split batch input into jobs and start processing\n                               in parallel using multiple threads. A value of 0\n                               indicates to use as many parallel threads as\n                               computation cores are available.\n                                 (default=`0')",
48   "  Default processing of input data is performed in a serial fashion, i.e. one\n  sequence at a time. Using this switch, a user can instead start the\n  computation for many sequences in the input in parallel. RNAheat will create\n  as many parallel computation slots as specified and assigns input sequences\n  of the input file(s) to the available slots. Note, that this increases memory\n  consumption since input alignments have to be kept in memory until an empty\n  compute slot is available and each running job requires its own dynamic\n  programming matrices.\n\n",
49   "      --unordered            Do not try to keep output in order with input\n                               while parallel processing is in place.\n                                 (default=off)",
50   "  When parallel input processing (--jobs flag) is enabled, the order in which\n  input is processed depends on the host machines job scheduler. Therefore, any\n  output to stdout or files generated by this program will most likely not\n  follow the order of the corresponding input data set. The default of RNAheat\n  is to use a specialized data structure to still keep the results output in\n  order with the input data. However, this comes with a trade-off in terms of\n  memory consumption, since all output must be kept in memory for as long as no\n  chunks of consecutive, ordered output are available. By setting this flag,\n  RNAheat will not buffer individual results but print them as soon as they\n  have been computated.\n\n",
51   "  -i, --infile=<filename>    Read a file instead of reading from stdin\n",
52   "  The default behavior of RNAheat is to read input from stdin or the file(s)\n  that follow(s) the RNAheat command. Using this parameter the user can specify\n  input file names where data is read from. Note, that any additional files\n  supplied to RNAheat are still processed as well.\n\n",
53   "      --auto-id              Automatically generate an ID for each sequence.\n                                 (default=off)",
54   "  The default mode of RNAheat is to automatically determine an ID from the\n  input sequence data if the input file format allows to do that. Sequence IDs\n  are usually given in the FASTA header of input sequences. If this flag is\n  active, RNAheat ignores any IDs retrieved from the input and automatically\n  generates an ID for each sequence. This ID consists of a prefix and an\n  increasing number. This flag can also be used to add a FASTA header to the\n  output even if the input has none.\n\n",
55   "      --id-prefix=prefix     Prefix for automatically generated IDs (as used in\n                               output file names)\n\n                                 (default=`sequence')",
56   "  If this parameter is set, each sequences' FASTA id will be prefixed with the\n  provided string. FASTA ids then take the form \">prefix_xxxx\" where xxxx is\n  the sequence number. Note: Setting this parameter implies --auto-id.\n\n",
57   "      --id-delim=delimiter   Change the delimiter between prefix and increasing\n                               number for automatically generated IDs (as used\n                               in output file names)\n\n                                 (default=`_')",
58   "  This parameter can be used to change the default delimiter \"_\" between\n   the prefix string and the increasing number for automatically generated ID.\n\n",
59   "      --id-digits=INT        Specify the number of digits of the counter in\n                               automatically generated alignment IDs.\n                                 (default=`4')",
60   "  When alignments IDs are automatically generated, they receive an increasing\n  number, starting with 1. This number will always be left-padded by leading\n  zeros, such that the number takes up a certain width. Using this parameter,\n  the width can be specified to the users need. We allow numbers in the range\n  [1:18]. This option implies --auto-id.\n\n",
61   "      --id-start=LONG        Specify the first number in automatically\n                               generated alignment IDs.\n                                 (default=`1')",
62   "  When sequence IDs are automatically generated, they receive an increasing\n  number, usually starting with 1. Using this parameter, the first number can\n  be specified to the users requirements. Note: negative numbers are not\n  allowed.\n  Note: Setting this parameter implies to ignore any IDs retrieved from the\n  input data, i.e. it activates the --auto-id flag.\n\n",
63   "\nStructure Constraints:",
64   "  Command line options to interact with the structure constraints feature of\n  this program\n\n",
65   "      --maxBPspan=INT        Set the maximum base pair span\n\n                                 (default=`-1')",
66   "\nModel Details:",
67   "  -4, --noTetra              Do not include special tabulated stabilizing\n                               energies for tri-, tetra- and hexaloop hairpins.\n                               Mostly for testing.\n\n                                 (default=off)",
68   "  -d, --dangles=INT          How to treat \"dangling end\" energies for bases\n                               adjacent to helices in free ends and multi-loops\n                                 (default=`2')",
69   "  \n  With -d2 dangling energies will be added for the bases adjacent to a helix on\n  both sides in any case\n\n  -d0 ignores dangling ends altogether (mostly for debugging).\n\n",
70   "      --noLP                 Produce structures without lonely pairs (helices\n                               of length 1).\n                                 (default=off)",
71   "  For partition function folding this only disallows pairs that can only occur\n  isolated. Other pairs may still occasionally occur as helices of length 1.\n\n",
72   "      --noGU                 Do not allow GU pairs\n\n                                 (default=off)",
73   "      --noClosingGU          Do not allow GU pairs at the end of helices\n\n                                 (default=off)",
74   "  -P, --paramFile=paramfile  Read energy parameters from paramfile, instead of\n                               using the default parameter set.\n",
75   "  Different sets of energy parameters for RNA and DNA should accompany your\n  distribution.\n  See the RNAlib documentation for details on the file format. When passing the\n  placeholder file name \"DNA\", DNA parameters are loaded without the need to\n  actually specify any input file.\n\n",
76   "      --nsp=STRING           Allow other pairs in addition to the usual\n                               AU,GC,and GU pairs.\n",
77   "  Its argument is a comma separated list of additionally allowed pairs. If the\n  first character is a \"-\" then AB will imply that AB and BA are allowed\n  pairs.\n  e.g. RNAheat -nsp -GA  will allow GA and AG pairs. Nonstandard pairs are\n  given 0 stacking energy.\n\n",
78   "  -e, --energyModel=INT      Rarely used option to fold sequences from the\n                               artificial ABCD... alphabet, where A pairs B,\n                               C-D etc.  Use the energy parameters for GC (-e\n                               1) or AU (-e 2) pairs.\n\n",
79   "  -g, --gquad                Incoorporate G-Quadruplex formation into the\n                               structure prediction algorithm.\n\n                                 (default=off)",
80   "  -c, --circ                 Assume a circular (instead of linear) RNA\n                               molecule.\n\n                                 (default=off)",
81   "\nIf in doubt our program is right, nature is at fault.\nComments should be sent to rna@tbi.univie.ac.at.\n\n",
82     0
83 };
84 static void
init_full_help_array(void)85 init_full_help_array(void)
86 {
87   RNAheat_args_info_full_help[0] = RNAheat_args_info_detailed_help[0];
88   RNAheat_args_info_full_help[1] = RNAheat_args_info_detailed_help[1];
89   RNAheat_args_info_full_help[2] = RNAheat_args_info_detailed_help[2];
90   RNAheat_args_info_full_help[3] = RNAheat_args_info_detailed_help[3];
91   RNAheat_args_info_full_help[4] = RNAheat_args_info_detailed_help[4];
92   RNAheat_args_info_full_help[5] = RNAheat_args_info_detailed_help[5];
93   RNAheat_args_info_full_help[6] = RNAheat_args_info_detailed_help[6];
94   RNAheat_args_info_full_help[7] = RNAheat_args_info_detailed_help[7];
95   RNAheat_args_info_full_help[8] = RNAheat_args_info_detailed_help[8];
96   RNAheat_args_info_full_help[9] = RNAheat_args_info_detailed_help[9];
97   RNAheat_args_info_full_help[10] = RNAheat_args_info_detailed_help[10];
98   RNAheat_args_info_full_help[11] = RNAheat_args_info_detailed_help[11];
99   RNAheat_args_info_full_help[12] = RNAheat_args_info_detailed_help[13];
100   RNAheat_args_info_full_help[13] = RNAheat_args_info_detailed_help[15];
101   RNAheat_args_info_full_help[14] = RNAheat_args_info_detailed_help[17];
102   RNAheat_args_info_full_help[15] = RNAheat_args_info_detailed_help[19];
103   RNAheat_args_info_full_help[16] = RNAheat_args_info_detailed_help[21];
104   RNAheat_args_info_full_help[17] = RNAheat_args_info_detailed_help[23];
105   RNAheat_args_info_full_help[18] = RNAheat_args_info_detailed_help[25];
106   RNAheat_args_info_full_help[19] = RNAheat_args_info_detailed_help[27];
107   RNAheat_args_info_full_help[20] = RNAheat_args_info_detailed_help[28];
108   RNAheat_args_info_full_help[21] = RNAheat_args_info_detailed_help[29];
109   RNAheat_args_info_full_help[22] = RNAheat_args_info_detailed_help[30];
110   RNAheat_args_info_full_help[23] = RNAheat_args_info_detailed_help[31];
111   RNAheat_args_info_full_help[24] = RNAheat_args_info_detailed_help[32];
112   RNAheat_args_info_full_help[25] = RNAheat_args_info_detailed_help[34];
113   RNAheat_args_info_full_help[26] = RNAheat_args_info_detailed_help[36];
114   RNAheat_args_info_full_help[27] = RNAheat_args_info_detailed_help[37];
115   RNAheat_args_info_full_help[28] = RNAheat_args_info_detailed_help[38];
116   RNAheat_args_info_full_help[29] = RNAheat_args_info_detailed_help[40];
117   RNAheat_args_info_full_help[30] = RNAheat_args_info_detailed_help[42];
118   RNAheat_args_info_full_help[31] = RNAheat_args_info_detailed_help[43];
119   RNAheat_args_info_full_help[32] = RNAheat_args_info_detailed_help[44];
120   RNAheat_args_info_full_help[33] = RNAheat_args_info_detailed_help[45];
121   RNAheat_args_info_full_help[34] = 0;
122 
123 }
124 
125 const char *RNAheat_args_info_full_help[35];
126 
127 static void
init_help_array(void)128 init_help_array(void)
129 {
130   RNAheat_args_info_help[0] = RNAheat_args_info_detailed_help[0];
131   RNAheat_args_info_help[1] = RNAheat_args_info_detailed_help[1];
132   RNAheat_args_info_help[2] = RNAheat_args_info_detailed_help[2];
133   RNAheat_args_info_help[3] = RNAheat_args_info_detailed_help[3];
134   RNAheat_args_info_help[4] = RNAheat_args_info_detailed_help[4];
135   RNAheat_args_info_help[5] = RNAheat_args_info_detailed_help[5];
136   RNAheat_args_info_help[6] = RNAheat_args_info_detailed_help[6];
137   RNAheat_args_info_help[7] = RNAheat_args_info_detailed_help[7];
138   RNAheat_args_info_help[8] = RNAheat_args_info_detailed_help[8];
139   RNAheat_args_info_help[9] = RNAheat_args_info_detailed_help[9];
140   RNAheat_args_info_help[10] = RNAheat_args_info_detailed_help[10];
141   RNAheat_args_info_help[11] = RNAheat_args_info_detailed_help[11];
142   RNAheat_args_info_help[12] = RNAheat_args_info_detailed_help[15];
143   RNAheat_args_info_help[13] = RNAheat_args_info_detailed_help[17];
144   RNAheat_args_info_help[14] = RNAheat_args_info_detailed_help[19];
145   RNAheat_args_info_help[15] = RNAheat_args_info_detailed_help[27];
146   RNAheat_args_info_help[16] = RNAheat_args_info_detailed_help[28];
147   RNAheat_args_info_help[17] = RNAheat_args_info_detailed_help[29];
148   RNAheat_args_info_help[18] = RNAheat_args_info_detailed_help[30];
149   RNAheat_args_info_help[19] = RNAheat_args_info_detailed_help[31];
150   RNAheat_args_info_help[20] = RNAheat_args_info_detailed_help[32];
151   RNAheat_args_info_help[21] = RNAheat_args_info_detailed_help[34];
152   RNAheat_args_info_help[22] = RNAheat_args_info_detailed_help[36];
153   RNAheat_args_info_help[23] = RNAheat_args_info_detailed_help[37];
154   RNAheat_args_info_help[24] = RNAheat_args_info_detailed_help[38];
155   RNAheat_args_info_help[25] = RNAheat_args_info_detailed_help[43];
156   RNAheat_args_info_help[26] = RNAheat_args_info_detailed_help[44];
157   RNAheat_args_info_help[27] = RNAheat_args_info_detailed_help[45];
158   RNAheat_args_info_help[28] = 0;
159 
160 }
161 
162 const char *RNAheat_args_info_help[29];
163 
164 typedef enum {ARG_NO
165   , ARG_FLAG
166   , ARG_STRING
167   , ARG_INT
168   , ARG_LONG
169   , ARG_FLOAT
170 } RNAheat_cmdline_parser_arg_type;
171 
172 static
173 void clear_given (struct RNAheat_args_info *args_info);
174 static
175 void clear_args (struct RNAheat_args_info *args_info);
176 
177 static int
178 RNAheat_cmdline_parser_internal (int argc, char **argv, struct RNAheat_args_info *args_info,
179                         struct RNAheat_cmdline_parser_params *params, const char *additional_error);
180 
181 static int
182 RNAheat_cmdline_parser_required2 (struct RNAheat_args_info *args_info, const char *prog_name, const char *additional_error);
183 
184 static char *
185 gengetopt_strdup (const char *s);
186 
187 static
clear_given(struct RNAheat_args_info * args_info)188 void clear_given (struct RNAheat_args_info *args_info)
189 {
190   args_info->help_given = 0 ;
191   args_info->detailed_help_given = 0 ;
192   args_info->full_help_given = 0 ;
193   args_info->version_given = 0 ;
194   args_info->Tmin_given = 0 ;
195   args_info->Tmax_given = 0 ;
196   args_info->stepsize_given = 0 ;
197   args_info->ipoints_given = 0 ;
198   args_info->noconv_given = 0 ;
199   args_info->jobs_given = 0 ;
200   args_info->unordered_given = 0 ;
201   args_info->infile_given = 0 ;
202   args_info->auto_id_given = 0 ;
203   args_info->id_prefix_given = 0 ;
204   args_info->id_delim_given = 0 ;
205   args_info->id_digits_given = 0 ;
206   args_info->id_start_given = 0 ;
207   args_info->maxBPspan_given = 0 ;
208   args_info->noTetra_given = 0 ;
209   args_info->dangles_given = 0 ;
210   args_info->noLP_given = 0 ;
211   args_info->noGU_given = 0 ;
212   args_info->noClosingGU_given = 0 ;
213   args_info->paramFile_given = 0 ;
214   args_info->nsp_given = 0 ;
215   args_info->energyModel_given = 0 ;
216   args_info->gquad_given = 0 ;
217   args_info->circ_given = 0 ;
218 }
219 
220 static
clear_args(struct RNAheat_args_info * args_info)221 void clear_args (struct RNAheat_args_info *args_info)
222 {
223   FIX_UNUSED (args_info);
224   args_info->Tmin_arg = 0;
225   args_info->Tmin_orig = NULL;
226   args_info->Tmax_arg = 100;
227   args_info->Tmax_orig = NULL;
228   args_info->stepsize_arg = 1.;
229   args_info->stepsize_orig = NULL;
230   args_info->ipoints_arg = 2;
231   args_info->ipoints_orig = NULL;
232   args_info->noconv_flag = 0;
233   args_info->jobs_arg = 0;
234   args_info->jobs_orig = NULL;
235   args_info->unordered_flag = 0;
236   args_info->infile_arg = NULL;
237   args_info->infile_orig = NULL;
238   args_info->auto_id_flag = 0;
239   args_info->id_prefix_arg = gengetopt_strdup ("sequence");
240   args_info->id_prefix_orig = NULL;
241   args_info->id_delim_arg = gengetopt_strdup ("_");
242   args_info->id_delim_orig = NULL;
243   args_info->id_digits_arg = 4;
244   args_info->id_digits_orig = NULL;
245   args_info->id_start_arg = 1;
246   args_info->id_start_orig = NULL;
247   args_info->maxBPspan_arg = -1;
248   args_info->maxBPspan_orig = NULL;
249   args_info->noTetra_flag = 0;
250   args_info->dangles_arg = 2;
251   args_info->dangles_orig = NULL;
252   args_info->noLP_flag = 0;
253   args_info->noGU_flag = 0;
254   args_info->noClosingGU_flag = 0;
255   args_info->paramFile_arg = NULL;
256   args_info->paramFile_orig = NULL;
257   args_info->nsp_arg = NULL;
258   args_info->nsp_orig = NULL;
259   args_info->energyModel_orig = NULL;
260   args_info->gquad_flag = 0;
261   args_info->circ_flag = 0;
262 
263 }
264 
265 static
init_args_info(struct RNAheat_args_info * args_info)266 void init_args_info(struct RNAheat_args_info *args_info)
267 {
268   init_full_help_array();
269   init_help_array();
270   args_info->help_help = RNAheat_args_info_detailed_help[0] ;
271   args_info->detailed_help_help = RNAheat_args_info_detailed_help[1] ;
272   args_info->full_help_help = RNAheat_args_info_detailed_help[2] ;
273   args_info->version_help = RNAheat_args_info_detailed_help[3] ;
274   args_info->Tmin_help = RNAheat_args_info_detailed_help[6] ;
275   args_info->Tmax_help = RNAheat_args_info_detailed_help[7] ;
276   args_info->stepsize_help = RNAheat_args_info_detailed_help[8] ;
277   args_info->ipoints_help = RNAheat_args_info_detailed_help[9] ;
278   args_info->noconv_help = RNAheat_args_info_detailed_help[10] ;
279   args_info->jobs_help = RNAheat_args_info_detailed_help[11] ;
280   args_info->unordered_help = RNAheat_args_info_detailed_help[13] ;
281   args_info->infile_help = RNAheat_args_info_detailed_help[15] ;
282   args_info->infile_min = 0;
283   args_info->infile_max = 0;
284   args_info->auto_id_help = RNAheat_args_info_detailed_help[17] ;
285   args_info->id_prefix_help = RNAheat_args_info_detailed_help[19] ;
286   args_info->id_delim_help = RNAheat_args_info_detailed_help[21] ;
287   args_info->id_digits_help = RNAheat_args_info_detailed_help[23] ;
288   args_info->id_start_help = RNAheat_args_info_detailed_help[25] ;
289   args_info->maxBPspan_help = RNAheat_args_info_detailed_help[29] ;
290   args_info->noTetra_help = RNAheat_args_info_detailed_help[31] ;
291   args_info->dangles_help = RNAheat_args_info_detailed_help[32] ;
292   args_info->noLP_help = RNAheat_args_info_detailed_help[34] ;
293   args_info->noGU_help = RNAheat_args_info_detailed_help[36] ;
294   args_info->noClosingGU_help = RNAheat_args_info_detailed_help[37] ;
295   args_info->paramFile_help = RNAheat_args_info_detailed_help[38] ;
296   args_info->nsp_help = RNAheat_args_info_detailed_help[40] ;
297   args_info->energyModel_help = RNAheat_args_info_detailed_help[42] ;
298   args_info->gquad_help = RNAheat_args_info_detailed_help[43] ;
299   args_info->circ_help = RNAheat_args_info_detailed_help[44] ;
300 
301 }
302 
303 void
RNAheat_cmdline_parser_print_version(void)304 RNAheat_cmdline_parser_print_version (void)
305 {
306   printf ("%s %s\n",
307      (strlen(RNAHEAT_CMDLINE_PARSER_PACKAGE_NAME) ? RNAHEAT_CMDLINE_PARSER_PACKAGE_NAME : RNAHEAT_CMDLINE_PARSER_PACKAGE),
308      RNAHEAT_CMDLINE_PARSER_VERSION);
309 
310   if (strlen(RNAheat_args_info_versiontext) > 0)
311     printf("\n%s\n", RNAheat_args_info_versiontext);
312 }
313 
print_help_common(void)314 static void print_help_common(void)
315 {
316 	size_t len_purpose = strlen(RNAheat_args_info_purpose);
317 	size_t len_usage = strlen(RNAheat_args_info_usage);
318 
319 	if (len_usage > 0) {
320 		printf("%s\n", RNAheat_args_info_usage);
321 	}
322 	if (len_purpose > 0) {
323 		printf("%s\n", RNAheat_args_info_purpose);
324 	}
325 
326 	if (len_usage || len_purpose) {
327 		printf("\n");
328 	}
329 
330 	if (strlen(RNAheat_args_info_description) > 0) {
331 		printf("%s\n\n", RNAheat_args_info_description);
332 	}
333 }
334 
335 void
RNAheat_cmdline_parser_print_help(void)336 RNAheat_cmdline_parser_print_help (void)
337 {
338   int i = 0;
339   print_help_common();
340   while (RNAheat_args_info_help[i])
341     printf("%s\n", RNAheat_args_info_help[i++]);
342 }
343 
344 void
RNAheat_cmdline_parser_print_full_help(void)345 RNAheat_cmdline_parser_print_full_help (void)
346 {
347   int i = 0;
348   print_help_common();
349   while (RNAheat_args_info_full_help[i])
350     printf("%s\n", RNAheat_args_info_full_help[i++]);
351 }
352 
353 void
RNAheat_cmdline_parser_print_detailed_help(void)354 RNAheat_cmdline_parser_print_detailed_help (void)
355 {
356   int i = 0;
357   print_help_common();
358   while (RNAheat_args_info_detailed_help[i])
359     printf("%s\n", RNAheat_args_info_detailed_help[i++]);
360 }
361 
362 void
RNAheat_cmdline_parser_init(struct RNAheat_args_info * args_info)363 RNAheat_cmdline_parser_init (struct RNAheat_args_info *args_info)
364 {
365   clear_given (args_info);
366   clear_args (args_info);
367   init_args_info (args_info);
368 
369   args_info->inputs = 0;
370   args_info->inputs_num = 0;
371 }
372 
373 void
RNAheat_cmdline_parser_params_init(struct RNAheat_cmdline_parser_params * params)374 RNAheat_cmdline_parser_params_init(struct RNAheat_cmdline_parser_params *params)
375 {
376   if (params)
377     {
378       params->override = 0;
379       params->initialize = 1;
380       params->check_required = 1;
381       params->check_ambiguity = 0;
382       params->print_errors = 1;
383     }
384 }
385 
386 struct RNAheat_cmdline_parser_params *
RNAheat_cmdline_parser_params_create(void)387 RNAheat_cmdline_parser_params_create(void)
388 {
389   struct RNAheat_cmdline_parser_params *params =
390     (struct RNAheat_cmdline_parser_params *)malloc(sizeof(struct RNAheat_cmdline_parser_params));
391   RNAheat_cmdline_parser_params_init(params);
392   return params;
393 }
394 
395 static void
free_string_field(char ** s)396 free_string_field (char **s)
397 {
398   if (*s)
399     {
400       free (*s);
401       *s = 0;
402     }
403 }
404 
405 /** @brief generic value variable */
406 union generic_value {
407     int int_arg;
408     long long_arg;
409     float float_arg;
410     char *string_arg;
411     const char *default_string_arg;
412 };
413 
414 /** @brief holds temporary values for multiple options */
415 struct generic_list
416 {
417   union generic_value arg;
418   char *orig;
419   struct generic_list *next;
420 };
421 
422 /**
423  * @brief add a node at the head of the list
424  */
add_node(struct generic_list ** list)425 static void add_node(struct generic_list **list) {
426   struct generic_list *new_node = (struct generic_list *) malloc (sizeof (struct generic_list));
427   new_node->next = *list;
428   *list = new_node;
429   new_node->arg.string_arg = 0;
430   new_node->orig = 0;
431 }
432 
433 
434 static void
free_multiple_string_field(unsigned int len,char *** arg,char *** orig)435 free_multiple_string_field(unsigned int len, char ***arg, char ***orig)
436 {
437   unsigned int i;
438   if (*arg) {
439     for (i = 0; i < len; ++i)
440       {
441         free_string_field(&((*arg)[i]));
442         free_string_field(&((*orig)[i]));
443       }
444     free_string_field(&((*arg)[0])); /* free default string */
445 
446     free (*arg);
447     *arg = 0;
448     free (*orig);
449     *orig = 0;
450   }
451 }
452 
453 static void
RNAheat_cmdline_parser_release(struct RNAheat_args_info * args_info)454 RNAheat_cmdline_parser_release (struct RNAheat_args_info *args_info)
455 {
456   unsigned int i;
457   free_string_field (&(args_info->Tmin_orig));
458   free_string_field (&(args_info->Tmax_orig));
459   free_string_field (&(args_info->stepsize_orig));
460   free_string_field (&(args_info->ipoints_orig));
461   free_string_field (&(args_info->jobs_orig));
462   free_multiple_string_field (args_info->infile_given, &(args_info->infile_arg), &(args_info->infile_orig));
463   free_string_field (&(args_info->id_prefix_arg));
464   free_string_field (&(args_info->id_prefix_orig));
465   free_string_field (&(args_info->id_delim_arg));
466   free_string_field (&(args_info->id_delim_orig));
467   free_string_field (&(args_info->id_digits_orig));
468   free_string_field (&(args_info->id_start_orig));
469   free_string_field (&(args_info->maxBPspan_orig));
470   free_string_field (&(args_info->dangles_orig));
471   free_string_field (&(args_info->paramFile_arg));
472   free_string_field (&(args_info->paramFile_orig));
473   free_string_field (&(args_info->nsp_arg));
474   free_string_field (&(args_info->nsp_orig));
475   free_string_field (&(args_info->energyModel_orig));
476 
477 
478   for (i = 0; i < args_info->inputs_num; ++i)
479     free (args_info->inputs [i]);
480 
481   if (args_info->inputs_num)
482     free (args_info->inputs);
483 
484   clear_given (args_info);
485 }
486 
487 
488 static void
write_into_file(FILE * outfile,const char * opt,const char * arg,const char * values[])489 write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[])
490 {
491   FIX_UNUSED (values);
492   if (arg) {
493     fprintf(outfile, "%s=\"%s\"\n", opt, arg);
494   } else {
495     fprintf(outfile, "%s\n", opt);
496   }
497 }
498 
499 static void
write_multiple_into_file(FILE * outfile,int len,const char * opt,char ** arg,const char * values[])500 write_multiple_into_file(FILE *outfile, int len, const char *opt, char **arg, const char *values[])
501 {
502   int i;
503 
504   for (i = 0; i < len; ++i)
505     write_into_file(outfile, opt, (arg ? arg[i] : 0), values);
506 }
507 
508 int
RNAheat_cmdline_parser_dump(FILE * outfile,struct RNAheat_args_info * args_info)509 RNAheat_cmdline_parser_dump(FILE *outfile, struct RNAheat_args_info *args_info)
510 {
511   int i = 0;
512 
513   if (!outfile)
514     {
515       fprintf (stderr, "%s: cannot dump options to stream\n", RNAHEAT_CMDLINE_PARSER_PACKAGE);
516       return EXIT_FAILURE;
517     }
518 
519   if (args_info->help_given)
520     write_into_file(outfile, "help", 0, 0 );
521   if (args_info->detailed_help_given)
522     write_into_file(outfile, "detailed-help", 0, 0 );
523   if (args_info->full_help_given)
524     write_into_file(outfile, "full-help", 0, 0 );
525   if (args_info->version_given)
526     write_into_file(outfile, "version", 0, 0 );
527   if (args_info->Tmin_given)
528     write_into_file(outfile, "Tmin", args_info->Tmin_orig, 0);
529   if (args_info->Tmax_given)
530     write_into_file(outfile, "Tmax", args_info->Tmax_orig, 0);
531   if (args_info->stepsize_given)
532     write_into_file(outfile, "stepsize", args_info->stepsize_orig, 0);
533   if (args_info->ipoints_given)
534     write_into_file(outfile, "ipoints", args_info->ipoints_orig, 0);
535   if (args_info->noconv_given)
536     write_into_file(outfile, "noconv", 0, 0 );
537   if (args_info->jobs_given)
538     write_into_file(outfile, "jobs", args_info->jobs_orig, 0);
539   if (args_info->unordered_given)
540     write_into_file(outfile, "unordered", 0, 0 );
541   write_multiple_into_file(outfile, args_info->infile_given, "infile", args_info->infile_orig, 0);
542   if (args_info->auto_id_given)
543     write_into_file(outfile, "auto-id", 0, 0 );
544   if (args_info->id_prefix_given)
545     write_into_file(outfile, "id-prefix", args_info->id_prefix_orig, 0);
546   if (args_info->id_delim_given)
547     write_into_file(outfile, "id-delim", args_info->id_delim_orig, 0);
548   if (args_info->id_digits_given)
549     write_into_file(outfile, "id-digits", args_info->id_digits_orig, 0);
550   if (args_info->id_start_given)
551     write_into_file(outfile, "id-start", args_info->id_start_orig, 0);
552   if (args_info->maxBPspan_given)
553     write_into_file(outfile, "maxBPspan", args_info->maxBPspan_orig, 0);
554   if (args_info->noTetra_given)
555     write_into_file(outfile, "noTetra", 0, 0 );
556   if (args_info->dangles_given)
557     write_into_file(outfile, "dangles", args_info->dangles_orig, 0);
558   if (args_info->noLP_given)
559     write_into_file(outfile, "noLP", 0, 0 );
560   if (args_info->noGU_given)
561     write_into_file(outfile, "noGU", 0, 0 );
562   if (args_info->noClosingGU_given)
563     write_into_file(outfile, "noClosingGU", 0, 0 );
564   if (args_info->paramFile_given)
565     write_into_file(outfile, "paramFile", args_info->paramFile_orig, 0);
566   if (args_info->nsp_given)
567     write_into_file(outfile, "nsp", args_info->nsp_orig, 0);
568   if (args_info->energyModel_given)
569     write_into_file(outfile, "energyModel", args_info->energyModel_orig, 0);
570   if (args_info->gquad_given)
571     write_into_file(outfile, "gquad", 0, 0 );
572   if (args_info->circ_given)
573     write_into_file(outfile, "circ", 0, 0 );
574 
575 
576   i = EXIT_SUCCESS;
577   return i;
578 }
579 
580 int
RNAheat_cmdline_parser_file_save(const char * filename,struct RNAheat_args_info * args_info)581 RNAheat_cmdline_parser_file_save(const char *filename, struct RNAheat_args_info *args_info)
582 {
583   FILE *outfile;
584   int i = 0;
585 
586   outfile = fopen(filename, "w");
587 
588   if (!outfile)
589     {
590       fprintf (stderr, "%s: cannot open file for writing: %s\n", RNAHEAT_CMDLINE_PARSER_PACKAGE, filename);
591       return EXIT_FAILURE;
592     }
593 
594   i = RNAheat_cmdline_parser_dump(outfile, args_info);
595   fclose (outfile);
596 
597   return i;
598 }
599 
600 void
RNAheat_cmdline_parser_free(struct RNAheat_args_info * args_info)601 RNAheat_cmdline_parser_free (struct RNAheat_args_info *args_info)
602 {
603   RNAheat_cmdline_parser_release (args_info);
604 }
605 
606 /** @brief replacement of strdup, which is not standard */
607 char *
gengetopt_strdup(const char * s)608 gengetopt_strdup (const char *s)
609 {
610   char *result = 0;
611   if (!s)
612     return result;
613 
614   result = (char*)malloc(strlen(s) + 1);
615   if (result == (char*)0)
616     return (char*)0;
617   strcpy(result, s);
618   return result;
619 }
620 
621 static char *
get_multiple_arg_token(const char * arg)622 get_multiple_arg_token(const char *arg)
623 {
624   const char *tok;
625   char *ret;
626   size_t len, num_of_escape, i, j;
627 
628   if (!arg)
629     return 0;
630 
631   tok = strchr (arg, ',');
632   num_of_escape = 0;
633 
634   /* make sure it is not escaped */
635   while (tok)
636     {
637       if (*(tok-1) == '\\')
638         {
639           /* find the next one */
640           tok = strchr (tok+1, ',');
641           ++num_of_escape;
642         }
643       else
644         break;
645     }
646 
647   if (tok)
648     len = (size_t)(tok - arg + 1);
649   else
650     len = strlen (arg) + 1;
651 
652   len -= num_of_escape;
653 
654   ret = (char *) malloc (len);
655 
656   i = 0;
657   j = 0;
658   while (arg[i] && (j < len-1))
659     {
660       if (arg[i] == '\\' &&
661 	  arg[ i + 1 ] &&
662 	  arg[ i + 1 ] == ',')
663         ++i;
664 
665       ret[j++] = arg[i++];
666     }
667 
668   ret[len-1] = '\0';
669 
670   return ret;
671 }
672 
673 static const char *
get_multiple_arg_token_next(const char * arg)674 get_multiple_arg_token_next(const char *arg)
675 {
676   const char *tok;
677 
678   if (!arg)
679     return 0;
680 
681   tok = strchr (arg, ',');
682 
683   /* make sure it is not escaped */
684   while (tok)
685     {
686       if (*(tok-1) == '\\')
687         {
688           /* find the next one */
689           tok = strchr (tok+1, ',');
690         }
691       else
692         break;
693     }
694 
695   if (! tok || strlen(tok) == 1)
696     return 0;
697 
698   return tok+1;
699 }
700 
701 static int
702 check_multiple_option_occurrences(const char *prog_name, unsigned int option_given, unsigned int min, unsigned int max, const char *option_desc);
703 
704 int
check_multiple_option_occurrences(const char * prog_name,unsigned int option_given,unsigned int min,unsigned int max,const char * option_desc)705 check_multiple_option_occurrences(const char *prog_name, unsigned int option_given, unsigned int min, unsigned int max, const char *option_desc)
706 {
707   int error_occurred = 0;
708 
709   if (option_given && (min > 0 || max > 0))
710     {
711       if (min > 0 && max > 0)
712         {
713           if (min == max)
714             {
715               /* specific occurrences */
716               if (option_given != (unsigned int) min)
717                 {
718                   fprintf (stderr, "%s: %s option occurrences must be %d\n",
719                     prog_name, option_desc, min);
720                   error_occurred = 1;
721                 }
722             }
723           else if (option_given < (unsigned int) min
724                 || option_given > (unsigned int) max)
725             {
726               /* range occurrences */
727               fprintf (stderr, "%s: %s option occurrences must be between %d and %d\n",
728                 prog_name, option_desc, min, max);
729               error_occurred = 1;
730             }
731         }
732       else if (min > 0)
733         {
734           /* at least check */
735           if (option_given < min)
736             {
737               fprintf (stderr, "%s: %s option occurrences must be at least %d\n",
738                 prog_name, option_desc, min);
739               error_occurred = 1;
740             }
741         }
742       else if (max > 0)
743         {
744           /* at most check */
745           if (option_given > max)
746             {
747               fprintf (stderr, "%s: %s option occurrences must be at most %d\n",
748                 prog_name, option_desc, max);
749               error_occurred = 1;
750             }
751         }
752     }
753 
754   return error_occurred;
755 }
756 int
RNAheat_cmdline_parser(int argc,char ** argv,struct RNAheat_args_info * args_info)757 RNAheat_cmdline_parser (int argc, char **argv, struct RNAheat_args_info *args_info)
758 {
759   return RNAheat_cmdline_parser2 (argc, argv, args_info, 0, 1, 1);
760 }
761 
762 int
RNAheat_cmdline_parser_ext(int argc,char ** argv,struct RNAheat_args_info * args_info,struct RNAheat_cmdline_parser_params * params)763 RNAheat_cmdline_parser_ext (int argc, char **argv, struct RNAheat_args_info *args_info,
764                    struct RNAheat_cmdline_parser_params *params)
765 {
766   int result;
767   result = RNAheat_cmdline_parser_internal (argc, argv, args_info, params, 0);
768 
769   if (result == EXIT_FAILURE)
770     {
771       RNAheat_cmdline_parser_free (args_info);
772       exit (EXIT_FAILURE);
773     }
774 
775   return result;
776 }
777 
778 int
RNAheat_cmdline_parser2(int argc,char ** argv,struct RNAheat_args_info * args_info,int override,int initialize,int check_required)779 RNAheat_cmdline_parser2 (int argc, char **argv, struct RNAheat_args_info *args_info, int override, int initialize, int check_required)
780 {
781   int result;
782   struct RNAheat_cmdline_parser_params params;
783 
784   params.override = override;
785   params.initialize = initialize;
786   params.check_required = check_required;
787   params.check_ambiguity = 0;
788   params.print_errors = 1;
789 
790   result = RNAheat_cmdline_parser_internal (argc, argv, args_info, &params, 0);
791 
792   if (result == EXIT_FAILURE)
793     {
794       RNAheat_cmdline_parser_free (args_info);
795       exit (EXIT_FAILURE);
796     }
797 
798   return result;
799 }
800 
801 int
RNAheat_cmdline_parser_required(struct RNAheat_args_info * args_info,const char * prog_name)802 RNAheat_cmdline_parser_required (struct RNAheat_args_info *args_info, const char *prog_name)
803 {
804   int result = EXIT_SUCCESS;
805 
806   if (RNAheat_cmdline_parser_required2(args_info, prog_name, 0) > 0)
807     result = EXIT_FAILURE;
808 
809   if (result == EXIT_FAILURE)
810     {
811       RNAheat_cmdline_parser_free (args_info);
812       exit (EXIT_FAILURE);
813     }
814 
815   return result;
816 }
817 
818 int
RNAheat_cmdline_parser_required2(struct RNAheat_args_info * args_info,const char * prog_name,const char * additional_error)819 RNAheat_cmdline_parser_required2 (struct RNAheat_args_info *args_info, const char *prog_name, const char *additional_error)
820 {
821   int error_occurred = 0;
822   FIX_UNUSED (additional_error);
823 
824   /* checks for required options */
825   if (check_multiple_option_occurrences(prog_name, args_info->infile_given, args_info->infile_min, args_info->infile_max, "'--infile' ('-i')"))
826      error_occurred = 1;
827 
828 
829   /* checks for dependences among options */
830   if (args_info->unordered_given && ! args_info->jobs_given)
831     {
832       fprintf (stderr, "%s: '--unordered' option depends on option 'jobs'%s\n", prog_name, (additional_error ? additional_error : ""));
833       error_occurred = 1;
834     }
835 
836   return error_occurred;
837 }
838 
839 /*
840  * Extracted from the glibc source tree, version 2.3.6
841  *
842  * Licensed under the GPL as per the whole glibc source tree.
843  *
844  * This file was modified so that getopt_long can be called
845  * many times without risking previous memory to be spoiled.
846  *
847  * Modified by Andre Noll and Lorenzo Bettini for use in
848  * GNU gengetopt generated files.
849  *
850  */
851 
852 /*
853  * we must include anything we need since this file is not thought to be
854  * inserted in a file already using getopt.h
855  *
856  * Lorenzo
857  */
858 
859 struct option
860 {
861   const char *name;
862   /* has_arg can't be an enum because some compilers complain about
863      type mismatches in all the code that assumes it is an int.  */
864   int has_arg;
865   int *flag;
866   int val;
867 };
868 
869 /* This version of `getopt' appears to the caller like standard Unix `getopt'
870    but it behaves differently for the user, since it allows the user
871    to intersperse the options with the other arguments.
872 
873    As `getopt' works, it permutes the elements of ARGV so that,
874    when it is done, all the options precede everything else.  Thus
875    all application programs are extended to handle flexible argument order.
876 */
877 /*
878    If the field `flag' is not NULL, it points to a variable that is set
879    to the value given in the field `val' when the option is found, but
880    left unchanged if the option is not found.
881 
882    To have a long-named option do something other than set an `int' to
883    a compiled-in constant, such as set a value from `custom_optarg', set the
884    option's `flag' field to zero and its `val' field to a nonzero
885    value (the equivalent single-letter option character, if there is
886    one).  For long options that have a zero `flag' field, `getopt'
887    returns the contents of the `val' field.  */
888 
889 /* Names for the values of the `has_arg' field of `struct option'.  */
890 #ifndef no_argument
891 #define no_argument		0
892 #endif
893 
894 #ifndef required_argument
895 #define required_argument	1
896 #endif
897 
898 #ifndef optional_argument
899 #define optional_argument	2
900 #endif
901 
902 struct custom_getopt_data {
903 	/*
904 	 * These have exactly the same meaning as the corresponding global variables,
905 	 * except that they are used for the reentrant versions of getopt.
906 	 */
907 	int custom_optind;
908 	int custom_opterr;
909 	int custom_optopt;
910 	char *custom_optarg;
911 
912 	/* True if the internal members have been initialized.  */
913 	int initialized;
914 
915 	/*
916 	 * The next char to be scanned in the option-element in which the last option
917 	 * character we returned was found.  This allows us to pick up the scan where
918 	 * we left off.  If this is zero, or a null string, it means resume the scan by
919 	 * advancing to the next ARGV-element.
920 	 */
921 	char *nextchar;
922 
923 	/*
924 	 * Describe the part of ARGV that contains non-options that have been skipped.
925 	 * `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is
926 	 * the index after the last of them.
927 	 */
928 	int first_nonopt;
929 	int last_nonopt;
930 };
931 
932 /*
933  * the variables optarg, optind, opterr and optopt are renamed with
934  * the custom_ prefix so that they don't interfere with getopt ones.
935  *
936  * Moreover they're static so they are visible only from within the
937  * file where this very file will be included.
938  */
939 
940 /*
941  * For communication from `custom_getopt' to the caller.  When `custom_getopt' finds an
942  * option that takes an argument, the argument value is returned here.
943  */
944 static char *custom_optarg;
945 
946 /*
947  * Index in ARGV of the next element to be scanned.  This is used for
948  * communication to and from the caller and for communication between
949  * successive calls to `custom_getopt'.
950  *
951  * On entry to `custom_getopt', 1 means this is the first call; initialize.
952  *
953  * When `custom_getopt' returns -1, this is the index of the first of the non-option
954  * elements that the caller should itself scan.
955  *
956  * Otherwise, `custom_optind' communicates from one call to the next how much of ARGV
957  * has been scanned so far.
958  *
959  * 1003.2 says this must be 1 before any call.
960  */
961 static int custom_optind = 1;
962 
963 /*
964  * Callers store zero here to inhibit the error message for unrecognized
965  * options.
966  */
967 static int custom_opterr = 1;
968 
969 /*
970  * Set to an option character which was unrecognized.  This must be initialized
971  * on some systems to avoid linking in the system's own getopt implementation.
972  */
973 static int custom_optopt = '?';
974 
975 /*
976  * Exchange two adjacent subsequences of ARGV.  One subsequence is elements
977  * [first_nonopt,last_nonopt) which contains all the non-options that have been
978  * skipped so far.  The other is elements [last_nonopt,custom_optind), which contains
979  * all the options processed since those non-options were skipped.
980  * `first_nonopt' and `last_nonopt' are relocated so that they describe the new
981  * indices of the non-options in ARGV after they are moved.
982  */
exchange(char ** argv,struct custom_getopt_data * d)983 static void exchange(char **argv, struct custom_getopt_data *d)
984 {
985 	int bottom = d->first_nonopt;
986 	int middle = d->last_nonopt;
987 	int top = d->custom_optind;
988 	char *tem;
989 
990 	/*
991 	 * Exchange the shorter segment with the far end of the longer segment.
992 	 * That puts the shorter segment into the right place.  It leaves the
993 	 * longer segment in the right place overall, but it consists of two
994 	 * parts that need to be swapped next.
995 	 */
996 	while (top > middle && middle > bottom) {
997 		if (top - middle > middle - bottom) {
998 			/* Bottom segment is the short one.  */
999 			int len = middle - bottom;
1000 			int i;
1001 
1002 			/* Swap it with the top part of the top segment.  */
1003 			for (i = 0; i < len; i++) {
1004 				tem = argv[bottom + i];
1005 				argv[bottom + i] =
1006 					argv[top - (middle - bottom) + i];
1007 				argv[top - (middle - bottom) + i] = tem;
1008 			}
1009 			/* Exclude the moved bottom segment from further swapping.  */
1010 			top -= len;
1011 		} else {
1012 			/* Top segment is the short one.  */
1013 			int len = top - middle;
1014 			int i;
1015 
1016 			/* Swap it with the bottom part of the bottom segment.  */
1017 			for (i = 0; i < len; i++) {
1018 				tem = argv[bottom + i];
1019 				argv[bottom + i] = argv[middle + i];
1020 				argv[middle + i] = tem;
1021 			}
1022 			/* Exclude the moved top segment from further swapping.  */
1023 			bottom += len;
1024 		}
1025 	}
1026 	/* Update records for the slots the non-options now occupy.  */
1027 	d->first_nonopt += (d->custom_optind - d->last_nonopt);
1028 	d->last_nonopt = d->custom_optind;
1029 }
1030 
1031 /* Initialize the internal data when the first call is made.  */
custom_getopt_initialize(struct custom_getopt_data * d)1032 static void custom_getopt_initialize(struct custom_getopt_data *d)
1033 {
1034 	/*
1035 	 * Start processing options with ARGV-element 1 (since ARGV-element 0
1036 	 * is the program name); the sequence of previously skipped non-option
1037 	 * ARGV-elements is empty.
1038 	 */
1039 	d->first_nonopt = d->last_nonopt = d->custom_optind;
1040 	d->nextchar = NULL;
1041 	d->initialized = 1;
1042 }
1043 
1044 #define NONOPTION_P (argv[d->custom_optind][0] != '-' || argv[d->custom_optind][1] == '\0')
1045 
1046 /* return: zero: continue, nonzero: return given value to user */
shuffle_argv(int argc,char * const * argv,const struct option * longopts,struct custom_getopt_data * d)1047 static int shuffle_argv(int argc, char *const *argv,const struct option *longopts,
1048 	struct custom_getopt_data *d)
1049 {
1050 	/*
1051 	 * Give FIRST_NONOPT & LAST_NONOPT rational values if CUSTOM_OPTIND has been
1052 	 * moved back by the user (who may also have changed the arguments).
1053 	 */
1054 	if (d->last_nonopt > d->custom_optind)
1055 		d->last_nonopt = d->custom_optind;
1056 	if (d->first_nonopt > d->custom_optind)
1057 		d->first_nonopt = d->custom_optind;
1058 	/*
1059 	 * If we have just processed some options following some
1060 	 * non-options, exchange them so that the options come first.
1061 	 */
1062 	if (d->first_nonopt != d->last_nonopt &&
1063 			d->last_nonopt != d->custom_optind)
1064 		exchange((char **) argv, d);
1065 	else if (d->last_nonopt != d->custom_optind)
1066 		d->first_nonopt = d->custom_optind;
1067 	/*
1068 	 * Skip any additional non-options and extend the range of
1069 	 * non-options previously skipped.
1070 	 */
1071 	while (d->custom_optind < argc && NONOPTION_P)
1072 		d->custom_optind++;
1073 	d->last_nonopt = d->custom_optind;
1074 	/*
1075 	 * The special ARGV-element `--' means premature end of options.  Skip
1076 	 * it like a null option, then exchange with previous non-options as if
1077 	 * it were an option, then skip everything else like a non-option.
1078 	 */
1079 	if (d->custom_optind != argc && !strcmp(argv[d->custom_optind], "--")) {
1080 		d->custom_optind++;
1081 		if (d->first_nonopt != d->last_nonopt
1082 				&& d->last_nonopt != d->custom_optind)
1083 			exchange((char **) argv, d);
1084 		else if (d->first_nonopt == d->last_nonopt)
1085 			d->first_nonopt = d->custom_optind;
1086 		d->last_nonopt = argc;
1087 		d->custom_optind = argc;
1088 	}
1089 	/*
1090 	 * If we have done all the ARGV-elements, stop the scan and back over
1091 	 * any non-options that we skipped and permuted.
1092 	 */
1093 	if (d->custom_optind == argc) {
1094 		/*
1095 		 * Set the next-arg-index to point at the non-options that we
1096 		 * previously skipped, so the caller will digest them.
1097 		 */
1098 		if (d->first_nonopt != d->last_nonopt)
1099 			d->custom_optind = d->first_nonopt;
1100 		return -1;
1101 	}
1102 	/*
1103 	 * If we have come to a non-option and did not permute it, either stop
1104 	 * the scan or describe it to the caller and pass it by.
1105 	 */
1106 	if (NONOPTION_P) {
1107 		d->custom_optarg = argv[d->custom_optind++];
1108 		return 1;
1109 	}
1110 	/*
1111 	 * We have found another option-ARGV-element. Skip the initial
1112 	 * punctuation.
1113 	 */
1114 	d->nextchar = (argv[d->custom_optind] + 1 + (longopts != NULL && argv[d->custom_optind][1] == '-'));
1115 	return 0;
1116 }
1117 
1118 /*
1119  * Check whether the ARGV-element is a long option.
1120  *
1121  * If there's a long option "fubar" and the ARGV-element is "-fu", consider
1122  * that an abbreviation of the long option, just like "--fu", and not "-f" with
1123  * arg "u".
1124  *
1125  * This distinction seems to be the most useful approach.
1126  *
1127  */
check_long_opt(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * longind,int print_errors,struct custom_getopt_data * d)1128 static int check_long_opt(int argc, char *const *argv, const char *optstring,
1129 		const struct option *longopts, int *longind,
1130 		int print_errors, struct custom_getopt_data *d)
1131 {
1132 	char *nameend;
1133 	const struct option *p;
1134 	const struct option *pfound = NULL;
1135 	int exact = 0;
1136 	int ambig = 0;
1137 	int indfound = -1;
1138 	int option_index;
1139 
1140 	for (nameend = d->nextchar; *nameend && *nameend != '='; nameend++)
1141 		/* Do nothing.  */ ;
1142 
1143 	/* Test all long options for either exact match or abbreviated matches */
1144 	for (p = longopts, option_index = 0; p->name; p++, option_index++)
1145 		if (!strncmp(p->name, d->nextchar, nameend - d->nextchar)) {
1146 			if ((unsigned int) (nameend - d->nextchar)
1147 					== (unsigned int) strlen(p->name)) {
1148 				/* Exact match found.  */
1149 				pfound = p;
1150 				indfound = option_index;
1151 				exact = 1;
1152 				break;
1153 			} else if (pfound == NULL) {
1154 				/* First nonexact match found.  */
1155 				pfound = p;
1156 				indfound = option_index;
1157 			} else if (pfound->has_arg != p->has_arg
1158 					|| pfound->flag != p->flag
1159 					|| pfound->val != p->val)
1160 				/* Second or later nonexact match found.  */
1161 				ambig = 1;
1162 		}
1163 	if (ambig && !exact) {
1164 		if (print_errors) {
1165 			fprintf(stderr,
1166 				"%s: option `%s' is ambiguous\n",
1167 				argv[0], argv[d->custom_optind]);
1168 		}
1169 		d->nextchar += strlen(d->nextchar);
1170 		d->custom_optind++;
1171 		d->custom_optopt = 0;
1172 		return '?';
1173 	}
1174 	if (pfound) {
1175 		option_index = indfound;
1176 		d->custom_optind++;
1177 		if (*nameend) {
1178 			if (pfound->has_arg != no_argument)
1179 				d->custom_optarg = nameend + 1;
1180 			else {
1181 				if (print_errors) {
1182 					if (argv[d->custom_optind - 1][1] == '-') {
1183 						/* --option */
1184 						fprintf(stderr, "%s: option `--%s' doesn't allow an argument\n",
1185 							argv[0], pfound->name);
1186 					} else {
1187 						/* +option or -option */
1188 						fprintf(stderr, "%s: option `%c%s' doesn't allow an argument\n",
1189 							argv[0], argv[d->custom_optind - 1][0], pfound->name);
1190 					}
1191 
1192 				}
1193 				d->nextchar += strlen(d->nextchar);
1194 				d->custom_optopt = pfound->val;
1195 				return '?';
1196 			}
1197 		} else if (pfound->has_arg == required_argument) {
1198 			if (d->custom_optind < argc)
1199 				d->custom_optarg = argv[d->custom_optind++];
1200 			else {
1201 				if (print_errors) {
1202 					fprintf(stderr,
1203 						"%s: option `%s' requires an argument\n",
1204 						argv[0],
1205 						argv[d->custom_optind - 1]);
1206 				}
1207 				d->nextchar += strlen(d->nextchar);
1208 				d->custom_optopt = pfound->val;
1209 				return optstring[0] == ':' ? ':' : '?';
1210 			}
1211 		}
1212 		d->nextchar += strlen(d->nextchar);
1213 		if (longind != NULL)
1214 			*longind = option_index;
1215 		if (pfound->flag) {
1216 			*(pfound->flag) = pfound->val;
1217 			return 0;
1218 		}
1219 		return pfound->val;
1220 	}
1221 	/*
1222 	 * Can't find it as a long option.  If this is not getopt_long_only, or
1223 	 * the option starts with '--' or is not a valid short option, then
1224 	 * it's an error.  Otherwise interpret it as a short option.
1225 	 */
1226 	if (print_errors) {
1227 		if (argv[d->custom_optind][1] == '-') {
1228 			/* --option */
1229 			fprintf(stderr,
1230 				"%s: unrecognized option `--%s'\n",
1231 				argv[0], d->nextchar);
1232 		} else {
1233 			/* +option or -option */
1234 			fprintf(stderr,
1235 				"%s: unrecognized option `%c%s'\n",
1236 				argv[0], argv[d->custom_optind][0],
1237 				d->nextchar);
1238 		}
1239 	}
1240 	d->nextchar = (char *) "";
1241 	d->custom_optind++;
1242 	d->custom_optopt = 0;
1243 	return '?';
1244 }
1245 
check_short_opt(int argc,char * const * argv,const char * optstring,int print_errors,struct custom_getopt_data * d)1246 static int check_short_opt(int argc, char *const *argv, const char *optstring,
1247 		int print_errors, struct custom_getopt_data *d)
1248 {
1249 	char c = *d->nextchar++;
1250 	const char *temp = strchr(optstring, c);
1251 
1252 	/* Increment `custom_optind' when we start to process its last character.  */
1253 	if (*d->nextchar == '\0')
1254 		++d->custom_optind;
1255 	if (!temp || c == ':') {
1256 		if (print_errors)
1257 			fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c);
1258 
1259 		d->custom_optopt = c;
1260 		return '?';
1261 	}
1262 	if (temp[1] == ':') {
1263 		if (temp[2] == ':') {
1264 			/* This is an option that accepts an argument optionally.  */
1265 			if (*d->nextchar != '\0') {
1266 				d->custom_optarg = d->nextchar;
1267 				d->custom_optind++;
1268 			} else
1269 				d->custom_optarg = NULL;
1270 			d->nextchar = NULL;
1271 		} else {
1272 			/* This is an option that requires an argument.  */
1273 			if (*d->nextchar != '\0') {
1274 				d->custom_optarg = d->nextchar;
1275 				/*
1276 				 * If we end this ARGV-element by taking the
1277 				 * rest as an arg, we must advance to the next
1278 				 * element now.
1279 				 */
1280 				d->custom_optind++;
1281 			} else if (d->custom_optind == argc) {
1282 				if (print_errors) {
1283 					fprintf(stderr,
1284 						"%s: option requires an argument -- %c\n",
1285 						argv[0], c);
1286 				}
1287 				d->custom_optopt = c;
1288 				if (optstring[0] == ':')
1289 					c = ':';
1290 				else
1291 					c = '?';
1292 			} else
1293 				/*
1294 				 * We already incremented `custom_optind' once;
1295 				 * increment it again when taking next ARGV-elt
1296 				 * as argument.
1297 				 */
1298 				d->custom_optarg = argv[d->custom_optind++];
1299 			d->nextchar = NULL;
1300 		}
1301 	}
1302 	return c;
1303 }
1304 
1305 /*
1306  * Scan elements of ARGV for option characters given in OPTSTRING.
1307  *
1308  * If an element of ARGV starts with '-', and is not exactly "-" or "--",
1309  * then it is an option element.  The characters of this element
1310  * (aside from the initial '-') are option characters.  If `getopt'
1311  * is called repeatedly, it returns successively each of the option characters
1312  * from each of the option elements.
1313  *
1314  * If `getopt' finds another option character, it returns that character,
1315  * updating `custom_optind' and `nextchar' so that the next call to `getopt' can
1316  * resume the scan with the following option character or ARGV-element.
1317  *
1318  * If there are no more option characters, `getopt' returns -1.
1319  * Then `custom_optind' is the index in ARGV of the first ARGV-element
1320  * that is not an option.  (The ARGV-elements have been permuted
1321  * so that those that are not options now come last.)
1322  *
1323  * OPTSTRING is a string containing the legitimate option characters.
1324  * If an option character is seen that is not listed in OPTSTRING,
1325  * return '?' after printing an error message.  If you set `custom_opterr' to
1326  * zero, the error message is suppressed but we still return '?'.
1327  *
1328  * If a char in OPTSTRING is followed by a colon, that means it wants an arg,
1329  * so the following text in the same ARGV-element, or the text of the following
1330  * ARGV-element, is returned in `custom_optarg'.  Two colons mean an option that
1331  * wants an optional arg; if there is text in the current ARGV-element,
1332  * it is returned in `custom_optarg', otherwise `custom_optarg' is set to zero.
1333  *
1334  * If OPTSTRING starts with `-' or `+', it requests different methods of
1335  * handling the non-option ARGV-elements.
1336  * See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
1337  *
1338  * Long-named options begin with `--' instead of `-'.
1339  * Their names may be abbreviated as long as the abbreviation is unique
1340  * or is an exact match for some defined option.  If they have an
1341  * argument, it follows the option name in the same ARGV-element, separated
1342  * from the option name by a `=', or else the in next ARGV-element.
1343  * When `getopt' finds a long-named option, it returns 0 if that option's
1344  * `flag' field is nonzero, the value of the option's `val' field
1345  * if the `flag' field is zero.
1346  *
1347  * The elements of ARGV aren't really const, because we permute them.
1348  * But we pretend they're const in the prototype to be compatible
1349  * with other systems.
1350  *
1351  * LONGOPTS is a vector of `struct option' terminated by an
1352  * element containing a name which is zero.
1353  *
1354  * LONGIND returns the index in LONGOPT of the long-named option found.
1355  * It is only valid when a long-named option has been found by the most
1356  * recent call.
1357  *
1358  * Return the option character from OPTS just read.  Return -1 when there are
1359  * no more options.  For unrecognized options, or options missing arguments,
1360  * `custom_optopt' is set to the option letter, and '?' is returned.
1361  *
1362  * The OPTS string is a list of characters which are recognized option letters,
1363  * optionally followed by colons, specifying that that letter takes an
1364  * argument, to be placed in `custom_optarg'.
1365  *
1366  * If a letter in OPTS is followed by two colons, its argument is optional.
1367  * This behavior is specific to the GNU `getopt'.
1368  *
1369  * The argument `--' causes premature termination of argument scanning,
1370  * explicitly telling `getopt' that there are no more options.  If OPTS begins
1371  * with `--', then non-option arguments are treated as arguments to the option
1372  * '\0'.  This behavior is specific to the GNU `getopt'.
1373  */
1374 
getopt_internal_r(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * longind,struct custom_getopt_data * d)1375 static int getopt_internal_r(int argc, char *const *argv, const char *optstring,
1376 		const struct option *longopts, int *longind,
1377 		struct custom_getopt_data *d)
1378 {
1379 	int ret, print_errors = d->custom_opterr;
1380 
1381 	if (optstring[0] == ':')
1382 		print_errors = 0;
1383 	if (argc < 1)
1384 		return -1;
1385 	d->custom_optarg = NULL;
1386 
1387 	/*
1388 	 * This is a big difference with GNU getopt, since optind == 0
1389 	 * means initialization while here 1 means first call.
1390 	 */
1391 	if (d->custom_optind == 0 || !d->initialized) {
1392 		if (d->custom_optind == 0)
1393 			d->custom_optind = 1;	/* Don't scan ARGV[0], the program name.  */
1394 		custom_getopt_initialize(d);
1395 	}
1396 	if (d->nextchar == NULL || *d->nextchar == '\0') {
1397 		ret = shuffle_argv(argc, argv, longopts, d);
1398 		if (ret)
1399 			return ret;
1400 	}
1401 	if (longopts && (argv[d->custom_optind][1] == '-' ))
1402 		return check_long_opt(argc, argv, optstring, longopts,
1403 			longind, print_errors, d);
1404 	return check_short_opt(argc, argv, optstring, print_errors, d);
1405 }
1406 
custom_getopt_internal(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * longind)1407 static int custom_getopt_internal(int argc, char *const *argv, const char *optstring,
1408 	const struct option *longopts, int *longind)
1409 {
1410 	int result;
1411 	/* Keep a global copy of all internal members of d */
1412 	static struct custom_getopt_data d;
1413 
1414 	d.custom_optind = custom_optind;
1415 	d.custom_opterr = custom_opterr;
1416 	result = getopt_internal_r(argc, argv, optstring, longopts,
1417 		longind, &d);
1418 	custom_optind = d.custom_optind;
1419 	custom_optarg = d.custom_optarg;
1420 	custom_optopt = d.custom_optopt;
1421 	return result;
1422 }
1423 
custom_getopt_long(int argc,char * const * argv,const char * options,const struct option * long_options,int * opt_index)1424 static int custom_getopt_long (int argc, char *const *argv, const char *options,
1425 	const struct option *long_options, int *opt_index)
1426 {
1427 	return custom_getopt_internal(argc, argv, options, long_options,
1428 		opt_index);
1429 }
1430 
1431 
1432 static char *package_name = 0;
1433 
1434 /**
1435  * @brief updates an option
1436  * @param field the generic pointer to the field to update
1437  * @param orig_field the pointer to the orig field
1438  * @param field_given the pointer to the number of occurrence of this option
1439  * @param prev_given the pointer to the number of occurrence already seen
1440  * @param value the argument for this option (if null no arg was specified)
1441  * @param possible_values the possible values for this option (if specified)
1442  * @param default_value the default value (in case the option only accepts fixed values)
1443  * @param arg_type the type of this option
1444  * @param check_ambiguity @see RNAheat_cmdline_parser_params.check_ambiguity
1445  * @param override @see RNAheat_cmdline_parser_params.override
1446  * @param no_free whether to free a possible previous value
1447  * @param multiple_option whether this is a multiple option
1448  * @param long_opt the corresponding long option
1449  * @param short_opt the corresponding short option (or '-' if none)
1450  * @param additional_error possible further error specification
1451  */
1452 static
update_arg(void * field,char ** orig_field,unsigned int * field_given,unsigned int * prev_given,char * value,const char * possible_values[],const char * default_value,RNAheat_cmdline_parser_arg_type arg_type,int check_ambiguity,int override,int no_free,int multiple_option,const char * long_opt,char short_opt,const char * additional_error)1453 int update_arg(void *field, char **orig_field,
1454                unsigned int *field_given, unsigned int *prev_given,
1455                char *value, const char *possible_values[],
1456                const char *default_value,
1457                RNAheat_cmdline_parser_arg_type arg_type,
1458                int check_ambiguity, int override,
1459                int no_free, int multiple_option,
1460                const char *long_opt, char short_opt,
1461                const char *additional_error)
1462 {
1463   char *stop_char = 0;
1464   const char *val = value;
1465   int found;
1466   char **string_field;
1467   FIX_UNUSED (field);
1468 
1469   stop_char = 0;
1470   found = 0;
1471 
1472   if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given)))
1473     {
1474       if (short_opt != '-')
1475         fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n",
1476                package_name, long_opt, short_opt,
1477                (additional_error ? additional_error : ""));
1478       else
1479         fprintf (stderr, "%s: `--%s' option given more than once%s\n",
1480                package_name, long_opt,
1481                (additional_error ? additional_error : ""));
1482       return 1; /* failure */
1483     }
1484 
1485   FIX_UNUSED (default_value);
1486 
1487   if (field_given && *field_given && ! override)
1488     return 0;
1489   if (prev_given)
1490     (*prev_given)++;
1491   if (field_given)
1492     (*field_given)++;
1493   if (possible_values)
1494     val = possible_values[found];
1495 
1496   switch(arg_type) {
1497   case ARG_FLAG:
1498     *((int *)field) = !*((int *)field);
1499     break;
1500   case ARG_INT:
1501     if (val) *((int *)field) = strtol (val, &stop_char, 0);
1502     break;
1503   case ARG_LONG:
1504     if (val) *((long *)field) = (long)strtol (val, &stop_char, 0);
1505     break;
1506   case ARG_FLOAT:
1507     if (val) *((float *)field) = (float)strtod (val, &stop_char);
1508     break;
1509   case ARG_STRING:
1510     if (val) {
1511       string_field = (char **)field;
1512       if (!no_free && *string_field)
1513         free (*string_field); /* free previous string */
1514       *string_field = gengetopt_strdup (val);
1515     }
1516     break;
1517   default:
1518     break;
1519   };
1520 
1521   /* check numeric conversion */
1522   switch(arg_type) {
1523   case ARG_INT:
1524   case ARG_LONG:
1525   case ARG_FLOAT:
1526     if (val && !(stop_char && *stop_char == '\0')) {
1527       fprintf(stderr, "%s: invalid numeric value: %s\n", package_name, val);
1528       return 1; /* failure */
1529     }
1530     break;
1531   default:
1532     ;
1533   };
1534 
1535   /* store the original value */
1536   switch(arg_type) {
1537   case ARG_NO:
1538   case ARG_FLAG:
1539     break;
1540   default:
1541     if (value && orig_field) {
1542       if (no_free) {
1543         *orig_field = value;
1544       } else {
1545         if (*orig_field)
1546           free (*orig_field); /* free previous string */
1547         *orig_field = gengetopt_strdup (value);
1548       }
1549     }
1550   };
1551 
1552   return 0; /* OK */
1553 }
1554 
1555 /**
1556  * @brief store information about a multiple option in a temporary list
1557  * @param list where to (temporarily) store multiple options
1558  */
1559 static
update_multiple_arg_temp(struct generic_list ** list,unsigned int * prev_given,const char * val,const char * possible_values[],const char * default_value,RNAheat_cmdline_parser_arg_type arg_type,const char * long_opt,char short_opt,const char * additional_error)1560 int update_multiple_arg_temp(struct generic_list **list,
1561                unsigned int *prev_given, const char *val,
1562                const char *possible_values[], const char *default_value,
1563                RNAheat_cmdline_parser_arg_type arg_type,
1564                const char *long_opt, char short_opt,
1565                const char *additional_error)
1566 {
1567   /* store single arguments */
1568   char *multi_token;
1569   const char *multi_next;
1570 
1571   if (arg_type == ARG_NO) {
1572     (*prev_given)++;
1573     return 0; /* OK */
1574   }
1575 
1576   multi_token = get_multiple_arg_token(val);
1577   multi_next = get_multiple_arg_token_next (val);
1578 
1579   while (1)
1580     {
1581       add_node (list);
1582       if (update_arg((void *)&((*list)->arg), &((*list)->orig), 0,
1583           prev_given, multi_token, possible_values, default_value,
1584           arg_type, 0, 1, 1, 1, long_opt, short_opt, additional_error)) {
1585         if (multi_token) free(multi_token);
1586         return 1; /* failure */
1587       }
1588 
1589       if (multi_next)
1590         {
1591           multi_token = get_multiple_arg_token(multi_next);
1592           multi_next = get_multiple_arg_token_next (multi_next);
1593         }
1594       else
1595         break;
1596     }
1597 
1598   return 0; /* OK */
1599 }
1600 
1601 /**
1602  * @brief free the passed list (including possible string argument)
1603  */
1604 static
free_list(struct generic_list * list,short string_arg)1605 void free_list(struct generic_list *list, short string_arg)
1606 {
1607   if (list) {
1608     struct generic_list *tmp;
1609     while (list)
1610       {
1611         tmp = list;
1612         if (string_arg && list->arg.string_arg)
1613           free (list->arg.string_arg);
1614         if (list->orig)
1615           free (list->orig);
1616         list = list->next;
1617         free (tmp);
1618       }
1619   }
1620 }
1621 
1622 /**
1623  * @brief updates a multiple option starting from the passed list
1624  */
1625 static
update_multiple_arg(void * field,char *** orig_field,unsigned int field_given,unsigned int prev_given,union generic_value * default_value,RNAheat_cmdline_parser_arg_type arg_type,struct generic_list * list)1626 void update_multiple_arg(void *field, char ***orig_field,
1627                unsigned int field_given, unsigned int prev_given, union generic_value *default_value,
1628                RNAheat_cmdline_parser_arg_type arg_type,
1629                struct generic_list *list)
1630 {
1631   int i;
1632   struct generic_list *tmp;
1633 
1634   if (prev_given && list) {
1635     *orig_field = (char **) realloc (*orig_field, (field_given + prev_given) * sizeof (char *));
1636 
1637     switch(arg_type) {
1638     case ARG_INT:
1639       *((int **)field) = (int *)realloc (*((int **)field), (field_given + prev_given) * sizeof (int)); break;
1640     case ARG_LONG:
1641       *((long **)field) = (long *)realloc (*((long **)field), (field_given + prev_given) * sizeof (long)); break;
1642     case ARG_FLOAT:
1643       *((float **)field) = (float *)realloc (*((float **)field), (field_given + prev_given) * sizeof (float)); break;
1644     case ARG_STRING:
1645       *((char ***)field) = (char **)realloc (*((char ***)field), (field_given + prev_given) * sizeof (char *)); break;
1646     default:
1647       break;
1648     };
1649 
1650     for (i = (prev_given - 1); i >= 0; --i)
1651       {
1652         tmp = list;
1653 
1654         switch(arg_type) {
1655         case ARG_INT:
1656           (*((int **)field))[i + field_given] = tmp->arg.int_arg; break;
1657         case ARG_LONG:
1658           (*((long **)field))[i + field_given] = tmp->arg.long_arg; break;
1659         case ARG_FLOAT:
1660           (*((float **)field))[i + field_given] = tmp->arg.float_arg; break;
1661         case ARG_STRING:
1662           (*((char ***)field))[i + field_given] = tmp->arg.string_arg; break;
1663         default:
1664           break;
1665         }
1666         (*orig_field) [i + field_given] = list->orig;
1667         list = list->next;
1668         free (tmp);
1669       }
1670   } else { /* set the default value */
1671     if (default_value && ! field_given) {
1672       switch(arg_type) {
1673       case ARG_INT:
1674         if (! *((int **)field)) {
1675           *((int **)field) = (int *)malloc (sizeof (int));
1676           (*((int **)field))[0] = default_value->int_arg;
1677         }
1678         break;
1679       case ARG_LONG:
1680         if (! *((long **)field)) {
1681           *((long **)field) = (long *)malloc (sizeof (long));
1682           (*((long **)field))[0] = default_value->long_arg;
1683         }
1684         break;
1685       case ARG_FLOAT:
1686         if (! *((float **)field)) {
1687           *((float **)field) = (float *)malloc (sizeof (float));
1688           (*((float **)field))[0] = default_value->float_arg;
1689         }
1690         break;
1691       case ARG_STRING:
1692         if (! *((char ***)field)) {
1693           *((char ***)field) = (char **)malloc (sizeof (char *));
1694           (*((char ***)field))[0] = gengetopt_strdup(default_value->string_arg);
1695         }
1696         break;
1697       default: break;
1698       }
1699       if (!(*orig_field)) {
1700         *orig_field = (char **) malloc (sizeof (char *));
1701         (*orig_field)[0] = 0;
1702       }
1703     }
1704   }
1705 }
1706 
1707 int
RNAheat_cmdline_parser_internal(int argc,char ** argv,struct RNAheat_args_info * args_info,struct RNAheat_cmdline_parser_params * params,const char * additional_error)1708 RNAheat_cmdline_parser_internal (
1709   int argc, char **argv, struct RNAheat_args_info *args_info,
1710                         struct RNAheat_cmdline_parser_params *params, const char *additional_error)
1711 {
1712   int c;	/* Character of the parsed option.  */
1713 
1714   struct generic_list * infile_list = NULL;
1715   int error_occurred = 0;
1716   struct RNAheat_args_info local_args_info;
1717 
1718   int override;
1719   int initialize;
1720   int check_required;
1721   int check_ambiguity;
1722 
1723   char *optarg;
1724   int optind;
1725   int opterr;
1726   int optopt;
1727 
1728   package_name = argv[0];
1729 
1730   /* TODO: Why is this here? It is not used anywhere. */
1731   override = params->override;
1732   FIX_UNUSED(override);
1733 
1734   initialize = params->initialize;
1735   check_required = params->check_required;
1736 
1737   /* TODO: Why is this here? It is not used anywhere. */
1738   check_ambiguity = params->check_ambiguity;
1739   FIX_UNUSED(check_ambiguity);
1740 
1741   if (initialize)
1742     RNAheat_cmdline_parser_init (args_info);
1743 
1744   RNAheat_cmdline_parser_init (&local_args_info);
1745 
1746   optarg = 0;
1747   optind = 0;
1748   opterr = params->print_errors;
1749   optopt = '?';
1750 
1751   while (1)
1752     {
1753       int option_index = 0;
1754 
1755       static struct option long_options[] = {
1756         { "help",	0, NULL, 'h' },
1757         { "detailed-help",	0, NULL, 0 },
1758         { "full-help",	0, NULL, 0 },
1759         { "version",	0, NULL, 'V' },
1760         { "Tmin",	1, NULL, 0 },
1761         { "Tmax",	1, NULL, 0 },
1762         { "stepsize",	1, NULL, 0 },
1763         { "ipoints",	1, NULL, 'm' },
1764         { "noconv",	0, NULL, 0 },
1765         { "jobs",	2, NULL, 'j' },
1766         { "unordered",	0, NULL, 0 },
1767         { "infile",	1, NULL, 'i' },
1768         { "auto-id",	0, NULL, 0 },
1769         { "id-prefix",	1, NULL, 0 },
1770         { "id-delim",	1, NULL, 0 },
1771         { "id-digits",	1, NULL, 0 },
1772         { "id-start",	1, NULL, 0 },
1773         { "maxBPspan",	1, NULL, 0 },
1774         { "noTetra",	0, NULL, '4' },
1775         { "dangles",	1, NULL, 'd' },
1776         { "noLP",	0, NULL, 0 },
1777         { "noGU",	0, NULL, 0 },
1778         { "noClosingGU",	0, NULL, 0 },
1779         { "paramFile",	1, NULL, 'P' },
1780         { "nsp",	1, NULL, 0 },
1781         { "energyModel",	1, NULL, 'e' },
1782         { "gquad",	0, NULL, 'g' },
1783         { "circ",	0, NULL, 'c' },
1784         { 0,  0, 0, 0 }
1785       };
1786 
1787       custom_optarg = optarg;
1788       custom_optind = optind;
1789       custom_opterr = opterr;
1790       custom_optopt = optopt;
1791 
1792       c = custom_getopt_long (argc, argv, "hVm:j::i:4d:P:e:gc", long_options, &option_index);
1793 
1794       optarg = custom_optarg;
1795       optind = custom_optind;
1796       opterr = custom_opterr;
1797       optopt = custom_optopt;
1798 
1799       if (c == -1) break;	/* Exit from `while (1)' loop.  */
1800 
1801       switch (c)
1802         {
1803         case 'h':	/* Print help and exit.  */
1804           RNAheat_cmdline_parser_print_help ();
1805           RNAheat_cmdline_parser_free (&local_args_info);
1806           exit (EXIT_SUCCESS);
1807 
1808         case 'V':	/* Print version and exit.  */
1809           RNAheat_cmdline_parser_print_version ();
1810           RNAheat_cmdline_parser_free (&local_args_info);
1811           exit (EXIT_SUCCESS);
1812 
1813         case 'm':	/* The program fits a parabola to 2*ipoints+1 data points to calculate 2nd derivatives. Increasing this parameter produces a smoother curve
1814 
1815 .  */
1816 
1817 
1818           if (update_arg( (void *)&(args_info->ipoints_arg),
1819                &(args_info->ipoints_orig), &(args_info->ipoints_given),
1820               &(local_args_info.ipoints_given), optarg, 0, "2", ARG_INT,
1821               check_ambiguity, override, 0, 0,
1822               "ipoints", 'm',
1823               additional_error))
1824             goto failure;
1825 
1826           break;
1827         case 'j':	/* Split batch input into jobs and start processing in parallel using multiple threads. A value of 0 indicates to use as many parallel threads as computation cores are available.
1828 .  */
1829 
1830 
1831           if (update_arg( (void *)&(args_info->jobs_arg),
1832                &(args_info->jobs_orig), &(args_info->jobs_given),
1833               &(local_args_info.jobs_given), optarg, 0, "0", ARG_INT,
1834               check_ambiguity, override, 0, 0,
1835               "jobs", 'j',
1836               additional_error))
1837             goto failure;
1838 
1839           break;
1840         case 'i':	/* Read a file instead of reading from stdin
1841 .  */
1842 
1843           if (update_multiple_arg_temp(&infile_list,
1844               &(local_args_info.infile_given), optarg, 0, 0, ARG_STRING,
1845               "infile", 'i',
1846               additional_error))
1847             goto failure;
1848 
1849           break;
1850         case '4':	/* Do not include special tabulated stabilizing energies for tri-, tetra- and hexaloop hairpins. Mostly for testing.
1851 
1852 .  */
1853 
1854 
1855           if (update_arg((void *)&(args_info->noTetra_flag), 0, &(args_info->noTetra_given),
1856               &(local_args_info.noTetra_given), optarg, 0, 0, ARG_FLAG,
1857               check_ambiguity, override, 1, 0, "noTetra", '4',
1858               additional_error))
1859             goto failure;
1860 
1861           break;
1862         case 'd':	/* How to treat \"dangling end\" energies for bases adjacent to helices in free ends and multi-loops
1863 .  */
1864 
1865 
1866           if (update_arg( (void *)&(args_info->dangles_arg),
1867                &(args_info->dangles_orig), &(args_info->dangles_given),
1868               &(local_args_info.dangles_given), optarg, 0, "2", ARG_INT,
1869               check_ambiguity, override, 0, 0,
1870               "dangles", 'd',
1871               additional_error))
1872             goto failure;
1873 
1874           break;
1875         case 'P':	/* Read energy parameters from paramfile, instead of using the default parameter set.
1876 .  */
1877 
1878 
1879           if (update_arg( (void *)&(args_info->paramFile_arg),
1880                &(args_info->paramFile_orig), &(args_info->paramFile_given),
1881               &(local_args_info.paramFile_given), optarg, 0, 0, ARG_STRING,
1882               check_ambiguity, override, 0, 0,
1883               "paramFile", 'P',
1884               additional_error))
1885             goto failure;
1886 
1887           break;
1888         case 'e':	/* Rarely used option to fold sequences from the artificial ABCD... alphabet, where A pairs B, C-D etc.  Use the energy parameters for GC (-e 1) or AU (-e 2) pairs.
1889 
1890 .  */
1891 
1892 
1893           if (update_arg( (void *)&(args_info->energyModel_arg),
1894                &(args_info->energyModel_orig), &(args_info->energyModel_given),
1895               &(local_args_info.energyModel_given), optarg, 0, 0, ARG_INT,
1896               check_ambiguity, override, 0, 0,
1897               "energyModel", 'e',
1898               additional_error))
1899             goto failure;
1900 
1901           break;
1902         case 'g':	/* Incoorporate G-Quadruplex formation into the structure prediction algorithm.
1903 
1904 .  */
1905 
1906 
1907           if (update_arg((void *)&(args_info->gquad_flag), 0, &(args_info->gquad_given),
1908               &(local_args_info.gquad_given), optarg, 0, 0, ARG_FLAG,
1909               check_ambiguity, override, 1, 0, "gquad", 'g',
1910               additional_error))
1911             goto failure;
1912 
1913           break;
1914         case 'c':	/* Assume a circular (instead of linear) RNA molecule.
1915 
1916 .  */
1917 
1918 
1919           if (update_arg((void *)&(args_info->circ_flag), 0, &(args_info->circ_given),
1920               &(local_args_info.circ_given), optarg, 0, 0, ARG_FLAG,
1921               check_ambiguity, override, 1, 0, "circ", 'c',
1922               additional_error))
1923             goto failure;
1924 
1925           break;
1926 
1927         case 0:	/* Long option with no short option */
1928           if (strcmp (long_options[option_index].name, "detailed-help") == 0) {
1929             RNAheat_cmdline_parser_print_detailed_help ();
1930             RNAheat_cmdline_parser_free (&local_args_info);
1931             exit (EXIT_SUCCESS);
1932           }
1933 
1934           if (strcmp (long_options[option_index].name, "full-help") == 0) {
1935             RNAheat_cmdline_parser_print_full_help ();
1936             RNAheat_cmdline_parser_free (&local_args_info);
1937             exit (EXIT_SUCCESS);
1938           }
1939 
1940           /* Lowest temperature
1941 
1942 .  */
1943           if (strcmp (long_options[option_index].name, "Tmin") == 0)
1944           {
1945 
1946 
1947             if (update_arg( (void *)&(args_info->Tmin_arg),
1948                  &(args_info->Tmin_orig), &(args_info->Tmin_given),
1949                 &(local_args_info.Tmin_given), optarg, 0, "0", ARG_FLOAT,
1950                 check_ambiguity, override, 0, 0,
1951                 "Tmin", '-',
1952                 additional_error))
1953               goto failure;
1954 
1955           }
1956           /* Highest temperature
1957 
1958 .  */
1959           else if (strcmp (long_options[option_index].name, "Tmax") == 0)
1960           {
1961 
1962 
1963             if (update_arg( (void *)&(args_info->Tmax_arg),
1964                  &(args_info->Tmax_orig), &(args_info->Tmax_given),
1965                 &(local_args_info.Tmax_given), optarg, 0, "100", ARG_FLOAT,
1966                 check_ambiguity, override, 0, 0,
1967                 "Tmax", '-',
1968                 additional_error))
1969               goto failure;
1970 
1971           }
1972           /* Calculate partition function every stepsize degrees C
1973 
1974 .  */
1975           else if (strcmp (long_options[option_index].name, "stepsize") == 0)
1976           {
1977 
1978 
1979             if (update_arg( (void *)&(args_info->stepsize_arg),
1980                  &(args_info->stepsize_orig), &(args_info->stepsize_given),
1981                 &(local_args_info.stepsize_given), optarg, 0, "1.", ARG_FLOAT,
1982                 check_ambiguity, override, 0, 0,
1983                 "stepsize", '-',
1984                 additional_error))
1985               goto failure;
1986 
1987           }
1988           /* Do not automatically substitude nucleotide \"T\" with \"U\"
1989 
1990 .  */
1991           else if (strcmp (long_options[option_index].name, "noconv") == 0)
1992           {
1993 
1994 
1995             if (update_arg((void *)&(args_info->noconv_flag), 0, &(args_info->noconv_given),
1996                 &(local_args_info.noconv_given), optarg, 0, 0, ARG_FLAG,
1997                 check_ambiguity, override, 1, 0, "noconv", '-',
1998                 additional_error))
1999               goto failure;
2000 
2001           }
2002           /* Do not try to keep output in order with input while parallel processing is in place.
2003 .  */
2004           else if (strcmp (long_options[option_index].name, "unordered") == 0)
2005           {
2006 
2007 
2008             if (update_arg((void *)&(args_info->unordered_flag), 0, &(args_info->unordered_given),
2009                 &(local_args_info.unordered_given), optarg, 0, 0, ARG_FLAG,
2010                 check_ambiguity, override, 1, 0, "unordered", '-',
2011                 additional_error))
2012               goto failure;
2013 
2014           }
2015           /* Automatically generate an ID for each sequence.
2016 .  */
2017           else if (strcmp (long_options[option_index].name, "auto-id") == 0)
2018           {
2019 
2020 
2021             if (update_arg((void *)&(args_info->auto_id_flag), 0, &(args_info->auto_id_given),
2022                 &(local_args_info.auto_id_given), optarg, 0, 0, ARG_FLAG,
2023                 check_ambiguity, override, 1, 0, "auto-id", '-',
2024                 additional_error))
2025               goto failure;
2026 
2027           }
2028           /* Prefix for automatically generated IDs (as used in output file names)
2029 
2030 .  */
2031           else if (strcmp (long_options[option_index].name, "id-prefix") == 0)
2032           {
2033 
2034 
2035             if (update_arg( (void *)&(args_info->id_prefix_arg),
2036                  &(args_info->id_prefix_orig), &(args_info->id_prefix_given),
2037                 &(local_args_info.id_prefix_given), optarg, 0, "sequence", ARG_STRING,
2038                 check_ambiguity, override, 0, 0,
2039                 "id-prefix", '-',
2040                 additional_error))
2041               goto failure;
2042 
2043           }
2044           /* Change the delimiter between prefix and increasing number for automatically generated IDs (as used in output file names)
2045 
2046 .  */
2047           else if (strcmp (long_options[option_index].name, "id-delim") == 0)
2048           {
2049 
2050 
2051             if (update_arg( (void *)&(args_info->id_delim_arg),
2052                  &(args_info->id_delim_orig), &(args_info->id_delim_given),
2053                 &(local_args_info.id_delim_given), optarg, 0, "_", ARG_STRING,
2054                 check_ambiguity, override, 0, 0,
2055                 "id-delim", '-',
2056                 additional_error))
2057               goto failure;
2058 
2059           }
2060           /* Specify the number of digits of the counter in automatically generated alignment IDs.
2061 .  */
2062           else if (strcmp (long_options[option_index].name, "id-digits") == 0)
2063           {
2064 
2065 
2066             if (update_arg( (void *)&(args_info->id_digits_arg),
2067                  &(args_info->id_digits_orig), &(args_info->id_digits_given),
2068                 &(local_args_info.id_digits_given), optarg, 0, "4", ARG_INT,
2069                 check_ambiguity, override, 0, 0,
2070                 "id-digits", '-',
2071                 additional_error))
2072               goto failure;
2073 
2074           }
2075           /* Specify the first number in automatically generated alignment IDs.
2076 .  */
2077           else if (strcmp (long_options[option_index].name, "id-start") == 0)
2078           {
2079 
2080 
2081             if (update_arg( (void *)&(args_info->id_start_arg),
2082                  &(args_info->id_start_orig), &(args_info->id_start_given),
2083                 &(local_args_info.id_start_given), optarg, 0, "1", ARG_LONG,
2084                 check_ambiguity, override, 0, 0,
2085                 "id-start", '-',
2086                 additional_error))
2087               goto failure;
2088 
2089           }
2090           /* Set the maximum base pair span
2091 
2092 .  */
2093           else if (strcmp (long_options[option_index].name, "maxBPspan") == 0)
2094           {
2095 
2096 
2097             if (update_arg( (void *)&(args_info->maxBPspan_arg),
2098                  &(args_info->maxBPspan_orig), &(args_info->maxBPspan_given),
2099                 &(local_args_info.maxBPspan_given), optarg, 0, "-1", ARG_INT,
2100                 check_ambiguity, override, 0, 0,
2101                 "maxBPspan", '-',
2102                 additional_error))
2103               goto failure;
2104 
2105           }
2106           /* Produce structures without lonely pairs (helices of length 1).
2107 .  */
2108           else if (strcmp (long_options[option_index].name, "noLP") == 0)
2109           {
2110 
2111 
2112             if (update_arg((void *)&(args_info->noLP_flag), 0, &(args_info->noLP_given),
2113                 &(local_args_info.noLP_given), optarg, 0, 0, ARG_FLAG,
2114                 check_ambiguity, override, 1, 0, "noLP", '-',
2115                 additional_error))
2116               goto failure;
2117 
2118           }
2119           /* Do not allow GU pairs
2120 
2121 .  */
2122           else if (strcmp (long_options[option_index].name, "noGU") == 0)
2123           {
2124 
2125 
2126             if (update_arg((void *)&(args_info->noGU_flag), 0, &(args_info->noGU_given),
2127                 &(local_args_info.noGU_given), optarg, 0, 0, ARG_FLAG,
2128                 check_ambiguity, override, 1, 0, "noGU", '-',
2129                 additional_error))
2130               goto failure;
2131 
2132           }
2133           /* Do not allow GU pairs at the end of helices
2134 
2135 .  */
2136           else if (strcmp (long_options[option_index].name, "noClosingGU") == 0)
2137           {
2138 
2139 
2140             if (update_arg((void *)&(args_info->noClosingGU_flag), 0, &(args_info->noClosingGU_given),
2141                 &(local_args_info.noClosingGU_given), optarg, 0, 0, ARG_FLAG,
2142                 check_ambiguity, override, 1, 0, "noClosingGU", '-',
2143                 additional_error))
2144               goto failure;
2145 
2146           }
2147           /* Allow other pairs in addition to the usual AU,GC,and GU pairs.
2148 .  */
2149           else if (strcmp (long_options[option_index].name, "nsp") == 0)
2150           {
2151 
2152 
2153             if (update_arg( (void *)&(args_info->nsp_arg),
2154                  &(args_info->nsp_orig), &(args_info->nsp_given),
2155                 &(local_args_info.nsp_given), optarg, 0, 0, ARG_STRING,
2156                 check_ambiguity, override, 0, 0,
2157                 "nsp", '-',
2158                 additional_error))
2159               goto failure;
2160 
2161           }
2162 
2163           break;
2164         case '?':	/* Invalid option.  */
2165           /* `getopt_long' already printed an error message.  */
2166           goto failure;
2167 
2168         default:	/* bug: option not considered.  */
2169           fprintf (stderr, "%s: option unknown: %c%s\n", RNAHEAT_CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : ""));
2170           abort ();
2171         } /* switch */
2172     } /* while */
2173 
2174 
2175   update_multiple_arg((void *)&(args_info->infile_arg),
2176     &(args_info->infile_orig), args_info->infile_given,
2177     local_args_info.infile_given, 0,
2178     ARG_STRING, infile_list);
2179 
2180   args_info->infile_given += local_args_info.infile_given;
2181   local_args_info.infile_given = 0;
2182 
2183   if (check_required)
2184     {
2185       error_occurred += RNAheat_cmdline_parser_required2 (args_info, argv[0], additional_error);
2186     }
2187 
2188   RNAheat_cmdline_parser_release (&local_args_info);
2189 
2190   if ( error_occurred )
2191     return (EXIT_FAILURE);
2192 
2193   if (optind < argc)
2194     {
2195       int i = 0 ;
2196       int found_prog_name = 0;
2197       /* whether program name, i.e., argv[0], is in the remaining args
2198          (this may happen with some implementations of getopt,
2199           but surely not with the one included by gengetopt) */
2200 
2201 
2202       args_info->inputs_num = argc - optind - found_prog_name;
2203       args_info->inputs =
2204         (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
2205       while (optind < argc)
2206         args_info->inputs[ i++ ] = gengetopt_strdup (argv[optind++]) ;
2207     }
2208 
2209   return 0;
2210 
2211 failure:
2212   free_list (infile_list, 1 );
2213 
2214   RNAheat_cmdline_parser_release (&local_args_info);
2215   return (EXIT_FAILURE);
2216 }
2217 /* vim: set ft=c noet ts=8 sts=8 sw=8 tw=80 nojs spell : */
2218