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