2 #define I3__FILE__ "config_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))
51 typedef struct token {
95 for (
int c = 0; c < 10; c++) {
96 if (
stack[c].identifier != NULL &&
97 strcmp(
stack[c].identifier, identifier) != 0)
99 if (
stack[c].identifier == NULL) {
116 fprintf(stderr,
"BUG: commands_parser stack full. This means either a bug "
117 "in the code, or a new command which contains more than "
118 "10 identified tokens.\n");
123 for (
int c = 0; c < 10; c++) {
124 if (
stack[c].identifier != NULL)
136 fprintf(stderr,
"BUG: commands_parser stack full. This means either a bug "
137 "in the code, or a new command which contains more than "
138 "10 identified tokens.\n");
144 for (
int c = 0; c < 10; c++) {
145 if (
stack[c].identifier == NULL)
147 if (strcmp(identifier,
stack[c].identifier) == 0)
154 for (
int c = 0; c < 10; c++) {
155 if (
stack[c].identifier == NULL)
157 if (strcmp(identifier,
stack[c].identifier) == 0)
164 for (
int c = 0; c < 10; c++) {
180 typedef struct criterion {
187 static
TAILQ_HEAD(criteria_head, criterion) criteria =
195 static
void push_criterion(
void *unused_criteria, const
char *type,
197 struct criterion *criterion = malloc(
sizeof(
struct criterion));
198 criterion->type = strdup(type);
199 criterion->value = strdup(value);
208 static void clear_criteria(
void *unused_criteria) {
209 struct criterion *criterion;
212 free(criterion->type);
213 free(criterion->value);
268 statelist[statelist_idx++] = _next_state;
277 while (*walk !=
'\n' && *walk !=
'\r' && walk >= beginning) {
292 char *end = strchr(result,
'\n');
301 const char *dumpwalk = input;
303 while (*dumpwalk !=
'\0') {
304 char *next_nl = strchr(dumpwalk,
'\n');
305 if (next_nl != NULL) {
306 DLOG(
"CONFIG(line %3d): %.*s\n", linecnt, (
int)(next_nl - dumpwalk), dumpwalk);
307 dumpwalk = next_nl + 1;
309 DLOG(
"CONFIG(line %3d): %s\n", linecnt, dumpwalk);
326 const char *walk = input;
327 const size_t len = strlen(input);
340 while ((walk - input) <= len) {
343 while ((*walk ==
' ' || *walk ==
'\t') && *walk !=
'\0')
349 token_handled =
false;
350 for (c = 0; c < ptr->
n; c++) {
351 token = &(ptr->
array[c]);
354 if (token->
name[0] ==
'\'') {
355 if (strncasecmp(walk, token->
name + 1, strlen(token->
name) - 1) == 0) {
358 walk += strlen(token->
name) - 1;
360 token_handled =
true;
366 if (strcmp(token->
name,
"number") == 0) {
370 long int num = strtol(walk, &end, 10);
371 if ((errno == ERANGE && (num == LONG_MIN || num == LONG_MAX)) ||
372 (errno != 0 && num == 0))
385 token_handled =
true;
389 if (strcmp(token->
name,
"string") == 0 ||
390 strcmp(token->
name,
"word") == 0) {
391 const char *beginning = walk;
396 while (*walk !=
'\0' && (*walk !=
'"' || *(walk-1) ==
'\\'))
399 if (token->
name[0] ==
's') {
400 while (*walk !=
'\0' && *walk !=
'\r' && *walk !=
'\n')
406 while (*walk !=
' ' && *walk !=
'\t' &&
407 *walk !=
']' && *walk !=
',' &&
408 *walk !=
';' && *walk !=
'\r' &&
409 *walk !=
'\n' && *walk !=
'\0')
413 if (walk != beginning) {
414 char *str =
scalloc(walk-beginning + 1);
417 for (inpos = 0, outpos = 0;
418 inpos < (walk-beginning);
423 if (beginning[inpos] ==
'\\' && beginning[inpos+1] ==
'"')
425 str[outpos] = beginning[inpos];
435 token_handled =
true;
440 if (strcmp(token->
name,
"end") == 0) {
442 if (*walk ==
'\0' || *walk ==
'\n' || *walk ==
'\r') {
444 token_handled =
true;
460 if (!token_handled) {
464 for (c = 0; c < ptr->
n; c++)
465 tokenlen += strlen(ptr->
array[c].
name) + strlen(
"'', ");
471 char *possible_tokens =
smalloc(tokenlen + 1);
472 char *tokenwalk = possible_tokens;
473 for (c = 0; c < ptr->
n; c++) {
474 token = &(ptr->
array[c]);
475 if (token->
name[0] ==
'\'') {
479 strcpy(tokenwalk, token->
name + 1);
480 tokenwalk += strlen(token->
name + 1);
485 if (strcmp(token->
name,
"error") == 0)
490 strcpy(tokenwalk, token->
name);
491 tokenwalk += strlen(token->
name);
494 if (c < (ptr->
n - 1)) {
500 sasprintf(&errormessage,
"Expected one of these tokens: %s",
502 free(possible_tokens);
510 char *position =
scalloc(strlen(error_line) + 1);
511 const char *copywalk;
512 for (copywalk = error_line;
513 *copywalk !=
'\n' && *copywalk !=
'\r' && *copywalk !=
'\0';
515 position[(copywalk - error_line)] = (copywalk >= walk ?
'^' : (*copywalk ==
'\t' ?
'\t' :
' '));
516 position[(copywalk - error_line)] =
'\0';
518 ELOG(
"CONFIG: %s\n", errormessage);
524 const char *context_p1_start =
start_of_line(error_line-2, input);
525 char *context_p1_line =
single_line(context_p1_start);
527 const char *context_p2_start =
start_of_line(context_p1_start-2, input);
528 char *context_p2_line =
single_line(context_p2_start);
529 ELOG(
"CONFIG: Line %3d: %s\n", linecnt - 2, context_p2_line);
530 free(context_p2_line);
532 ELOG(
"CONFIG: Line %3d: %s\n", linecnt - 1, context_p1_line);
533 free(context_p1_line);
535 ELOG(
"CONFIG: Line %3d: %s\n", linecnt, error_copy);
536 ELOG(
"CONFIG: %s\n", position);
539 for (
int i = 0; i < 2; i++) {
540 char *error_line_end = strchr(error_line,
'\n');
541 if (error_line_end != NULL && *(error_line_end + 1) !=
'\0') {
542 error_line = error_line_end + 1;
544 ELOG(
"CONFIG: Line %3d: %s\n", linecnt + i + 1, error_copy);
564 ystr(
"errorposition");
569 while ((walk - input) <= len && *walk !=
'\n')
579 bool error_token_found =
false;
580 for (
int i =
statelist_idx-1; (i >= 0) && !error_token_found; i--) {
582 for (
int j = 0; j < errptr->
n; j++) {
583 if (strcmp(errptr->
array[j].
name,
"error") != 0)
586 error_token_found =
true;
591 assert(error_token_found);
617 fprintf(stdout,
"# ");
618 vfprintf(stdout, fmt, args);
626 vfprintf(stderr, fmt, args);
632 void cfg_criteria_init(
I3_CFG,
int _state) {
636 void cfg_criteria_add(
I3_CFG,
const char *ctype,
const char *cvalue) {
639 void cfg_criteria_pop_state(
I3_CFG) {
643 int main(
int argc,
char *argv[]) {
645 fprintf(stderr,
"Syntax: %s <command>\n", argv[0]);