41# if defined (_XOPEN_UNIX)
42# include <sys/resource.h>
72# define _WIN32_WINNT 0x0500
75# if _WIN32_WINNT >= 0x0500
82 "Usage: %s [OPTIONS] [targets]\n"
84 " Treats each token in targets as the path to an executable. Each target\n"
85 " enumerated is executed, and the output is processed after termination.\n"
86 " If target prepended by '@' character, target is treated as text file\n"
87 " with list of targets (one target per line).\n"
88 " If the execution takes longer than a certain (configurable) amount of\n"
89 " time, the process is killed.\n"
91 " -d dir Specify root directory for output reference files.\n"
92 " -h, -? Display usage information and exit.\n"
93 " -t seconds Set timeout before killing target (default is 10\n"
95 " -x opts Specify command line options to pass to targets.\n"
96 " -- Terminate option processing and treat all arguments\n"
97 " that follow as targets.\n"
98 " --compat Use compatability mode test output parsing.\n"
99 " --nocompat Use standard test output parsing (default).\n"
100 " --help Display usage information and exit.\n"
101 " --exit=val Exit immediately with the specified return code.\n"
102 " --sleep=sec Sleep for the specified number of seconds.\n"
103 " --signal=sig Send itself the specified signal.\n"
104 " --ignore=sig Ignore the specified signal.\n"
105 " --ulimit=lim Set child process usage limits (see below).\n"
106 " --warn=alias Set compiler log warning pattern (see below).\n"
108 " All short (single dash) options must be specified seperately.\n"
109 " If a short option takes a value, it may either be provided like\n"
110 " '-sval' or '-s val'.\n"
111 " If a long option take a value, it may either be provided like\n"
112 " '--option=value' or '--option value'.\n"
114 " --ulimit sets limits on how much of a given resource or resorces\n"
115 " child processes are allowed to utilize. These limits take on two\n"
116 " forms, 'soft' and 'hard' limits. Options are specified in the form\n"
117 " 'resource:limit', where resource is a resource named below, and and\n"
118 " limit is a number, with value specifing the limit for the named\n"
119 " resource. If multiple limits are to be set, they can be specified\n"
120 " either in multiple instances of the --ulimit switch, or by specifying\n"
121 " additional limits in the same call by seperating the pairs with\n"
122 " commas. 'Soft' limits are specified by providing the resource name\n"
123 " in lowercase letters, while 'hard' limits are specified by providing\n"
124 " the resource name in uppercase letters. To set both limits, specify\n"
125 " the resource name in title case.\n"
128 " core Maximum size of core file, in bytes.\n"
129 " cpu Maximum CPU time, in seconds.\n"
130 " data Maximum data segment size, in bytes.\n"
131 " fsize Maximum size of generated files, in bytes.\n"
132 " nofile Maximum number of open file descriptors.\n"
133 " stack Maximum size of initial thread's stack, in bytes.\n"
134 " as Maximum size of available memory, in bytes.\n"
136 " Note: Some operating systems lack support for some or all of the\n"
137 " ulimit modes. If a system is unable to limit a given property, a\n"
138 " warning message will be produced.\n"
140 " --warn set the string used to parse compile and link logs. Rather\n"
141 " than specifying a search string, an alias code is provided,\n"
142 " coresponding to the output of a compiler and linker. Alias codes\n"
143 " are case sensitive.\n"
150 " icc Intel icc for Linux\n"
151 " mipspro SGI MIPSpro\n"
153 " vacpp IBM VisualAge C++\n"
164show_usage (
int status)
170 fprintf (where, usage_text,
exe_name);
182get_short_val (
char*
const* argv,
int* idx)
187 if (
'\0' == argv [*idx][2])
188 return argv [++(*idx)];
190 return argv [*idx] + 2;
201get_long_val (
char*
const* argv,
int* idx,
size_t offset)
206 if (
'\0' == argv [*idx][
offset])
207 return argv [++(*idx)];
208 else if (
'=' == argv [*idx][
offset])
209 return argv [*idx] +
offset + 1;
221parse_limit_opts (
const char* opts,
struct target_opts* defaults)
223 static const struct {
236 "core",
"CORE",
"Core", 4 },
243 "cpu",
"CPU",
"Cpu", 3 },
250 "data",
"DATA",
"Data", 4 },
257 "fsize",
"FSIZE",
"Fsize", 5 },
264 "nofile",
"NOFILE",
"Nofile", 6 },
271 "stack",
"STACK",
"Stack", 5 },
278 "as",
"AS",
"As", 2 },
282 const char*
arg = opts;
288 const size_t arglen = strlen (
arg);
290 for (
size_t i = 0; limits [
i].name; ++
i) {
291 if ( limits [
i].
len < arglen
293 || 0 == memcmp (limits [
i].caps,
arg, limits [
i].
len)
294 || 0 == memcmp (limits [
i].mixd,
arg, limits [
i].
len))
295 &&
':' ==
arg [limits [
i].
len]) {
299 const bool hard = 0 != isupper (
arg [0]);
300 const bool soft = 0 != islower (
arg [1]);
302 arg += limits [
i].len + 1;
304 if (!isdigit (*
arg)) {
309 const long lim = strtol (
arg, &end, 10);
313 if (
'\0' != *
arg &&
',' != *
arg)
316 if (limits [
i].limit) {
317 if (!*limits [
i].limit) {
318 (*limits [
i].limit) =
324 (*limits [
i].limit)->rlim_cur = lim;
327 (*limits [
i].limit)->rlim_max = lim;
330 warn (
"Unable to process %s limit: Not supported\n",
339 else if (
'\0' != *
arg) {
355 static const struct {
359 {
"acc",
"Warning " },
364 {
"cxx",
"Warning:"},
365 {
"eccp",
"warning:"},
366 {
"gcc",
"warning:"},
367 {
"icc",
"warning #"},
368 {
"mipspro",
"CC: WARNING"},
369 {
"sunpro",
"Warning:"},
370 {
"vacpp",
": (W) "},
378 for (
size_t i = 0; warn_set [
i].name; ++
i) {
379 if (0 == strcmp (warn_set [
i].
name,
arg)) {
382 defaults->
c_warn = warn_set [
i].pat;
383 defaults->
l_warn = warn_set [
i].pat;
399bad_value (
const char* opt,
const char*
val)
412missing_value (
const char* opt)
416 terminate (1,
"Missing argument for %s\n", opt);
425bad_option (
const char* opt)
429 warn (
"Unknown option: %s\n", opt);
436 const char** exe_opts)
439 const char opt_data_dir[] =
"-d";
440 const char opt_t_flags[] =
"-x";
441 const char opt_compat[] =
"--compat";
442 const char opt_exit[] =
"--exit";
443 const char opt_help[] =
"--help";
444 const char opt_ignore[] =
"--ignore";
445 const char opt_nocompat[] =
"--nocompat";
446 const char opt_signal[] =
"--signal";
447 const char opt_sleep[] =
"--sleep";
448 const char opt_ulimit[] =
"--ulimit";
449 const char opt_verbose[] =
"--verbose";
450 const char opt_warn[] =
"--warn";
463 parse_warn_opts (
"Gcc", defaults);
464#elif defined (__HP_aCC)
465 parse_warn_opts (
"Acc", defaults);
466#elif defined (__IBMCPP__)
467 parse_warn_opts (
"Xlc", defaults);
468#elif defined (__SUNPRO_CC)
469 parse_warn_opts (
"Sunpro", defaults);
471 parse_warn_opts (
"Cds", defaults);
472#elif defined (__APOGEE__)
473 parse_warn_opts (
"Como", defaults);
476#elif defined (__DECCXX)
477 parse_warn_opts (
"Cxx", defaults);
478#elif defined (_SGI_COMPILER_VERSION)
479 parse_warn_opts (
"Mipspro", defaults);
480#elif defined (__INTEL_COMPILER)
481 parse_warn_opts (
"Icc", defaults);
484#elif defined (__EDG__)
485 parse_warn_opts (
"Eccp", defaults);
488 if (1 == argc ||
'-' != argv [1][0])
491 for (
i = 1;
i < argc &&
'-' == argv [
i][0]; ++
i) {
494 const char* optname = argv [
i];
497 const char* optarg = 0;
501 switch (argv [
i][1]) {
512 optarg = get_short_val (argv, &
i);
514 if (!isdigit (*optarg))
515 bad_value (optname, optarg);
518 defaults->
timeout = unsigned (strtol (optarg, &
end, 10));
520 bad_value (optname, optarg);
523 missing_value (optname);
528 optname = opt_data_dir;
529 defaults->
data_dir = get_short_val (argv, &
i);
531 missing_value (optname);
535 optname = opt_verbose;
540 optname = opt_t_flags;
541 *exe_opts = get_short_val (argv, &
i);
543 missing_value (optname);
548 const size_t arglen = strlen (argv [
i]);
551 if (
'\0' == argv [
i][2])
554 if (
sizeof opt_compat - 1 == arglen
555 && !memcmp (opt_compat, argv [
i],
sizeof opt_compat)) {
560 else if (
sizeof opt_nocompat - 1 == arglen
561 && !memcmp (opt_nocompat, argv [
i],
sizeof opt_nocompat)) {
566 else if (
sizeof opt_exit - 1 <= arglen
567 && !memcmp (opt_exit, argv [
i],
sizeof opt_exit - 1)) {
570 optarg = get_long_val (argv, &
i,
sizeof opt_exit - 1);
571 if (optarg && *optarg) {
572 if (!isdigit (*optarg))
573 bad_value (optname, optarg);
576 const long code = strtol (optarg, &
end, 10);
577 if (
'\0' == *
end && !errno)
581 else if (
sizeof opt_help - 1 == arglen
582 && !memcmp (opt_help, argv [
i],
sizeof opt_help - 1)) {
588 else if (
sizeof opt_sleep - 1 <= arglen
589 && !memcmp (opt_sleep, argv [
i],
sizeof opt_sleep - 1)) {
592 optarg = get_long_val (argv, &
i,
sizeof opt_sleep - 1);
593 if (optarg && *optarg) {
594 if (!isdigit (*optarg))
595 bad_value (optname, optarg);
598 const long nsec = strtol (optarg, &
end, 10);
599 if (
'\0' == *
end && 0 <= nsec && !errno) {
605 else if (
sizeof opt_signal - 1 <= arglen
606 && !memcmp (opt_signal, argv [
i],
sizeof opt_signal - 1)) {
608 optname = opt_signal;
609 optarg = get_long_val (argv, &
i,
sizeof opt_signal - 1);
610 if (optarg && *optarg) {
613 if (0 > raise (signo))
620 else if (
sizeof opt_ignore - 1 <= arglen
621 && !memcmp (opt_ignore, argv [
i],
sizeof opt_ignore - 1)) {
623 optname = opt_ignore;
624 optarg = get_long_val (argv, &
i,
sizeof opt_ignore - 1);
625 if (optarg && *optarg) {
629 terminate (1,
"rw_signal(%s, ...) failed: %s\n",
635 else if (
sizeof opt_ulimit - 1 <= arglen
636 && !memcmp (opt_ulimit, argv [
i],
sizeof opt_ulimit - 1)) {
638 optname = opt_ulimit;
639 optarg = get_long_val (argv, &
i,
sizeof opt_ulimit - 1);
640 if (optarg && *optarg) {
641 if (!parse_limit_opts (optarg, defaults)) {
646 else if (
sizeof opt_warn - 1 <= arglen
647 && !memcmp (opt_warn, argv [
i],
sizeof opt_warn - 1)) {
650 optarg = get_long_val (argv, &
i,
sizeof opt_warn - 1);
651 if (optarg && *optarg) {
652 if (!parse_warn_opts (optarg, defaults)) {
662 bad_value (optname, optarg);
664 missing_value (optname);
668 bad_option (argv [
i]);
670 missing_value (optname);
685 char **table_pos, **argv;
690 optlen = strlen (opts);
694 argv = (
char**)
RW_MALLOC (
sizeof (
char*));
701 table_pos = argv = (
char**)
RW_MALLOC ((optlen + 3) *
sizeof (
char*) / 2);
717 if (isspace (*
pos)) {
724 *(table_pos++) =
last;
738 if (*
pos == in_quote) {
742 else if (0 == in_quote) {
756 *(table_pos++) =
last;
758 *table_pos = (
char*)0;
int get_signo(const char *signame)
const char * get_signame(int signo)
const size_t exe_suffix_len
char ** split_opt_string(const char *opts)
const char default_path_sep
int eval_options(int argc, char **argv, struct target_opts *defaults, const char **exe_opts)
void warn(const char *const format,...)
int rw_signal(int signo, void(*func)(int))
void rw_sleep(int seconds)