2 #define I3__FILE__ "commands_parser.c"
38 #define y(x, ...) (command_output.json_gen != NULL ? yajl_gen_##x(command_output.json_gen, ##__VA_ARGS__) : 0)
39 #define ystr(str) (command_output.json_gen != NULL ? yajl_gen_string(command_output.json_gen, (unsigned char *)str, strlen(str)) : 0)
88 for (
int c = 0; c < 10; c++) {
89 if (
stack[c].identifier != NULL)
100 fprintf(stderr,
"BUG: commands_parser stack full. This means either a bug "
101 "in the code, or a new command which contains more than "
102 "10 identified tokens.\n");
109 for (
int c = 0; c < 10; c++) {
110 if (
stack[c].identifier == NULL)
112 if (strcmp(identifier,
stack[c].identifier) == 0)
119 for (
int c = 0; c < 10; c++) {
134 typedef struct criterion {
141 static
TAILQ_HEAD(criteria_head, criterion) criteria =
149 static
void push_criterion(
void *unused_criteria, const
char *type,
151 struct criterion *criterion = malloc(
sizeof(
struct criterion));
152 criterion->type = strdup(type);
153 criterion->value = strdup(value);
162 static void clear_criteria(
void *unused_criteria) {
163 struct criterion *criterion;
166 free(criterion->type);
167 free(criterion->value);
215 DLOG(
"COMMAND: *%s*\n", input);
225 const char *walk = input;
226 const size_t len = strlen(input);
238 while ((
size_t)(walk - input) <= len) {
240 while ((*walk ==
' ' || *walk ==
'\t' ||
241 *walk ==
'\r' || *walk ==
'\n') &&
246 token_handled =
false;
247 for (c = 0; c < ptr->
n; c++) {
248 token = &(ptr->
array[c]);
251 if (token->
name[0] ==
'\'') {
252 if (strncasecmp(walk, token->
name + 1, strlen(token->
name) - 1) == 0) {
255 walk += strlen(token->
name) - 1;
257 token_handled =
true;
263 if (strcmp(token->
name,
"string") == 0 ||
264 strcmp(token->
name,
"word") == 0) {
265 const char *beginning = walk;
270 while (*walk !=
'\0' && (*walk !=
'"' || *(walk - 1) ==
'\\'))
273 if (token->
name[0] ==
's') {
278 while (*walk !=
';' && *walk !=
',' &&
279 *walk !=
'\0' && *walk !=
'\r' &&
286 while (*walk !=
' ' && *walk !=
'\t' &&
287 *walk !=
']' && *walk !=
',' &&
288 *walk !=
';' && *walk !=
'\r' &&
289 *walk !=
'\n' && *walk !=
'\0')
293 if (walk != beginning) {
294 char *str =
scalloc(walk - beginning + 1);
297 for (inpos = 0, outpos = 0;
298 inpos < (walk - beginning);
303 if (beginning[inpos] ==
'\\' && beginning[inpos + 1] ==
'"')
305 str[outpos] = beginning[inpos];
314 token_handled =
true;
319 if (strcmp(token->
name,
"end") == 0) {
320 if (*walk ==
'\0' || *walk ==
',' || *walk ==
';') {
322 token_handled =
true;
329 if (*walk ==
'\0' || *walk ==
';')
338 if (!token_handled) {
342 for (c = 0; c < ptr->
n; c++)
343 tokenlen += strlen(ptr->
array[c].
name) + strlen(
"'', ");
349 char *possible_tokens =
smalloc(tokenlen + 1);
350 char *tokenwalk = possible_tokens;
351 for (c = 0; c < ptr->
n; c++) {
352 token = &(ptr->
array[c]);
353 if (token->
name[0] ==
'\'') {
357 strcpy(tokenwalk, token->
name + 1);
358 tokenwalk += strlen(token->
name + 1);
364 strcpy(tokenwalk, token->
name);
365 tokenwalk += strlen(token->
name);
368 if (c < (ptr->
n - 1)) {
374 sasprintf(&errormessage,
"Expected one of these tokens: %s",
376 free(possible_tokens);
380 char *position =
smalloc(len + 1);
381 for (
const char *copywalk = input; *copywalk !=
'\0'; copywalk++)
382 position[(copywalk - input)] = (copywalk >= walk ?
'^' :
' ');
383 position[len] =
'\0';
385 ELOG(
"%s\n", errormessage);
386 ELOG(
"Your command: %s\n", input);
387 ELOG(
" %s\n", position);
405 ystr(
"errorposition");
449 fprintf(stdout,
"# ");
450 vfprintf(stdout, fmt, args);
458 vfprintf(stderr, fmt, args);
462 int main(
int argc,
char *argv[]) {
464 fprintf(stderr,
"Syntax: %s <command>\n", argv[0]);
467 yajl_gen gen = yajl_gen_alloc(NULL);
char * sstrdup(const char *str)
Safe-wrapper around strdup which exits if malloc returns NULL (meaning that there is no more memory a...
static struct CommandResultIR command_output
static void GENERATED_call(const int call_identifier, struct CommandResultIR *result)
#define TAILQ_REMOVE(head, elm, field)
static void next_state(const cmdp_token *token)
struct tokenptr cmdp_token_ptr
CommandResult * parse_command(const char *input, yajl_gen gen)
Parses and executes the given command.
#define TAILQ_FIRST(head)
void command_result_free(CommandResult *result)
Frees a CommandResult.
static Match current_match
static struct stack_entry stack[10]
A struct that contains useful information about the result of a command as a whole (e...
int sasprintf(char **strp, const char *fmt,...)
Safe-wrapper around asprintf which exits if it returns -1 (meaning that there is no more memory avail...
static char * get_string(const char *identifier)
static void clear_stack(void)
void errorlog(char *fmt,...)
static void push_string(const char *identifier, char *str)
#define TAILQ_EMPTY(head)
#define TAILQ_ENTRY(type)
A "match" is a data structure which acts like a mask or expression to match certain windows or not...
static struct CommandResultIR subcommand_output
void debuglog(char *fmt,...)
static cmdp_token_ptr tokens[51]
void * scalloc(size_t size)
Safe-wrapper around calloc which exits if malloc returns NULL (meaning that there is no more memory a...
#define TAILQ_INSERT_TAIL(head, elm, field)
#define TAILQ_HEAD_INITIALIZER(head)
void cmd_criteria_init(I3_CMD)
Initializes the specified 'Match' data structure and the initial state of commands.c for matching target windows of a command.
int main(int argc, char *argv[])
void * smalloc(size_t size)
Safe-wrapper around malloc which exits if malloc returns NULL (meaning that there is no more memory a...
#define TAILQ_HEAD(name, type)