Skip to content
Snippets Groups Projects
Commit db3bf25b authored by Michael Tüxen's avatar Michael Tüxen
Browse files

Add support for defines as in Google version 2.0.

You can use -Dproto=IPPROTO_SCTP or --define proto=IPPROTO_SCTP
and run the script
```
 0.0 socket(..., SOCK_STREAM, proto) = 3
+0.0 close (3)
```
to control the protocol being used from the command line.
parent ae6cdf07
No related branches found
No related tags found
No related merge requests found
......@@ -58,13 +58,14 @@ enum option_codes {
OPT_TCP_TS_TICK_USECS,
OPT_NON_FATAL,
OPT_DRY_RUN,
OPT_VERBOSE = 'v', /* our only single-letter option */
OPT_DEBUG,
OPT_UDP_ENCAPS,
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
OPT_TUN_DEV,
OPT_PERSISTENT_TUN_DEV,
#endif
OPT_DEFINE = 'D', /* a '-D' single-letter option */
OPT_VERBOSE = 'v', /* a '-v' single-letter option */
};
/* Specification of command line options for getopt_long(). */
......@@ -92,6 +93,7 @@ struct option options[] = {
{ "tcp_ts_tick_usecs", .has_arg = true, NULL, OPT_TCP_TS_TICK_USECS },
{ "non_fatal", .has_arg = true, NULL, OPT_NON_FATAL },
{ "dry_run", .has_arg = false, NULL, OPT_DRY_RUN },
{ "define", .has_arg = true, NULL, OPT_DEFINE },
{ "verbose", .has_arg = false, NULL, OPT_VERBOSE },
{ "debug", .has_arg = false, NULL, OPT_DEBUG },
{ "udp_encapsulation", .has_arg = true, NULL, OPT_UDP_ENCAPS },
......@@ -128,6 +130,7 @@ void show_usage(void)
"\t[--wire_client_dev=<eth_dev_name>]\n"
"\t[--wire_server_dev=<eth_dev_name>]\n"
"\t[--dry_run]\n"
"\t[--define symbol1=val1 --define symbol2=val2 ...]\n"
"\t[--verbose|-v]\n"
"\t[--debug] * requires compilation with DEBUG *\n"
"\t[--udp_encapsulation=[sctp,tcp]]\n"
......@@ -391,7 +394,7 @@ static void process_option(int opt, char *optarg, struct config *config,
char *where)
{
int port = 0;
char *end = NULL;
char *end = NULL, *equals = NULL, *symbol = NULL, *value = NULL;
unsigned long speed = 0;
DEBUGP("process_option %d = %s\n", opt, optarg);
......@@ -494,6 +497,14 @@ static void process_option(int opt, char *optarg, struct config *config,
case OPT_DRY_RUN:
config->dry_run = true;
break;
case OPT_DEFINE:
equals = strstr(optarg, "=");
if (equals == optarg || equals == NULL)
die("%s: bad definition: %s\n", where, optarg);
symbol = strndup(optarg, equals - optarg);
value = strdup(equals + 1);
definition_set(&config->defines, symbol, value);
break;
case OPT_VERBOSE:
config->verbose = true;
break;
......@@ -550,7 +561,7 @@ char **parse_command_line_options(int argc, char *argv[],
/* Parse the arguments. */
optind = 0;
while ((c = getopt_long(argc, argv, "v", options, NULL)) > 0)
while ((c = getopt_long(argc, argv, "vD:", options, NULL)) > 0)
process_option(c, optarg, config, "Command Line");
return argv + optind;
}
......@@ -560,6 +571,7 @@ static void parse_script_options(struct config *config,
{
struct option_list *opt = option_list;
while (opt != NULL) {
printf("opt->name = %s\n", opt->name);
int i;
int c = 0;
for (i = 0; options[i].name != NULL; i++) {
......@@ -568,15 +580,21 @@ static void parse_script_options(struct config *config,
break;
}
}
if (c != 0) {
process_option(options[i].val,
opt->value, config,
config->script_path);
} else {
die("%s: option '%s' unknown in file: %s\n",
config->script_path, opt->name,
config->script_path);
}
if (!c)
die("%s: option '%s' unknown\n",
config->script_path, opt->name);
if (opt->value && !options[i].has_arg)
die("%s: option '%s' forbids an argument\n",
config->script_path, opt->name);
if (!opt->value && options[i].has_arg)
die("%s: option '%s' requires an argument\n",
config->script_path, opt->name);
process_option(options[i].val,
opt->value, config,
config->script_path);
opt = opt->next;
}
}
......
......@@ -40,6 +40,52 @@
extern struct option options[];
/* A linked list of symbol->value (FOO=bar) definitions from command line. */
struct definition {
char *symbol; /* name of the symbol; owns the string */
char *value; /* value of the symbol; owns the string */
struct definition *next; /* link for linked list */
};
/* Return the definition in the linked list with a matching symbol, or NULL */
static inline struct definition *definition_find(struct definition *defs,
char *symbol)
{
struct definition *def = NULL;
for (def = defs; def != NULL; def = def->next) {
if (strcmp(def->symbol, symbol) == 0)
return def;
}
return NULL;
}
/* Set the value of the given symbol to the given value. */
static inline void definition_set(struct definition **defs,
char *symbol, char *value)
{
struct definition *def = definition_find(*defs, symbol);
if (def) {
free(def->value);
def->value = value;
} else {
def = calloc(1, sizeof(struct definition));
def->symbol = symbol;
def->value = value;
def->next = *defs; /* link to existing entries */
*defs = def; /* insert at head of linked list */
}
}
/* Return the value of the given symbol, or NULL if not found. */
static inline char *definition_get(struct definition *defs, char *symbol)
{
struct definition *def = definition_find(defs, symbol);
return def ? def->value : NULL;
}
struct config {
const char **argv; /* a copy of process argv */
......@@ -112,6 +158,9 @@ struct config {
char *tun_device;
bool persistent_tun_device;
#endif
/* List of FOO=bar definitions from command line. */
struct definition *defines;
};
/* Top-level info about the invocation of a test script */
......
......@@ -49,6 +49,8 @@
#include <stdio.h>
#include "script.h"
#include "tcp_options.h"
#include "parse.h"
#include "config.h"
/* This include of the bison-generated .h file must go last so that we
* can first include all of the declarations on which it depends.
......@@ -75,6 +77,33 @@ static char *quoted(const char *s)
return strndup(s + delim_len, strlen(s) - 2*delim_len);
}
/* Check to see if the word in yytext is a user-defined symbol, and if so then
* return its value. Otherwise return the word itself.
*/
int word(void)
{
char *word = yytext;
char *value = NULL;
/* Look in symbol table for matching user-defined symbol->value map. */
value = definition_get(in_config->defines, word);
if (value) {
if (value[0] == '"') {
yylval.string = quoted(value); /* SYM="val" */
return STRING;
} else if (value[0] == '`') {
yylval.string = quoted(value); /* SYM=`val` */
return BACK_QUOTED;
} else {
yylval.string = strdup(value); /* SYM=val */
return WORD;
}
}
/* A literal word (e.g. system call name or socket option name). */
yylval.string = strdup(word);
return WORD;
}
/* Copy the code inside a code snippet that is enclosed in %{ }% after
* first stripping the space and tab characters from either end of the
* snippet. We strip leading and trailing whitespace for Python users
......@@ -655,7 +684,7 @@ NULL return NULL_;
[-]?[0-9]*[.][0-9]+ yylval.floating = atof(yytext); return FLOAT;
[-]?[0-9]+ yylval.integer = atoll(yytext); return INTEGER;
0x[0-9a-fA-F]+ yylval.integer = hextol(yytext); return HEX_INTEGER;
[a-zA-Z0-9_]+ yylval.string = strdup(yytext); return WORD;
[a-zA-Z0-9_]+ return word();
\"(\\.|[^"])*\" yylval.string = quoted(yytext); return STRING;
\`(\\.|[^`])*\` yylval.string = quoted(yytext); return BACK_QUOTED;
[^ \t\n] return (int) yytext[0];
......
......@@ -52,8 +52,11 @@ extern void read_script(const char *script_path,
* implementation for this function is in the bison parser file
* parser.y.
*/
extern int parse_script(const struct config *config,
extern int parse_script(struct config *config,
struct script *script,
struct invocation *callback_invocation);
/* Config for lexing and parsing. */
extern struct config *in_config;
#endif /* __PARSER_H__ */
......@@ -141,7 +141,7 @@ static int current_script_line = -1;
* We uses this object to look up configuration info needed during
* parsing (such as whether packets are IPv4 or IPv6).
*/
static const struct config *in_config = NULL;
struct config *in_config = NULL;
/* The output of the parser: an output script containing
* 1) a linked list of options
......@@ -228,9 +228,9 @@ void read_script(const char *script_path, struct script *script)
* text script file with the given path name and fills in the script
* object with the parsed representation.
*/
int parse_script(const struct config *config,
struct script *script,
struct invocation *callback_invocation)
int parse_script(struct config *config,
struct script *script,
struct invocation *callback_invocation)
{
/* This bison-generated parser is not multi-thread safe, so we
* have a lock to prevent more than one thread using the
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment