2 #define I3__FILE__ "commands_parser.c"
38 #define y(x, ...) yajl_gen_ ## x (command_output.json_gen, ##__VA_ARGS__)
39 #define ystr(str) yajl_gen_string(command_output.json_gen, (unsigned char*)str, strlen(str))
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);
209 DLOG(
"COMMAND: *%s*\n", input);
222 const char *walk = input;
223 const size_t len = strlen(input);
235 while ((walk - input) <= len) {
237 while ((*walk ==
' ' || *walk ==
'\t' ||
238 *walk ==
'\r' || *walk ==
'\n') && *walk !=
'\0')
242 token_handled =
false;
243 for (c = 0; c < ptr->
n; c++) {
244 token = &(ptr->
array[c]);
247 if (token->
name[0] ==
'\'') {
248 if (strncasecmp(walk, token->
name + 1, strlen(token->
name) - 1) == 0) {
251 walk += strlen(token->
name) - 1;
253 token_handled =
true;
259 if (strcmp(token->
name,
"string") == 0 ||
260 strcmp(token->
name,
"word") == 0) {
261 const char *beginning = walk;
266 while (*walk !=
'\0' && (*walk !=
'"' || *(walk-1) ==
'\\'))
269 if (token->
name[0] ==
's') {
274 while (*walk !=
';' && *walk !=
',' &&
275 *walk !=
'\0' && *walk !=
'\r' &&
282 while (*walk !=
' ' && *walk !=
'\t' &&
283 *walk !=
']' && *walk !=
',' &&
284 *walk !=
';' && *walk !=
'\r' &&
285 *walk !=
'\n' && *walk !=
'\0')
289 if (walk != beginning) {
290 char *str =
scalloc(walk-beginning + 1);
293 for (inpos = 0, outpos = 0;
294 inpos < (walk-beginning);
299 if (beginning[inpos] ==
'\\' && beginning[inpos+1] ==
'"')
301 str[outpos] = beginning[inpos];
310 token_handled =
true;
315 if (strcmp(token->
name,
"end") == 0) {
316 if (*walk ==
'\0' || *walk ==
',' || *walk ==
';') {
318 token_handled =
true;
325 if (*walk ==
'\0' || *walk ==
';')
334 if (!token_handled) {
338 for (c = 0; c < ptr->
n; c++)
339 tokenlen += strlen(ptr->
array[c].
name) + strlen(
"'', ");
345 char *possible_tokens =
smalloc(tokenlen + 1);
346 char *tokenwalk = possible_tokens;
347 for (c = 0; c < ptr->
n; c++) {
348 token = &(ptr->
array[c]);
349 if (token->
name[0] ==
'\'') {
353 strcpy(tokenwalk, token->
name + 1);
354 tokenwalk += strlen(token->
name + 1);
360 strcpy(tokenwalk, token->
name);
361 tokenwalk += strlen(token->
name);
364 if (c < (ptr->
n - 1)) {
370 sasprintf(&errormessage,
"Expected one of these tokens: %s",
372 free(possible_tokens);
376 char *position =
smalloc(len + 1);
377 for (
const char *copywalk = input; *copywalk !=
'\0'; copywalk++)
378 position[(copywalk - input)] = (copywalk >= walk ?
'^' :
' ');
379 position[len] =
'\0';
381 ELOG(
"%s\n", errormessage);
382 ELOG(
"Your command: %s\n", input);
383 ELOG(
" %s\n", position);
398 ystr(
"errorposition");
431 fprintf(stdout,
"# ");
432 vfprintf(stdout, fmt, args);
440 vfprintf(stderr, fmt, args);
444 int main(
int argc,
char *argv[]) {
446 fprintf(stderr,
"Syntax: %s <command>\n", argv[0]);
#define TAILQ_INSERT_TAIL(head, elm, field)
static void next_state(const cmdp_token *token)
void errorlog(char *fmt,...)
#define TAILQ_EMPTY(head)
char * sstrdup(const char *str)
Safe-wrapper around strdup which exits if malloc returns NULL (meaning that there is no more memory a...
A "match" is a data structure which acts like a mask or expression to match certain windows or not...
static struct CommandResult command_output
static void GENERATED_call(const int call_identifier, struct CommandResult *result)
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_REMOVE(head, elm, field)
static cmdp_token_ptr tokens[50]
struct CommandResult * parse_command(const char *input)
struct tokenptr cmdp_token_ptr
static struct CommandResult subcommand_output
#define TAILQ_HEAD(name, type)
static void push_string(const char *identifier, char *str)
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.
static void clear_stack(void)
#define TAILQ_HEAD_INITIALIZER(head)
int main(int argc, char *argv[])
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 Match current_match
void * smalloc(size_t size)
Safe-wrapper around malloc which exits if malloc returns NULL (meaning that there is no more memory a...
static struct stack_entry stack[10]
#define TAILQ_FIRST(head)
#define TAILQ_ENTRY(type)
static char * get_string(const char *identifier)
void debuglog(char *fmt,...)