t = next_token();
if (t == TOK_CLOSE_PAREN)
break;
+
+ while (next_pos < num_args && !(adefs[next_pos].type & AT_POSITIONAL))
+ next_pos++;
+
uint argi = 0;
bool has_value = false;
+
if (t == TOK_IDENT)
{
while (adefs[argi].name && token != adefs[argi].name)
argi++;
- if (!adefs[argi].name)
- err("Command %s has no argument %s", cdef->name, token.c_str());
- if (c->args.count(token))
- err("Argument %s given multiple times", token.c_str());
- t = next_token();
- if (t == TOK_EQUAL)
- has_value = true;
+ if (adefs[argi].name)
+ {
+ if (c->args.count(token))
+ err("Argument %s given multiple times", token.c_str());
+ t = next_token();
+ if (t == TOK_EQUAL)
+ has_value = true;
+ else
+ return_token();
+ saw_named = true;
+ }
+ else if (next_pos < num_args && (adefs[next_pos].type & AT_TYPE_MASK) == AT_STRING)
+ {
+ // Shortcut syntax: positional arguments of string type can be specified
+ // as bare identifiers if they do not collide with names or other arguments.
+ return_token();
+ argi = next_pos++;
+ has_value = true;
+ }
else
- return_token();
- saw_named = true;
+ err("Command %s has no argument %s", cdef->name, token.c_str());
}
else if (saw_named)
err("Positional arguments must precede named ones");
- else
+ else if (next_pos < num_args)
{
return_token();
- while (next_pos < num_args && !(adefs[next_pos].type & AT_POSITIONAL))
- next_pos++;
- if (next_pos >= num_args)
- err("Too many positional arguments for command %s", cdef->name);
argi = next_pos++;
has_value = true;
}
+ else
+ err("Too many positional arguments for command %s", cdef->name);
const arg_def *adef = &adefs[argi];
uint type = adef->type & AT_TYPE_MASK;
{
case AT_STRING:
t = next_token();
- if (t != TOK_STRING)
- err("Argument %s must be a string", adef->name);
+ if (t != TOK_STRING && t != TOK_IDENT)
+ err("Argument %s must be a string or identifier", adef->name);
val = new arg_string(token);
break;
case AT_INT:
for (int i=0; cmd_table[i].name; i++)
{
const cmd_def *def = &cmd_table[i];
- printf("%s\n", def->name);
+ printf("%s - %s\n", def->name, def->help);
const arg_def *arg = def->arg_defs;
static const char * const type_names[] = {
- "string", "int", "double", "dimen", "switch"
+ "string", "int", "real", "dimen", "switch"
};
while (arg->name)
{
- printf("\t%s (%s)%s%s\n",
+ char a[32];
+ snprintf(a, sizeof(a), "%s%s=%s<%s>",
+ (arg->type & AT_POSITIONAL) ? "[" : "",
arg->name,
- type_names[arg->type & AT_TYPE_MASK],
- (arg->type & AT_MANDATORY) ? " [mandatory]" : "",
- (arg->type & AT_POSITIONAL) ? " [positional]" : "");
+ (arg->type & AT_POSITIONAL) ? "]" : "",
+ type_names[arg->type & AT_TYPE_MASK]);
+ printf(" %-20s %s\n", a, arg->help);
arg++;
}
if (def->has_pipeline)
- printf("\t{ pipeline }\n");
+ printf(" { pipeline }\n");
}
}