summaryrefslogtreecommitdiff
path: root/src/pmlc/gram.y
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmlc/gram.y')
-rw-r--r--src/pmlc/gram.y336
1 files changed, 336 insertions, 0 deletions
diff --git a/src/pmlc/gram.y b/src/pmlc/gram.y
new file mode 100644
index 0000000..1455329
--- /dev/null
+++ b/src/pmlc/gram.y
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2014 Red Hat.
+ * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program 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 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+%{
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include "pmapi.h"
+#include "impl.h"
+#include "./pmlc.h"
+
+#ifdef YYDEBUG
+int yydebug=1;
+#endif
+
+int mystate = GLOBAL;
+int logfreq;
+int parse_stmt;
+char emess[160];
+char *hostname;
+int state;
+int control;
+int qa_case;
+
+static int sts;
+
+extern int port;
+extern int pid;
+extern int is_local;
+extern int is_unix;
+extern int is_socket_path;
+
+%}
+
+%union {
+ long lval;
+ char * str;
+}
+
+%term LSQB
+ RSQB
+ COMMA
+ LBRACE
+ RBRACE
+ AT
+ EOL
+
+ LOG
+ MANDATORY ADVISORY
+ ON OFF MAYBE
+ EVERY ONCE
+ MSEC SECOND MINUTE HOUR
+
+ QUERY SHOW LOGGER CONNECT PRIMARY QUIT STATUS HELP
+ TIMEZONE LOCAL PORT SOCKET
+ NEW VOLUME
+
+ SYNC
+ QA
+
+%token<str> NAME HOSTNAME STRING URL
+%token<lval> NUMBER
+
+%type<lval> timeunits
+%%
+
+stmt : dowhat
+ {
+ mystate |= INSPEC;
+ if (!connected()) {
+ metric_cnt = -1;
+ return 0;
+ }
+ if (ConnectPMCD()) {
+ yyerror("");
+ metric_cnt = -1;
+ return 0;
+ }
+ beginmetrics();
+ }
+ somemetrics
+ {
+ mystate = GLOBAL;
+ endmetrics();
+ }
+ EOL
+ {
+ parse_stmt = LOG;
+ YYACCEPT;
+ }
+ | SHOW loggersopt hostopt EOL
+ {
+ parse_stmt = SHOW;
+ YYACCEPT;
+ }
+ | CONNECT towhom hostopt EOL
+ {
+ parse_stmt = CONNECT;
+ YYACCEPT;
+ }
+ | HELP EOL
+ {
+ parse_stmt = HELP;
+ YYACCEPT;
+ }
+ | QUIT EOL
+ {
+ parse_stmt = QUIT;
+ YYACCEPT;
+ }
+ | STATUS EOL
+ {
+ parse_stmt = STATUS;
+ YYACCEPT;
+ }
+ | NEW VOLUME EOL
+ {
+ parse_stmt = NEW;
+ YYACCEPT;
+ }
+ | TIMEZONE tzspec EOL
+ {
+ parse_stmt = TIMEZONE;
+ YYACCEPT;
+ }
+ | SYNC EOL
+ {
+ parse_stmt = SYNC;
+ YYACCEPT;
+ }
+ | QA NUMBER EOL
+ {
+ parse_stmt = QA;
+ qa_case = $2;
+ YYACCEPT;
+ }
+ | EOL
+ {
+ parse_stmt = 0;
+ YYACCEPT;
+ }
+ | { YYERROR; }
+ ;
+
+dowhat : action
+ ;
+
+action : QUERY { state = PM_LOG_ENQUIRE; }
+ | logopt cntrl ON frequency { state = PM_LOG_ON; }
+ | logopt cntrl OFF { state = PM_LOG_OFF; }
+ | logopt MANDATORY MAYBE
+ {
+ control = PM_LOG_MANDATORY;
+ state = PM_LOG_MAYBE;
+ }
+ ;
+
+logopt : LOG
+ | /* nothing */
+ ;
+
+cntrl : MANDATORY { control = PM_LOG_MANDATORY; }
+ | ADVISORY { control = PM_LOG_ADVISORY; }
+ ;
+
+frequency : everyopt NUMBER timeunits { logfreq = $2 * $3; }
+ | ONCE { logfreq = -1; }
+ ;
+
+everyopt : EVERY
+ | /* nothing */
+ ;
+
+timeunits : MSEC { $$ = 1; }
+ | SECOND { $$ = 1000; }
+ | MINUTE { $$ = 60000; }
+ | HOUR { $$ = 3600000; }
+ ;
+
+somemetrics : LBRACE { mystate |= INSPECLIST; } metriclist RBRACE
+ | metricspec
+ ;
+
+metriclist : metricspec
+ | metriclist metricspec
+ | metriclist COMMA metricspec
+ ;
+
+metricspec : NAME
+ {
+ beginmetgrp();
+ if ((sts = pmTraversePMNS($1, addmetric)) < 0)
+ /* metric_cnt is set by addmetric but if
+ * traversePMNS fails, set it so that the bad
+ * news is visible to other routines
+ */
+ metric_cnt = sts;
+ else if (metric_cnt < 0) /* addmetric failed */
+ sts = metric_cnt;
+
+ if (sts < 0 || metric_cnt == 0) {
+ sprintf(emess,
+ "Problem with lookup for metric \"%s\" ...",$1);
+ yywarn(emess);
+ if (sts < 0) {
+ fprintf(stderr, "Reason: ");
+ fprintf(stderr, "%s\n", pmErrStr(sts));
+ }
+ }
+ }
+ optinst { endmetgrp(); }
+ ;
+
+optinst : LSQB instancelist RSQB
+ | /* nothing */
+ ;
+
+instancelist : instance
+ | instance instancelist
+ | instance COMMA instancelist
+ ;
+
+instance : NAME { addinst($1, 0); }
+ | NUMBER { addinst(NULL, $1); }
+ | STRING { addinst($1, 0); }
+ ;
+
+loggersopt : LOGGER
+ | /* nothing */
+ ;
+
+hostopt : AT NAME { hostname = strdup($2); }
+ | AT HOSTNAME { hostname = strdup($2); }
+ | AT URL
+ {
+ char *prefix_end;
+ size_t prefix_len;
+ hostname = strdup($2);
+ prefix_end = strchr(hostname, ':');
+ if (prefix_end != NULL) {
+ prefix_len = prefix_end - hostname + 1;
+ if (prefix_len == 6 && strncmp(hostname, "local:", prefix_len) == 0)
+ is_local = 1;
+ else if (prefix_len == 5 && strncmp(hostname, "unix:", prefix_len) == 0)
+ is_unix = 1;
+ if (is_local || is_unix) {
+ const char *p;
+ /*
+ * Find out is a path was specified.
+ * Skip any initial path separators.
+ */
+ for (p = hostname + prefix_len; *p == __pmPathSeparator(); ++p)
+ ;
+ if (*p != '\0')
+ is_socket_path = 1;
+ }
+ }
+ }
+ | AT NUMBER
+ {
+ /* That MUST be a mistake! */
+ char tb[64];
+ sprintf (tb, "%d", (int)$2);
+ hostname = strdup(tb);
+ }
+ | AT STRING { hostname = strdup($2); }
+ | /* nothing */
+ ;
+
+towhom : PRIMARY { pid = PM_LOG_PRIMARY_PID; port = PM_LOG_NO_PORT; }
+ | NUMBER { pid = $1; port = PM_LOG_NO_PORT; }
+ | PORT NUMBER { pid = PM_LOG_NO_PID; port = $2; }
+ | SOCKET { pid = PM_LOG_NO_PID; port = PM_LOG_NO_PORT; }
+ ;
+
+tzspec : LOCAL { tztype = TZ_LOCAL; }
+ | LOGGER { tztype = TZ_LOGGER; }
+ | STRING
+ {
+ tztype = TZ_OTHER;
+ /* ignore the quotes: skip the leading one and
+ * clobber the trailing one with a null to
+ * terminate the string really required.
+ */
+ if (tz != NULL)
+ free(tz);
+ if ((tz = strdup($1)) == NULL) {
+ __pmNoMem("setting up timezone",
+ strlen($1), PM_FATAL_ERR);
+ }
+ }
+ ;
+
+%%
+
+extern char *configfile;
+extern int lineno;
+
+void
+yywarn(char *s)
+{
+ fprintf(stderr, "Warning [%s, line %d]\n",
+ configfile == NULL ? "<stdin>" : configfile, lineno);
+ if (s != NULL && s[0] != '\0')
+ fprintf(stderr, "%s\n", s);
+}
+
+void
+yyerror(char *s)
+{
+ fprintf(stderr, "Error [%s, line %d]\n",
+ configfile == NULL ? "<stdin>" : configfile, lineno);
+ if (s != NULL && s[0] != '\0')
+ fprintf(stderr, "%s\n", s);
+
+ skipAhead ();
+ yyclearin;
+ mystate = GLOBAL;
+}