missing NULL terminator in set_config_x
[geda-gaf.git] / gschem / src / parsecmd.c
blob83d37fd32a1a51d20de124d0775013a209d78660
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2012 Ales Hvezda
4 * Copyright (C) 1998-2020 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #include <config.h>
21 #include <version.h>
23 #include <stdio.h>
24 #include <ctype.h>
25 #ifdef HAVE_UNISTD_H
26 #include <unistd.h>
27 #endif
29 #include "gschem.h"
31 #define GETOPT_OPTIONS "c:hL:o:pqr:s:vV"
33 #ifndef OPTARG_IN_UNISTD
34 extern char *optarg;
35 extern int optind;
36 #endif
38 #ifdef HAVE_GETOPT_H
39 #include <getopt.h>
40 #endif
42 #ifdef HAVE_GETOPT_LONG
43 struct option long_options[] =
45 {"help", 0, 0, 'h'},
46 {"version", 0, 0, 'V'},
47 {"quiet", 0, 0, 'q'},
48 {"verbose", 0, 0, 'v'},
49 {"config-file", 0, 0, 'r'},
50 {"output", 0, 0, 'o'},
51 {"control-fd", required_argument, NULL, -4},
52 {0, 0, 0, 0}
54 #endif
56 /*! Contains a Scheme expression arising from command-line arguments.
57 * This is evaluated after initialising gschem, but before loading
58 * any rc files. */
59 SCM s_pre_load_expr = SCM_EOL;
61 /*! Contains a Scheme expression arising from command-line arguments.
62 * This is evaluated after loading gschem and any schematic
63 * files specified on the command-line.
65 SCM s_post_load_expr = SCM_EOL;
67 /*! \brief Print brief help message and exit.
68 * \par Function Description
69 * Print brief help message describing gschem usage & command-line
70 * options, then exit with \a exit_status.
72 * \param cmd First element of argv (name of program as run).
74 static void
75 usage(char *cmd)
77 printf(_(
78 "Usage: %s [OPTION ...] [--] [FILE ...]\n"
79 "\n"
80 "Interactively edit gEDA schematics or symbols. If one or more FILEs\n"
81 "are specified, open them for editing; otherwise, create a new, empty\n"
82 "schematic.\n"
83 "\n"
84 "Options:\n"
85 " -q, --quiet Quiet mode.\n"
86 " -v, --verbose Verbose mode.\n"
87 " -r, --config-file=FILE Additional configuration file to load.\n"
88 " -L DIR Add DIR to Scheme search path.\n"
89 " -c EXPR Scheme expression to run at startup.\n"
90 " -s FILE Scheme script to run at startup.\n"
91 " -o, --output=FILE Output filename (for printing).\n"
92 " -p Automatically place the window.\n"
93 " --control-fd=stdin|FD Read control commands from file descriptor.\n"
94 " -V, --version Show version information.\n"
95 " -h, --help Help; this message.\n"
96 " -- Treat all remaining arguments as filenames.\n"
97 "\n"
98 "Report bugs at <https://bugs.launchpad.net/geda>\n"
99 "gEDA/gaf homepage: <http://www.geda-project.org/>\n"),
100 cmd);
101 exit(0);
104 /*! \brief Print version info and exit.
105 * \par Function Description
106 * Print gEDA version, and copyright/warranty notices, and exit with
107 * exit status 0.
109 static void
110 version ()
112 printf(_(
113 "gEDA %s (g%.7s)\n"
114 "Copyright (C) 1998-2020 gEDA developers\n"
115 "This is free software, and you are welcome to redistribute it under\n"
116 "certain conditions. For details, see the file `COPYING', which is\n"
117 "included in the gEDA distribution.\n"
118 "There is NO WARRANTY, to the extent permitted by law.\n"),
119 PACKAGE_DOTTED_VERSION, PACKAGE_GIT_COMMIT);
120 exit (0);
123 /*! \brief Parse gschem command-line options.
124 * \par Function Description
125 * Parse command line options, displaying usage message or version
126 * information as required.
128 * \param argc Number of command-line arguments.
129 * \param argv Array of command-line arguments.
130 * \return index into \a argv of first non-option argument.
133 parse_commandline(int argc, char *argv[])
135 int ch;
136 SCM sym_cons = scm_from_utf8_symbol ("cons");
137 SCM sym_set_x = scm_from_utf8_symbol ("set!");
138 SCM sym_load_path = scm_from_utf8_symbol ("%load-path");
139 SCM sym_begin = scm_from_utf8_symbol ("begin");
140 SCM sym_load = scm_from_utf8_symbol ("load");
141 SCM sym_eval_string = scm_from_utf8_symbol ("eval-string");
143 #ifdef HAVE_GETOPT_LONG
144 while ((ch = getopt_long (argc, argv, GETOPT_OPTIONS, long_options, NULL)) != -1) {
145 #else
146 while ((ch = getopt (argc, argv, GETOPT_OPTIONS)) != -1) {
147 #endif
148 switch (ch) {
149 case 'v':
150 verbose_mode = TRUE;
151 break;
153 case 'q':
154 quiet_mode = TRUE;
155 break;
157 case 'r':
158 rc_filename = g_strdup (optarg);
159 break;
161 case 's':
162 /* Argument is filename of a Scheme script to be run on gschem
163 * load. Add the necessary expression to be evaluated after
164 * loading. */
165 s_post_load_expr =
166 scm_cons (scm_list_2 (sym_load,
167 scm_from_locale_string (optarg)),
168 s_post_load_expr);
169 break;
171 case 'c':
172 /* Argument is a Scheme expression to be evaluated on gschem
173 * load. Add the necessary expression to be evaluated after
174 * loading. */
175 s_post_load_expr =
176 scm_cons (scm_list_2 (sym_eval_string,
177 scm_from_locale_string (optarg)),
178 s_post_load_expr);
179 break;
181 case 'o':
182 output_filename = g_strdup (optarg);
183 break;
185 case 'p':
186 auto_place_mode = TRUE;
187 break;
189 case 'L':
190 /* Argument is a directory to add to the Scheme load path.
191 * Add the necessary expression to be evaluated before rc file
192 * loading. */
193 s_pre_load_expr =
194 scm_cons (scm_list_3 (sym_set_x,
195 sym_load_path,
196 scm_list_3 (sym_cons,
197 scm_from_locale_string (optarg),
198 sym_load_path)),
199 s_pre_load_expr);
200 break;
202 case -4:
203 x_controlfd_parsearg (optarg);
204 break;
206 case 'h':
207 usage(argv[0]);
208 break;
210 case 'V':
211 version ();
212 break;
214 case '?':
215 #ifndef HAVE_GETOPT_LONG
216 if ((optopt != ':') && (strchr (GETOPT_OPTIONS, optopt) != NULL)) {
217 fprintf (stderr,
218 "ERROR: -%c option requires an argument.\n\n",
219 optopt);
220 } else if (isprint (optopt)) {
221 fprintf (stderr, "ERROR: Unknown option -%c.\n\n", optopt);
222 } else {
223 fprintf (stderr, "ERROR: Unknown option character `\\x%x'.\n\n",
224 optopt);
226 #endif
227 fprintf (stderr, "\nRun `%s --help' for more information.\n", argv[0]);
228 exit (1);
229 break;
230 default:
231 g_assert_not_reached ();
235 if (quiet_mode) {
236 verbose_mode = FALSE;
239 /* Make sure Scheme expressions can be passed straight to eval */
240 s_pre_load_expr = scm_cons (sym_begin,
241 scm_reverse_x (s_pre_load_expr, SCM_UNDEFINED));
242 scm_gc_protect_object (s_pre_load_expr);
243 s_post_load_expr = scm_cons (sym_begin,
244 scm_reverse_x (s_post_load_expr, SCM_UNDEFINED));
245 scm_gc_protect_object (s_post_load_expr);
246 return(optind);