summaryrefslogtreecommitdiffstats
path: root/src/args-bison.y
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@shell.devel.redhat.com>2009-09-04 02:29:08 -0400
committerJiri Olsa <jolsa@shell.devel.redhat.com>2009-09-04 02:29:08 -0400
commit04f3fbbfdb3a5dd197dbc25ca18ad244f1fbf6a5 (patch)
tree8e53039a4f5d1a4571000bc06214053261aebf8d /src/args-bison.y
downloadlatrace-04f3fbbfdb3a5dd197dbc25ca18ad244f1fbf6a5.tar.gz
latrace-04f3fbbfdb3a5dd197dbc25ca18ad244f1fbf6a5.tar.xz
latrace-04f3fbbfdb3a5dd197dbc25ca18ad244f1fbf6a5.zip
initial commit - 0.5.7
Diffstat (limited to 'src/args-bison.y')
-rw-r--r--src/args-bison.y302
1 files changed, 302 insertions, 0 deletions
diff --git a/src/args-bison.y b/src/args-bison.y
new file mode 100644
index 0000000..64c88be
--- /dev/null
+++ b/src/args-bison.y
@@ -0,0 +1,302 @@
+/*
+ Copyright (C) 2008, 2009 Jiri Olsa <olsajiri@gmail.com>
+
+ This file is part of the latrace.
+
+ The latrace is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ The latrace is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the latrace (file COPYING). If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+
+%{
+
+#define YYERROR_VERBOSE 1
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+
+int yylex (void);
+void yyerror(const char *m);
+
+static struct lt_config_shared *scfg;
+static int struct_alive = 0;
+
+#define ERROR(fmt, args...) \
+do { \
+ char ebuf[1024]; \
+ sprintf(ebuf, fmt, ## args); \
+ yyerror(ebuf); \
+ YYERROR; \
+} while(0)
+
+#define CHK_TYPEDEF(ret, base, new, pointer) \
+do { \
+ switch(ret) { \
+ case -1: \
+ ERROR("unknown typedef - %s%s%s\n", base, (pointer ? "* " : " "), new); \
+ break; \
+ case 1: \
+ ERROR("typedef alrady defined - %s%s%s\n", base, (pointer ? "* " : " "), new); \
+ break; \
+ case 2: \
+ ERROR("typedef limit reached(%d) - %s%s%s\n", \
+ LT_ARGS_DEF_TYPEDEF_NUM, base, (pointer ? "* " : " "), new); \
+ break; \
+ }; \
+} while(0)
+
+#define GET_LIST_HEAD(head) \
+do { \
+ if (NULL == (head = (struct lt_list_head*) malloc(sizeof(*head)))) \
+ ERROR("failed to allocate list head"); \
+ lt_init_list_head(head); \
+} while(0)
+
+%}
+
+%token NAME FILENAME STRUCT ENUM TYPEDEF INCLUDE END POINTER
+
+%union
+{
+ char *s;
+ struct lt_arg *arg;
+ struct lt_enum_elem *enum_elem;
+ struct lt_list_head *head;
+}
+
+%type <s> NAME
+%type <s> FILENAME
+%type <head> STRUCT_DEF
+%type <head> ENUM_DEF
+%type <s> ENUM_REF
+%type <enum_elem> ENUM_ELEM
+%type <head> ARGS
+%type <arg> DEF
+
+%%
+entry:
+entry struct_def
+|
+entry enum_def
+|
+entry func_def
+|
+entry type_def
+|
+entry include_def
+|
+entry END
+{
+ if (lt_args_buf_close(scfg))
+ return 0;
+}
+|
+/* left blank intentionally */
+
+/* struct definitions */
+struct_def:
+STRUCT NAME '{' STRUCT_DEF '}' ';'
+{
+ switch(lt_args_add_struct(scfg, $2, $4)) {
+ case -1:
+ ERROR("failed to add struct %s\n", $2);
+ case 1:
+ ERROR("struct limit reached(%d) - %s\n", LT_ARGS_DEF_STRUCT_NUM, $2);
+ };
+
+ /* force creation of the new list head */
+ struct_alive = 0;
+}
+
+STRUCT_DEF:
+STRUCT_DEF DEF ';'
+{
+ struct lt_arg *def = $2;
+ struct lt_list_head *h = $1;
+
+ if (!struct_alive++)
+ GET_LIST_HEAD(h);
+
+ lt_list_add_tail(&def->args_list, h);
+ $$ = h;
+}
+| /* left blank intentionally,
+ XXX this could be done like the args_def, but user needs to be
+ able to create an empty structure, so thats why we play
+ with the global struct_alive thingie...
+ there could be better way probably */
+{
+}
+
+/* enum definitions */
+enum_def:
+ENUM NAME '{' ENUM_DEF '}' ';'
+{
+ switch(lt_args_add_enum(scfg, $2, $4)) {
+ case -1:
+ ERROR("failed to add enum %s\n", $2);
+ case 1:
+ ERROR("enum limit reached(%d) - %s\n", LT_ARGS_DEF_STRUCT_NUM, $2);
+ };
+}
+
+ENUM_DEF:
+ENUM_DEF ',' ENUM_ELEM
+{
+ struct lt_enum_elem *enum_elem = $3;
+ struct lt_list_head *h = $1;
+
+ lt_list_add_tail(&enum_elem->list, h);
+ $$ = h;
+}
+| ENUM_ELEM
+{
+ struct lt_list_head *h;
+ struct lt_enum_elem *enum_elem = $1;
+
+ GET_LIST_HEAD(h);
+ lt_list_add_tail(&enum_elem->list, h);
+ $$ = h;
+}
+
+ENUM_ELEM:
+NAME '=' NAME
+{
+ if (NULL == ($$ = lt_args_get_enum(scfg, $1, $3)))
+ ERROR("failed to add enum '%s = %s'\n", $1, $3);
+}
+|
+NAME
+{
+ if (NULL == ($$ = lt_args_get_enum(scfg, $1, NULL)))
+ ERROR("failed to add enum '%s = undef'\n", $1);
+}
+
+type_def:
+TYPEDEF NAME NAME ';'
+{
+ int ret = lt_args_add_typedef(scfg, $2, $3, 0);
+ CHK_TYPEDEF(ret, $2, $3, 0);
+}
+|
+TYPEDEF NAME POINTER NAME ';'
+{
+ int ret = lt_args_add_typedef(scfg, $2, $4, 1);
+ CHK_TYPEDEF(ret, $2, $4, 1);
+}
+
+/* function definitions */
+func_def:
+DEF '(' ARGS ')' ';'
+{
+ struct lt_arg *arg = $1;
+
+ if (lt_args_add_sym(scfg, arg, $3))
+ ERROR("failed to add symbol %s\n", arg->name);
+
+ /* force cration of the new list head */
+ $3 = NULL;
+}
+
+ARGS:
+ARGS ',' DEF
+{
+ struct lt_arg *def = $3;
+ struct lt_list_head *h = $1;
+
+ lt_list_add_tail(&def->args_list, h);
+ $$ = h;
+}
+| DEF
+{
+ struct lt_list_head *h;
+ struct lt_arg *def = $1;
+
+ GET_LIST_HEAD(h);
+ lt_list_add_tail(&def->args_list, h);
+ $$ = h;
+}
+| NAME
+{
+ GET_LIST_HEAD($$);
+}
+| /* left intentionaly blank */
+{
+ GET_LIST_HEAD($$);
+}
+
+DEF:
+NAME NAME ENUM_REF
+{
+ struct lt_arg *arg;
+
+ if (NULL == (arg = lt_args_getarg(scfg, $1, $2, 0, 1, $3)))
+ ERROR("unknown argument type - %s\n", $1);
+
+ $$ = arg;
+}
+|
+NAME POINTER NAME ENUM_REF
+{
+ struct lt_arg *arg;
+ if (NULL == (arg = lt_args_getarg(scfg, $1, $3, 1, 1, $4)))
+ ERROR("unknown argument type - %s\n", $1);
+
+ $$ = arg;
+}
+|
+STRUCT NAME NAME
+{
+ struct lt_arg *arg;
+ if (NULL == (arg = lt_args_getarg(scfg, $2, $3, 0, 1, NULL)))
+ ERROR("unknown argument type - %s\n", $2);
+
+ $$ = arg;
+}
+|
+STRUCT NAME POINTER NAME ENUM_REF
+{
+ struct lt_arg *arg;
+ if (NULL == (arg = lt_args_getarg(scfg, $2, $4, 1, 1, $5)))
+ ERROR("unknown argument type - %s\n", $2);
+
+ $$ = arg;
+}
+
+ENUM_REF:
+'=' NAME
+{
+ $$ = $2;
+}
+|
+{
+ $$ = NULL;
+}
+
+/* include definitions */
+include_def: INCLUDE '"' FILENAME '"'
+{
+ if (lt_args_buf_open(scfg, $3))
+ ERROR("failed to process include");
+}
+
+%%
+
+int lt_args_parse_init(struct lt_config_shared *cfg)
+{
+ scfg = cfg;
+ return 0;
+}