Edinburgh Speech Tools 2.4-release
 
Loading...
Searching...
No Matches
cmd_line.cc
1/*************************************************************************/
2/* */
3/* Centre for Speech Technology Research */
4/* University of Edinburgh, UK */
5/* Copyright (c) 1994,1995,1996 */
6/* All Rights Reserved. */
7/* */
8/* Permission is hereby granted, free of charge, to use and distribute */
9/* this software and its documentation without restriction, including */
10/* without limitation the rights to use, copy, modify, merge, publish, */
11/* distribute, sublicense, and/or sell copies of this work, and to */
12/* permit persons to whom this work is furnished to do so, subject to */
13/* the following conditions: */
14/* 1. The code must retain the above copyright notice, this list of */
15/* conditions and the following disclaimer. */
16/* 2. Any modifications must be clearly marked as such. */
17/* 3. Original authors' names are not deleted. */
18/* 4. The authors' names are not used to endorse or promote products */
19/* derived from this software without specific prior written */
20/* permission. */
21/* */
22/* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23/* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24/* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25/* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26/* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27/* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28/* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29/* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30/* THIS SOFTWARE. */
31/* */
32/*************************************************************************/
33/* Author : Paul Taylor */
34/* Date : October 1994 */
35/*-----------------------------------------------------------------------*/
36/* Command Line Utilities */
37/* */
38/* awb merged the help usage and argument definitions April 97 */
39/* */
40/*=======================================================================*/
41#include <cstdlib>
42#include "EST_unix.h"
43#include "EST_String.h"
44#include "EST_io_aux.h"
45#include "EST_Token.h"
46#include "EST_cutils.h"
47#include "EST_TList.h"
48#include "EST_string_aux.h"
49#include "EST_cmd_line.h"
50#include "EST_Pathname.h"
51#include "EST_Features.h"
52
53// This is reset by the command line options functions to argv[0]
54EST_String est_progname = "ESTtools";
55
56static int valid_option(const EST_Option &option,const char *arg,
58static void standard_options(int argc, char **argv, const EST_String &usage);
59static void arg_error(const EST_String &progname, const EST_String &message);
60static void parse_usage(const EST_String &progname, const EST_String &usage,
62static void output_man_options(const EST_String &usage);
63static void output_sgml_options(const EST_String &usage);
64static void output_sgml_synopsis(char **argv, const EST_String &usage);
65
66int init_lib_ops(EST_Option &al, EST_Option &op)
67{
68 char *envname;
69
70 // read environment variable operations file if specified
71 if ((al.val("-N", 0) != "true") &&
72 ((envname = getenv("IA_OP_FILE")) != 0))
73 if (op.load(getenv("IA_OP_FILE")) != read_ok)
74 exit (1);
75
76 // read command line operations file if specified
77 if (al.val("-c", 0) != "")
78 if (op.load(al.val("-c")) != read_ok)
79 exit (1);
80
81 // override operations with command line options
82 override_lib_ops(op, al);
83
84 if (al.val("-ops", 0) == "true") // print options if required
85 cout << op;
86
87 return 0;
88}
89
90// An attempt to integrate help, usage and argument definitions in
91// one string (seems to work)
92// Still to do:
93// * adding arbitrary "-" at end of files (do we need that?)
94// dealing with environment var specification of extra options
95// override options function (maybe no longer needed)
96// list of named values for argument
97// Way to identify mandatory arguments
98int parse_command_line(int argc,
99 char *argv[],
100 const EST_String &usage,
103{
104 // Parse the command line arguments returning them in a normalised
105 // form in al, and files in files.
106 int i;
110
111 // help, version, man_options are always supported
112 standard_options(argc,argv,usage);
113
114 // Find valid options, arguments and defaults
115 // sets defaults in al
116 est_progname = argv[0];
117 parse_usage(argv[0],usage,options,al);
118
119 for (i=1; i < argc; i++)
120 {
121 if (!EST_String(argv[i]).contains("-",0)) // its a filename
122 files.append(argv[i]);
123 else if (streq(argv[i],"-")) // single "-" denotes stdin/out
124 files.append("-");
125 else if (!valid_option(options,argv[i],arg))
126 {
127 arg_error(argv[0],
128 EST_String(": Unknown option \"")+argv[i]+"\"\n");
129 }
130 else // valid option, check args
131 {
132 if (options.val(arg) == "true") // no argument required
133 al.add_item(arg, "true");
134 else if (options.val(arg) == "<int>")
135 {
136 if (i+1 == argc)
137 arg_error(argv[0],
138 EST_String(": missing int argument for \"")+
139 arg+"\"\n");
140 i++;
141 if (!EST_String(argv[i]).matches(RXint))
142 arg_error(argv[0],
143 EST_String(": argument for \"")+
144 arg+"\" not an int\n");
145 al.add_item(arg,argv[i]);
146 }
147 else if ((options.val(arg) == "<float>") ||
148 (options.val(arg) == "<double>"))
149 {
150 if (i+1 == argc)
151 arg_error(argv[0],
152 EST_String(": missing float argument for \"")+
153 arg+"\"\n");
154 i++;
155 if (!EST_String(argv[i]).matches(RXdouble))
156 arg_error(argv[0],
157 EST_String(": argument for \"")+
158 arg+"\" not a float\n");
159 al.add_item(arg,argv[i]);
160 }
161 else if (options.val(arg) == "<string>")
162 {
163 if (i+1 == argc)
164 arg_error(argv[0],
165 EST_String(": missing string argument for \"")+
166 arg+"\"\n");
167 i++;
168 al.add_item(arg,argv[i]);
169 }
170 else if (options.val(arg) == "<ofile>")
171 {
172 if (i+1 == argc)
173 arg_error(argv[0],
174 EST_String(": missing ifile argument for \"")+
175 arg+"\"\n");
176 i++;
177 if (writable_file(argv[i]) == TRUE)
178 al.add_item(arg,argv[i]);
179 else
180 arg_error(argv[0],
181 EST_String(": output file not accessible \"")+
182 argv[i]+"\"\n");
183 }
184 else if (options.val(arg) == "<ifile>")
185 {
186 if (i+1 == argc)
187 arg_error(argv[0],
188 EST_String(": missing ifile argument for \"")+
189 arg+"\"\n");
190 i++;
191 if (readable_file(argv[i]) == TRUE)
192 al.add_item(arg,argv[i]);
193 else
194 arg_error(argv[0],
195 EST_String(": input file not accessible \"")+
196 argv[i]+"\"\n");
197
198 }
199 else if (options.val(arg) == "<star>")
200 {
201 al.add_item(arg,EST_String(argv[i]).after(arg));
202 }
203 // else string list
204 else
205 {
206 arg_error(argv[0],
207 EST_String(": unknown argument type \"")+
208 options.val(argv[i])+"\" (misparsed usage string)\n");
209 }
210 }
211 }
212
213 if (files.length() == 0)
214 files.append("-");
215
216 return 0;
217}
218
219static int valid_option(const EST_Option &options,const char *arg,
221{
222 // Checks to see arg is declared as an option.
223 // This would be trivial were it not for options containing *
224 // The actual arg name is put in sarg
225 EST_Litem *p;
226
227 for (p = options.list.head(); p != 0; p = p->next())
228 {
229 if (options.key(p) == arg)
230 {
231 sarg = arg;
232 return TRUE;
233 }
234 else if ((options.val(p) == "<star>") &&
235 (EST_String(arg).contains(options.key(p), 0)))
236 {
237 sarg = options.key(p);
238 return TRUE;
239 }
240 }
241
242 return FALSE;
243}
244
245static void parse_usage(const EST_String &progname, const EST_String &usage,
247{
248 // Extract option definitions from usage and put them in options
249 // If defaults are specified add them al
251 EST_Token t;
252
253 ts.open_string(usage);
254 ts.set_SingleCharSymbols("{}[]|");
255 ts.set_PunctuationSymbols("");
256 ts.set_PrePunctuationSymbols("");
257
258 while (!ts.eof())
259 {
260 t = ts.get();
261 if ((t.string().contains("-",0)) &&
262 (t.whitespace().contains("\n")))
263 { // An argument
264 if ((ts.peek().string() == "<string>") ||
265 (ts.peek().string() == "<float>") ||
266 (ts.peek().string() == "<double>") ||
267 (ts.peek().string() == "<ifile>") ||
268 (ts.peek().string() == "<ofile>") ||
269 (ts.peek().string() == "<int>"))
270 {
271 options.add_item(t.string(),ts.get().string());
272 if (ts.peek().string() == "{") // a default is given
273 {
274 ts.get();
275 al.add_item(t.string(),ts.get().string());
276 if (ts.get() != "}")
277 arg_error(progname,
278 EST_String(": malformed default value for \"")+
279 t.string()+"\" (missing closing brace)\n");
280 }
281 }
282 else if (t.string().contains("*"))
283 options.add_item(t.string().before("*"),"<star>");
284 // else check for explicit list of names
285 else
286 options.add_item(t.string(),"true"); // simple argument
287 }
288 }
289}
290
291static void arg_error(const EST_String &progname, const EST_String &message)
292{
293 // Output message and pointer to more help then exit
294 cerr << progname << message;
295 cerr << "Type -h for help on options.\n";
296 exit(-1);
297}
298
299static void standard_options(int argc, char **argv, const EST_String &usage)
300{
301 // A number of options are always supported
302 int i;
303
304 for (i=1; i < argc; i++)
305 {
306 if (streq(argv[i],"-man_options"))
307 {
308 output_man_options(usage);
309 exit(0);
310 }
311 if (streq(argv[i],"-sgml_options"))
312 {
313 output_sgml_options(usage);
314 exit(0);
315 }
316 if (streq(argv[i],"-sgml_synopsis"))
317 {
318 output_sgml_synopsis(argv, usage);
319 exit(0);
320 }
321 if ((streq(argv[i],"-h")) ||
322 (streq(argv[i],"-help")) ||
323 (streq(argv[i],"-?")) ||
324 (streq(argv[i],"--help")))
325 {
327 cout << "Usage: " << full.filename() << " " << usage << endl;
328 exit(0);
329 }
330 if (((streq(argv[i],"-version")) ||
331 (streq(argv[i],"--version")))&&
332 (!usage.contains("\n-v")))
333 {
334 cout << argv[0] << ": " << est_name << " v" << est_tools_version << endl;
335 exit(0);
336 }
337 }
338
339 return;
340}
341
342static void output_man_options(const EST_String &usage)
343{
345 EST_Token t;
346 int in_options = FALSE;
347
348 ts.open_string(usage);
349 ts.set_SingleCharSymbols("{}[]|");
350 ts.set_PunctuationSymbols("");
351 ts.set_PrePunctuationSymbols("");
352
353 while (!ts.eof())
354 {
355 t = ts.get();
356 if ((t.string().contains("-",0)) &&
357 (t.whitespace().contains("\n")))
358 { // An argument
359 fprintf(stdout,"\n.TP 8\n.BI \"%s \" ",(const char *)t.string());
360 if ((ts.peek().string() == "<string>") ||
361 (ts.peek().string() == "<float>") ||
362 (ts.peek().string() == "<double>") ||
363 (ts.peek().string() == "<int>"))
364 fprintf(stdout,"%s",(const char *)ts.get().string());
365 if ((ts.peek().string() == "{"))
366 { // a default value
367 ts.get();
368 fprintf(stdout," \" {%s}\"",(const char *)ts.get().string());
369 ts.get();
370 }
371 if (!ts.peek().whitespace().contains("\n"))
372 fprintf(stdout,"\n");
373 in_options = TRUE;
374 }
375 else if (in_options)
376 {
377 if (t.whitespace().contains("\n"))
378 fprintf(stdout,"\n");
379 fprintf(stdout,"%s ",(const char *)t.string());
380 }
381 }
382 if (in_options)
383 fprintf(stdout,"\n");
384
385
386}
387
388static void output_sgml_options(const EST_String &usage)
389{
391 EST_Token t;
393 int in_options = FALSE;
394
395 ts.open_string(usage);
396 ts.set_SingleCharSymbols("{}[]|");
397 ts.set_PunctuationSymbols("");
398 ts.set_PrePunctuationSymbols("");
399
400 fprintf(stdout,"<variablelist>\n");
401
402 while (!ts.eof())
403 {
404 t = ts.get();
405 if ((t.string().contains("-",0)) &&
406 (t.whitespace().contains("\n")))
407 { // An argument
408 if (in_options)
409 fprintf(stdout,"\n</PARA></LISTITEM>\n</varlistentry>\n\n");
410 fprintf(stdout,"<varlistentry><term>%s</term>\n<LISTITEM><PARA>\n", (const char *)t.string());
411 if ((ts.peek().string() == "<string>") ||
412 (ts.peek().string() == "<float>") ||
413 (ts.peek().string() == "<ifile>") ||
414 (ts.peek().string() == "<ofile>") ||
415 (ts.peek().string() == "<double>") ||
416 (ts.peek().string() == "<int>"))
417 { // must strip of the angle brackets to make SGML
418 atype = ts.get().string();
419 atype.gsub("<","");
420 atype.gsub(">","");
421 fprintf(stdout,"<replaceable>%s</replaceable>\n",
422 (const char *) atype);
423 }
424 if ((ts.peek().string() == "{"))
425 { // a default value
426 ts.get();
427 fprintf(stdout," \" {%s}\"",(const char *)ts.get().string());
428 ts.get();
429 }
430 if (!ts.peek().whitespace().contains("\n"))
431 fprintf(stdout,"\n");
432 in_options = TRUE;
433 }
434 else if (in_options)
435 {
436 if (t.whitespace().contains("\n"))
437 fprintf(stdout,"\n");
438 fprintf(stdout,"%s ",(const char *)t.string());
439 }
440 }
441 if (in_options)
442 fprintf(stdout,"</PARA></LISTITEM>\n</varlistentry>\n</variablelist>\n");
443
444}
445
446static void output_sgml_synopsis(char **argv, const EST_String &usage)
447{
449 EST_Token t;
451 int in_options = FALSE;
452
453 ts.open_string(usage);
454 ts.set_SingleCharSymbols("{}[]|");
455 ts.set_PunctuationSymbols("");
456 ts.set_PrePunctuationSymbols("");
457
459
460 fprintf(stdout,"<cmdsynopsis><command>%s</command>",
461 (const char *)full.filename());
462
463 fprintf(stdout,"%s",(const char *)ts.get_upto_eoln().string());
464
465 while (!ts.eof())
466 {
467 t = ts.get();
468 if ((t.string().contains("-",0)) &&
469 (t.whitespace().contains("\n")))
470 { // An argument
471 if (in_options)
472 fprintf(stdout,"</arg>\n");
473 fprintf(stdout,"<arg>%s ", (const char *)t.string());
474 if ((ts.peek().string() == "<string>") ||
475 (ts.peek().string() == "<float>") ||
476 (ts.peek().string() == "<ifile>") ||
477 (ts.peek().string() == "<ofile>") ||
478 (ts.peek().string() == "<double>") ||
479 (ts.peek().string() == "<int>"))
480 { // must strip of the angle brackets to make SGML
481 atype = ts.get().string();
482 atype.gsub("<","");
483 atype.gsub(">","");
484 fprintf(stdout,"<replaceable>%s</replaceable>",
485 (const char *) atype);
486 }
487 if ((ts.peek().string() == "{"))
488 { // a default value
489 ts.get();
490 fprintf(stdout," \" {%s}\"",(const char *)ts.get().string());
491 ts.get();
492 }
493 in_options = TRUE;
494 }
495 }
496 fprintf(stdout,"</arg>\n</cmdsynopsis>\n");
497}
498
499EST_String options_general(void)
500{
501 // The standard waveform input options
502 return
503 EST_String("")+
504 "-o <ofile> output file" +
505 "-otype <string> output file type\n";
506}
507
508void option_override(EST_Features &op, EST_Option al,
509 const EST_String &option, const EST_String &arg)
510{
511 if (al.present(arg))
512 op.set(option, al.val(arg));
513}
514
void set(const EST_String &name, int ival)
EST_read_status load(const EST_String &filename, const EST_String &comment=";")
int contains(const char *s, int pos=-1) const
Does it contain this substring?
Definition EST_String.h:375