summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2011-07-12 12:39:10 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2011-07-12 12:39:10 +0200
commit2a2a9716f7ee0debd192e75785e347f4e4af0b4d (patch)
tree8d8fef67d1c7bdf11bd193f3ce93dae8e9530ba4 /runtime
parent3b63b155ed5e4d58858baa3d6f07293099d8a4e5 (diff)
parent20607ba1695b99838db7bdf809b22cf52bbdf5ce (diff)
downloadrsyslog-2a2a9716f7ee0debd192e75785e347f4e4af0b4d.tar.gz
rsyslog-2a2a9716f7ee0debd192e75785e347f4e4af0b4d.tar.xz
rsyslog-2a2a9716f7ee0debd192e75785e347f4e4af0b4d.zip
Merge branch 'master-newconf'
Conflicts: ChangeLog tools/omfile.c
Diffstat (limited to 'runtime')
-rw-r--r--runtime/Makefile.am18
-rw-r--r--runtime/conf.c388
-rw-r--r--runtime/conf.h19
-rw-r--r--runtime/ctok.c629
-rw-r--r--runtime/ctok.h56
-rw-r--r--runtime/ctok_token.c129
-rw-r--r--runtime/ctok_token.h88
-rw-r--r--runtime/datetime.c1
-rw-r--r--runtime/errmsg.c1
-rw-r--r--runtime/expr.c482
-rw-r--r--runtime/expr.h57
-rw-r--r--runtime/msg.c118
-rw-r--r--runtime/msg.h2
-rw-r--r--runtime/rsconf.c323
-rw-r--r--runtime/rsyslog.c23
-rw-r--r--runtime/rsyslog.h1
-rw-r--r--runtime/rule.c31
-rw-r--r--runtime/rule.h6
-rw-r--r--runtime/statsobj.c1
-rw-r--r--runtime/sysvar.c204
-rw-r--r--runtime/sysvar.h47
-rw-r--r--runtime/vm.c869
-rw-r--r--runtime/vm.h68
-rw-r--r--runtime/vmop.c307
-rw-r--r--runtime/vmop.h129
-rw-r--r--runtime/vmprg.c236
-rw-r--r--runtime/vmprg.h69
-rw-r--r--runtime/vmstk.c234
-rw-r--r--runtime/vmstk.h56
29 files changed, 359 insertions, 4233 deletions
diff --git a/runtime/Makefile.am b/runtime/Makefile.am
index 232d8f03..ac4f4279 100644
--- a/runtime/Makefile.am
+++ b/runtime/Makefile.am
@@ -55,12 +55,6 @@ librsyslog_la_SOURCES = \
statsobj.h \
sync.c \
sync.h \
- expr.c \
- expr.h \
- ctok.c \
- ctok.h \
- ctok_token.c \
- ctok_token.h \
stream.c \
stream.h \
var.c \
@@ -69,16 +63,6 @@ librsyslog_la_SOURCES = \
wtp.h \
wti.c \
wti.h \
- sysvar.c \
- sysvar.h \
- vm.c \
- vm.h \
- vmstk.c \
- vmstk.h \
- vmprg.c \
- vmprg.h \
- vmop.c \
- vmop.h \
queue.c \
queue.h \
ruleset.c \
@@ -117,7 +101,7 @@ librsyslog_la_SOURCES = \
if WITH_MODDIRS
librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/:$(moddirs)\" $(PTHREADS_CFLAGS) $(LIBEE_CFLAGS) -I\$(top_srcdir)/tools
else
-librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/\" -I$(top_srcdir) $(PTHREADS_CFLAGS) $(LIBEE_CFLAGS) -I\$(top_srcdir)/tools
+librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/\" -I$(top_srcdir) $(PTHREADS_CFLAGS) $(LIBEE_CFLAGS) -I\$(top_srcdir)/tools -I\$(top_srcdir)/grammar
endif
#librsyslog_la_LDFLAGS = -module -avoid-version
librsyslog_la_LIBADD = $(DL_LIBS) $(RT_LIBS) $(LIBEE_LIBS)
diff --git a/runtime/conf.c b/runtime/conf.c
index 0dd53754..27077ea9 100644
--- a/runtime/conf.c
+++ b/runtime/conf.c
@@ -65,9 +65,6 @@
#include "srUtils.h"
#include "errmsg.h"
#include "net.h"
-#include "expr.h"
-#include "ctok.h"
-#include "ctok_token.h"
#include "rule.h"
#include "ruleset.h"
#include "rsconf.h"
@@ -78,15 +75,11 @@
#endif
/* forward definitions */
-static rsRetVal cfline(rsconf_t *conf, uchar *line, rule_t **pfCurr);
-static rsRetVal processConfFile(rsconf_t *conf, uchar *pConfFile);
+//static rsRetVal cfline(rsconf_t *conf, uchar *line, rule_t **pfCurr);
/* static data */
DEFobjStaticHelpers
-DEFobjCurrIf(expr)
-DEFobjCurrIf(ctok)
-DEFobjCurrIf(ctok_token)
DEFobjCurrIf(module)
DEFobjCurrIf(errmsg)
DEFobjCurrIf(net)
@@ -104,149 +97,9 @@ int bConfStrictScoping = 0; /* force strict scoping during config processing? */
* be run in a single thread anyways. So there can be no race conditions.
* rgerhards 2005-10-18
*/
-static EHostnameCmpMode eDfltHostnameCmpMode = HN_NO_COMP;
-static cstr_t *pDfltHostnameCmp = NULL;
-static cstr_t *pDfltProgNameCmp = NULL;
-
-
-/* process a directory and include all of its files into
- * the current config file. There is no specific order of inclusion,
- * files are included in the order they are read from the directory.
- * The caller must have make sure that the provided parameter is
- * indeed a directory.
- * rgerhards, 2007-08-01
- */
-static rsRetVal doIncludeDirectory(rsconf_t *conf, uchar *pDirName)
-{
- DEFiRet;
- int iEntriesDone = 0;
- DIR *pDir;
- union {
- struct dirent d;
- char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
- } u;
- struct dirent *res;
- size_t iDirNameLen;
- size_t iFileNameLen;
- uchar szFullFileName[MAXFNAME];
-
- ASSERT(pDirName != NULL);
-
- if((pDir = opendir((char*) pDirName)) == NULL) {
- errmsg.LogError(errno, RS_RET_FOPEN_FAILURE, "error opening include directory");
- ABORT_FINALIZE(RS_RET_FOPEN_FAILURE);
- }
-
- /* prepare file name buffer */
- iDirNameLen = strlen((char*) pDirName);
- memcpy(szFullFileName, pDirName, iDirNameLen);
-
- /* now read the directory */
- iEntriesDone = 0;
- while(readdir_r(pDir, &u.d, &res) == 0) {
- if(res == NULL)
- break; /* this also indicates end of directory */
-# ifdef DT_REG
- /* TODO: find an alternate way to checking for special files if this is
- * not defined. This is currently a known problem on HP UX, but the work-
- * around is simple: do not create special files in that directory. So
- * fixing this is actually not the most important thing on earth...
- * rgerhards, 2008-03-04
- */
- if(res->d_type != DT_REG)
- continue; /* we are not interested in special files */
-# endif
- if(res->d_name[0] == '.')
- continue; /* these files we are also not interested in */
- ++iEntriesDone;
- /* construct filename */
- iFileNameLen = strlen(res->d_name);
- if (iFileNameLen > NAME_MAX)
- iFileNameLen = NAME_MAX;
- memcpy(szFullFileName + iDirNameLen, res->d_name, iFileNameLen);
- *(szFullFileName + iDirNameLen + iFileNameLen) = '\0';
- dbgprintf("including file '%s'\n", szFullFileName);
- processConfFile(conf, szFullFileName);
- /* we deliberately ignore the iRet of processConfFile() - this is because
- * failure to process one file does not mean all files will fail. By ignoring,
- * we retry with the next file, which is the best thing we can do. -- rgerhards, 2007-08-01
- */
- }
-
- if(iEntriesDone == 0) {
- /* I just make it a debug output, because I can think of a lot of cases where it
- * makes sense not to have any files. E.g. a system maintainer may place a $Include
- * into the config file just in case, when additional modules be installed. When none
- * are installed, the directory will be empty, which is fine. -- rgerhards 2007-08-01
- */
- dbgprintf("warning: the include directory contained no files - this may be ok.\n");
- }
-
-finalize_it:
- if(pDir != NULL)
- closedir(pDir);
-
- RETiRet;
-}
-
-
-/* process a $include config line. That type of line requires
- * inclusion of another file.
- * rgerhards, 2007-08-01
- */
-rsRetVal
-doIncludeLine(rsconf_t *conf, uchar **pp, __attribute__((unused)) void* pVal)
-{
- DEFiRet;
- char pattern[MAXFNAME];
- uchar *cfgFile;
- glob_t cfgFiles;
- int result;
- size_t i = 0;
- struct stat fileInfo;
-
- ASSERT(pp != NULL);
- ASSERT(*pp != NULL);
-
- if(getSubString(pp, (char*) pattern, sizeof(pattern) / sizeof(char), ' ') != 0) {
- errmsg.LogError(0, RS_RET_NOT_FOUND, "could not parse config file name");
- ABORT_FINALIZE(RS_RET_NOT_FOUND);
- }
-
- /* Use GLOB_MARK to append a trailing slash for directories.
- * Required by doIncludeDirectory().
- */
- result = glob(pattern, GLOB_MARK, NULL, &cfgFiles);
- if(result == GLOB_NOSPACE || result == GLOB_ABORTED) {
- char errStr[1024];
- rs_strerror_r(errno, errStr, sizeof(errStr));
- errmsg.LogError(0, RS_RET_FILE_NOT_FOUND, "error accessing config file or directory '%s': %s",
- pattern, errStr);
- ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND);
- }
-
- for(i = 0; i < cfgFiles.gl_pathc; i++) {
- cfgFile = (uchar*) cfgFiles.gl_pathv[i];
-
- if(stat((char*) cfgFile, &fileInfo) != 0)
- continue; /* continue with the next file if we can't stat() the file */
-
- if(S_ISREG(fileInfo.st_mode)) { /* config file */
- dbgprintf("requested to include config file '%s'\n", cfgFile);
- iRet = processConfFile(conf, cfgFile);
- } else if(S_ISDIR(fileInfo.st_mode)) { /* config directory */
- dbgprintf("requested to include directory '%s'\n", cfgFile);
- iRet = doIncludeDirectory(conf, cfgFile);
- } else { /* TODO: shall we handle symlinks or not? */
- dbgprintf("warning: unable to process IncludeConfig directive '%s'\n", cfgFile);
- }
- }
-
- globfree(&cfgFiles);
-
-finalize_it:
- RETiRet;
-}
+EHostnameCmpMode eDfltHostnameCmpMode = HN_NO_COMP;
+cstr_t *pDfltHostnameCmp = NULL;
+cstr_t *pDfltProgNameCmp = NULL;
/* process a $ModLoad config line. */
@@ -354,7 +207,7 @@ finalize_it:
* 2004-11-17 rgerhards
*/
rsRetVal
-cfsysline(rsconf_t *conf, uchar *p)
+cfsysline(uchar *p)
{
DEFiRet;
uchar szCmd[64];
@@ -389,120 +242,6 @@ finalize_it:
}
-
-
-/* process a configuration file
- * started with code from init() by rgerhards on 2007-07-31
- */
-static rsRetVal
-processConfFile(rsconf_t *conf, uchar *pConfFile)
-{
- int iLnNbr = 0;
- FILE *cf;
- rule_t *pCurrRule = NULL;
- uchar *p;
- uchar cbuf[CFGLNSIZ];
- uchar *cline;
- int i;
- int bHadAnError = 0;
- uchar *pszOrgLine = NULL;
- size_t lenLine;
- DEFiRet;
- ASSERT(pConfFile != NULL);
-
- if((cf = fopen((char*)pConfFile, "r")) == NULL) {
- ABORT_FINALIZE(RS_RET_FOPEN_FAILURE);
- }
-
- /* Now process the file.
- */
- cline = cbuf;
- while (fgets((char*)cline, sizeof(cbuf) - (cline - cbuf), cf) != NULL) {
- ++iLnNbr;
- /* drop LF - TODO: make it better, replace fgets(), but its clean as it is */
- lenLine = ustrlen(cline);
- if(cline[lenLine-1] == '\n') {
- cline[lenLine-1] = '\0';
- }
- free(pszOrgLine);
- pszOrgLine = ustrdup(cline); /* save if needed for errmsg, NULL ptr is OK */
- /* check for end-of-section, comments, strip off trailing
- * spaces and newline character.
- */
- p = cline;
- skipWhiteSpace(&p);
- if (*p == '\0' || *p == '#')
- continue;
-
- /* we now need to copy the characters to the begin of line. As this overlaps,
- * we can not use strcpy(). -- rgerhards, 2008-03-20
- * TODO: review the code at whole - this is highly suspect (but will go away
- * once we do the rest of RainerScript).
- */
- for( i = 0 ; p[i] != '\0' ; ++i) {
- cline[i] = p[i];
- }
- cline[i] = '\0';
-
- for (p = (uchar*) strchr((char*)cline, '\0'); isspace((int) *--p);)
- /*EMPTY*/;
- if (*p == '\\') {
- if ((p - cbuf) > CFGLNSIZ - 30) {
- /* Oops the buffer is full - what now? */
- cline = cbuf;
- } else {
- *p = 0;
- cline = p;
- continue;
- }
- } else
- cline = cbuf;
- *++p = '\0'; /* TODO: check this */
-
- /* we now have the complete line, and are positioned at the first non-whitespace
- * character. So let's process it
- */
- if(cfline(conf, cbuf, &pCurrRule) != RS_RET_OK) {
- /* we log a message, but otherwise ignore the error. After all, the next
- * line can be correct. -- rgerhards, 2007-08-02
- */
- uchar szErrLoc[MAXFNAME + 64];
- dbgprintf("config line NOT successfully processed\n");
- snprintf((char*)szErrLoc, sizeof(szErrLoc) / sizeof(uchar),
- "%s, line %d", pConfFile, iLnNbr);
- errmsg.LogError(0, NO_ERRCODE, "the last error occured in %s:\"%s\"", (char*)szErrLoc, (char*)pszOrgLine);
- bHadAnError = 1;
- }
- }
-
- /* we probably have one selector left to be added - so let's do that now */
- if(pCurrRule != NULL) {
- CHKiRet(ruleset.AddRule(conf, rule.GetAssRuleset(pCurrRule), &pCurrRule));
- }
-
- /* close the configuration file */
- fclose(cf);
-
-finalize_it:
- if(iRet != RS_RET_OK) {
- char errStr[1024];
- if(pCurrRule != NULL)
- rule.Destruct(&pCurrRule);
-
- rs_strerror_r(errno, errStr, sizeof(errStr));
- dbgprintf("error %d processing config file '%s'; os error (if any): %s\n",
- iRet, pConfFile, errStr);
- }
-
- free(pszOrgLine);
-
- if(bHadAnError && (iRet == RS_RET_OK)) { /* a bit dirty, enhance in future releases */
- iRet = RS_RET_NONFATAL_CONFIG_ERR;
- }
- RETiRet;
-}
-
-
/* Helper to cfline() and its helpers. Parses a template name
* from an "action" line. Must be called with the Line pointer
* pointing to the first character after the semicolon.
@@ -602,7 +341,7 @@ cflineParseFileName(uchar* p, uchar *pFileName, omodStringRequest_t *pOMSR, int
* rgerhards 2005-09-15
*/
/* GPLv3 - stems back to sysklogd */
-static rsRetVal cflineProcessTradPRIFilter(uchar **pline, register rule_t *pRule)
+rsRetVal cflineProcessTradPRIFilter(uchar **pline, register rule_t *pRule)
{
uchar *p;
register uchar *q;
@@ -619,7 +358,7 @@ static rsRetVal cflineProcessTradPRIFilter(uchar **pline, register rule_t *pRule
ASSERT(*pline != NULL);
ISOBJ_TYPE_assert(pRule, rule);
- dbgprintf(" - traditional PRI filter\n");
+ dbgprintf(" - traditional PRI filter '%s'\n", *pline);
errno = 0; /* keep strerror_r() stuff out of logerror messages */
pRule->f_filter_type = FILTER_PRI;
@@ -632,7 +371,6 @@ static rsRetVal cflineProcessTradPRIFilter(uchar **pline, register rule_t *pRule
/* scan through the list of selectors */
for (p = *pline; *p && *p != '\t' && *p != ' ';) {
-
/* find the end of this facility name list */
for (q = p; *q && *q != '\t' && *q++ != '.'; )
continue;
@@ -643,8 +381,10 @@ static rsRetVal cflineProcessTradPRIFilter(uchar **pline, register rule_t *pRule
*bp = '\0';
/* skip cruft */
- while (strchr(",;", *q))
- q++;
+ if(*q) {
+ while (strchr(",;", *q))
+ q++;
+ }
/* decode priority name */
if ( *buf == '!' ) {
@@ -755,81 +495,12 @@ static rsRetVal cflineProcessTradPRIFilter(uchar **pline, register rule_t *pRule
}
-/* Helper to cfline(). This function processes an "if" type of filter,
- * what essentially means it parses an expression. As usual,
- * It processes the line up to the beginning of the action part.
- * A pointer to that beginnig is passed back to the caller.
- * rgerhards 2008-01-19
- */
-static rsRetVal cflineProcessIfFilter(uchar **pline, register rule_t *f)
-{
- DEFiRet;
- ctok_t *tok;
- ctok_token_t *pToken;
-
- ASSERT(pline != NULL);
- ASSERT(*pline != NULL);
- ASSERT(f != NULL);
-
- dbgprintf(" - general expression-based filter\n");
- errno = 0; /* keep strerror_r() stuff out of logerror messages */
-
- f->f_filter_type = FILTER_EXPR;
-
- /* if we come to over here, pline starts with "if ". We just skip that part. */
- (*pline) += 3;
-
- /* we first need a tokenizer... */
- CHKiRet(ctok.Construct(&tok));
- CHKiRet(ctok.Setpp(tok, *pline));
- CHKiRet(ctok.ConstructFinalize(tok));
-
- /* now construct our expression */
- CHKiRet(expr.Construct(&f->f_filterData.f_expr));
- CHKiRet(expr.ConstructFinalize(f->f_filterData.f_expr));
-
- /* ready to go... */
- CHKiRet(expr.Parse(f->f_filterData.f_expr, tok));
-
- /* we now need to parse off the "then" - and note an error if it is
- * missing...
- */
- CHKiRet(ctok.GetToken(tok, &pToken));
- if(pToken->tok != ctok_THEN) {
- ctok_token.Destruct(&pToken);
- ABORT_FINALIZE(RS_RET_SYNTAX_ERROR);
- }
-
- ctok_token.Destruct(&pToken); /* no longer needed */
-
- /* we are done, so we now need to restore things */
- CHKiRet(ctok.Getpp(tok, pline));
- CHKiRet(ctok.Destruct(&tok));
-
- /* debug support - print vmprg after construction (uncomment to use) */
- /* vmprgDebugPrint(f->f_filterData.f_expr->pVmprg); */
-
- /* we now need to skip whitespace to the action part, else we confuse
- * the legacy rsyslog conf parser. -- rgerhards, 2008-02-25
- */
- while(isspace(**pline))
- ++(*pline);
-
-finalize_it:
- if(iRet == RS_RET_SYNTAX_ERROR) {
- errmsg.LogError(0, RS_RET_SYNTAX_ERROR, "syntax error in expression");
- }
-
- RETiRet;
-}
-
-
/* Helper to cfline(). This function takes the filter part of a property
* based filter and decodes it. It processes the line up to the beginning
* of the action part. A pointer to that beginnig is passed back to the caller.
* rgerhards 2005-09-15
*/
-static rsRetVal cflineProcessPropFilter(uchar **pline, register rule_t *f)
+rsRetVal cflineProcessPropFilter(uchar **pline, register rule_t *f)
{
rsParsObj *pPars;
cstr_t *pCSCompOp;
@@ -841,7 +512,7 @@ static rsRetVal cflineProcessPropFilter(uchar **pline, register rule_t *f)
ASSERT(*pline != NULL);
ASSERT(f != NULL);
- dbgprintf(" - property-based filter\n");
+ dbgprintf(" - property-based filter '%s'\n", *pline);
errno = 0; /* keep strerror_r() stuff out of logerror messages */
f->f_filter_type = FILTER_PROP;
@@ -901,7 +572,6 @@ static rsRetVal cflineProcessPropFilter(uchar **pline, register rule_t *f)
iOffset = 0;
}
-dbgprintf("XXX: offset is %d, string '%s'\n", iOffset, rsCStrGetSzStrNoNULL(pCSCompOp));
if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "contains", 8)) {
f->f_filterData.prop.operation = FIOP_CONTAINS;
} else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "isequal", 7)) {
@@ -920,7 +590,6 @@ dbgprintf("XXX: offset is %d, string '%s'\n", iOffset, rsCStrGetSzStrNoNULL(pCSC
}
rsCStrDestruct(&pCSCompOp); /* no longer needed */
-dbgprintf("XXX: fiop is %u\n", (unsigned) f->f_filterData.prop.operation);
if(f->f_filterData.prop.operation != FIOP_ISEMPTY) {
/* read compare value */
iRet = parsQuotedCStr(pPars, &f->f_filterData.prop.pCSCompValue);
@@ -951,7 +620,7 @@ dbgprintf("XXX: fiop is %u\n", (unsigned) f->f_filterData.prop.operation);
* from the config file ("+/-hostname"). It stores it for further reference.
* rgerhards 2005-10-19
*/
-static rsRetVal cflineProcessHostSelector(rsconf_t *conf, uchar **pline)
+rsRetVal cflineProcessHostSelector(uchar **pline)
{
DEFiRet;
@@ -1001,7 +670,7 @@ finalize_it:
* from the config file ("!tagname"). It stores it for further reference.
* rgerhards 2005-10-18
*/
-static rsRetVal cflineProcessTagSelector(rsconf_t *conf, uchar **pline)
+rsRetVal cflineProcessTagSelector(uchar **pline)
{
DEFiRet;
@@ -1039,6 +708,7 @@ finalize_it:
}
+#if 0
/* read the filter part of a configuration line and store the filter
* in the supplied rule_t
* rgerhards, 2007-08-01
@@ -1055,12 +725,6 @@ static rsRetVal cflineDoFilter(uchar **pp, rule_t *f)
case ':':
CHKiRet(cflineProcessPropFilter(pp, f));
break;
- case 'i': /* "if" filter? */
- if(*(*pp+1) && (*(*pp+1) == 'f') && isspace(*(*pp+2))) {
- CHKiRet(cflineProcessIfFilter(pp, f));
- break;
- }
- /*FALLTHROUGH*/
default:
CHKiRet(cflineProcessTradPRIFilter(pp, f));
break;
@@ -1081,12 +745,13 @@ static rsRetVal cflineDoFilter(uchar **pp, rule_t *f)
finalize_it:
RETiRet;
}
+#endif
/* process the action part of a selector line
* rgerhards, 2007-08-01
*/
-static rsRetVal cflineDoAction(rsconf_t *conf, uchar **p, action_t **ppAction)
+rsRetVal cflineDoAction(rsconf_t *conf, uchar **p, action_t **ppAction)
{
modInfo_t *pMod;
cfgmodules_etry_t *node;
@@ -1147,6 +812,7 @@ static rsRetVal cflineDoAction(rsconf_t *conf, uchar **p, action_t **ppAction)
}
+#if 0
/* Process a configuration file line in traditional "filter selector" format
* or one that builds upon this format. Note that ppRule may be a NULL pointer,
* which is valid and happens if there is no previous line (right at the start
@@ -1207,15 +873,15 @@ cfline(rsconf_t *conf, uchar *line, rule_t **pfCurr)
/* check type of line and call respective processing */
switch(*line) {
case '!':
- iRet = cflineProcessTagSelector(conf, &line);
+ iRet = cflineProcessTagSelector(&line);
break;
case '+':
case '-':
- iRet = cflineProcessHostSelector(conf, &line);
+ iRet = cflineProcessHostSelector(&line);
break;
case '$':
++line; /* eat '$' */
- iRet = cfsysline(conf, line);
+ iRet = cfsysline(line);
break;
default:
iRet = cflineClassic(conf, line, pfCurr);
@@ -1224,6 +890,7 @@ cfline(rsconf_t *conf, uchar *line, rule_t **pfCurr)
RETiRet;
}
+#endif
/* return the current number of active actions
@@ -1256,9 +923,6 @@ CODESTARTobjQueryInterface(conf)
pIf->doNameLine = doNameLine;
pIf->cfsysline = cfsysline;
pIf->doModLoad = doModLoad;
- pIf->doIncludeLine = doIncludeLine;
- pIf->cfline = cfline;
- pIf->processConfFile = processConfFile;
pIf->GetNbrActActions = GetNbrActActions;
finalize_it:
@@ -1410,9 +1074,6 @@ CODESTARTObjClassExit(conf)
}
/* release objects we no longer need */
- objRelease(expr, CORE_COMPONENT);
- objRelease(ctok, CORE_COMPONENT);
- objRelease(ctok_token, CORE_COMPONENT);
objRelease(module, CORE_COMPONENT);
objRelease(errmsg, CORE_COMPONENT);
objRelease(net, LM_NET_FILENAME);
@@ -1427,9 +1088,6 @@ ENDObjClassExit(conf)
*/
BEGINAbstractObjClassInit(conf, 1, OBJ_IS_CORE_MODULE) /* class, version - CHANGE class also in END MACRO! */
/* request objects we use */
- CHKiRet(objUse(expr, CORE_COMPONENT));
- CHKiRet(objUse(ctok, CORE_COMPONENT));
- CHKiRet(objUse(ctok_token, CORE_COMPONENT));
CHKiRet(objUse(module, CORE_COMPONENT));
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(net, LM_NET_FILENAME)); /* TODO: make this dependcy go away! */
diff --git a/runtime/conf.h b/runtime/conf.h
index 096af630..9253e880 100644
--- a/runtime/conf.h
+++ b/runtime/conf.h
@@ -21,6 +21,7 @@
*/
#ifndef INCLUDED_CONF_H
#define INCLUDED_CONF_H
+#include "action.h"
/* definitions used for doNameLine to differentiate between different command types
* (with otherwise identical code). This is a left-over from the previous config
@@ -34,11 +35,8 @@ extern int bConfStrictScoping; /* force strict scoping during config processing?
/* interfaces */
BEGINinterface(conf) /* name must also be changed in ENDinterface macro! */
rsRetVal (*doNameLine)(uchar **pp, void* pVal);
- rsRetVal (*cfsysline)(rsconf_t *conf, uchar *p);
+ rsRetVal (*cfsysline)(uchar *p);
rsRetVal (*doModLoad)(uchar **pp, __attribute__((unused)) void* pVal);
- rsRetVal (*doIncludeLine)(rsconf_t *conf, uchar **pp, __attribute__((unused)) void* pVal);
- rsRetVal (*cfline)(rsconf_t *conf, uchar *line, rule_t **pfCurr);
- rsRetVal (*processConfFile)(rsconf_t *conf, uchar *pConfFile);
rsRetVal (*GetNbrActActions)(rsconf_t *conf, int *);
/* version 4 -- 2010-07-23 rgerhards */
/* "just" added global variables
@@ -48,8 +46,10 @@ BEGINinterface(conf) /* name must also be changed in ENDinterface macro! */
*/
/* version 5 -- 2011-04-19 rgerhards */
/* complete revamp, we now use the rsconf object */
+ /* version 6 -- 2011-07-06 rgerhards */
+ /* again a complete revamp, using flex/bison based parser now */
ENDinterface(conf)
-#define confCURR_IF_VERSION 5 /* increment whenever you change the interface structure! */
+#define confCURR_IF_VERSION 6 /* increment whenever you change the interface structure! */
/* in Version 3, entry point "ReInitConf()" was removed, as we do not longer need
* to support restart-type HUP -- rgerhards, 2009-07-15
*/
@@ -63,5 +63,14 @@ PROTOTYPEObj(conf);
rsRetVal cflineParseTemplateName(uchar** pp, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts, uchar *dfltTplName);
rsRetVal cflineParseFileName(uchar* p, uchar *pFileName, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts, uchar *pszTpl);
+/* more dirt to cover the new config interface (will go away...) */
+rsRetVal cflineProcessTagSelector(uchar **pline);
+rsRetVal cflineProcessHostSelector(uchar **pline);
+rsRetVal cflineProcessTradPRIFilter(uchar **pline, rule_t *pRule);
+rsRetVal cflineProcessPropFilter(uchar **pline, rule_t *f);
+rsRetVal cflineDoAction(rsconf_t *conf, uchar **p, action_t **ppAction);
+extern EHostnameCmpMode eDfltHostnameCmpMode;
+extern cstr_t *pDfltHostnameCmp;
+extern cstr_t *pDfltProgNameCmp;
#endif /* #ifndef INCLUDED_CONF_H */
diff --git a/runtime/ctok.c b/runtime/ctok.c
deleted file mode 100644
index 19c9bd24..00000000
--- a/runtime/ctok.c
+++ /dev/null
@@ -1,629 +0,0 @@
-/* ctok.c - helper class to tokenize an input stream - which surprisingly
- * currently does not work with streams but with string. But that will
- * probably change over time ;) This class was originally written to support
- * the expression module but may evolve when (if) the expression module is
- * expanded (or aggregated) by a full-fledged ctoken based config parser.
- * Obviously, this class is used together with config files and not any other
- * parse function.
- *
- * Module begun 2008-02-19 by Rainer Gerhards
- *
- * Copyright (C) 2008 by Rainer Gerhards and Adiscon GmbH.
- *
- * This file is part of the rsyslog runtime library.
- *
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
- */
-
-#include "config.h"
-#include <stdlib.h>
-#include <ctype.h>
-#include <strings.h>
-#include <assert.h>
-
-#include "rsyslog.h"
-#include "template.h"
-#include "ctok.h"
-
-/* static data */
-DEFobjStaticHelpers
-DEFobjCurrIf(ctok_token)
-DEFobjCurrIf(var)
-
-
-/* Standard-Constructor
- */
-BEGINobjConstruct(ctok) /* be sure to specify the object type also in END macro! */
-ENDobjConstruct(ctok)
-
-
-/* ConstructionFinalizer
- * rgerhards, 2008-01-09
- */
-rsRetVal ctokConstructFinalize(ctok_t __attribute__((unused)) *pThis)
-{
- DEFiRet;
- RETiRet;
-}
-
-
-/* destructor for the ctok object */
-BEGINobjDestruct(ctok) /* be sure to specify the object type also in END and CODESTART macros! */
-CODESTARTobjDestruct(ctok)
- /* ... then free resources */
-ENDobjDestruct(ctok)
-
-
-/* unget character from input stream. At most one character can be ungotten.
- * This funtion is only permitted to be called after at least one character
- * has been read from the stream. Right now, we handle the situation simply by
- * moving the string "stream" pointer one position backwards. If we work with
- * real streams (some time), the strm object will handle the functionality
- * itself. -- rgerhards, 2008-02-19
- */
-static rsRetVal
-ctokUngetCharFromStream(ctok_t *pThis, uchar __attribute__((unused)) c)
-{
- DEFiRet;
-
- ISOBJ_TYPE_assert(pThis, ctok);
- --pThis->pp;
-
- RETiRet;
-}
-
-
-/* get the next character from the input "stream". Note that this version
- * does NOT look for comment characters as end-of-stream, so it is suitable
- * when building constant strings! -- rgerhards, 2010-03-01
- */
-static inline rsRetVal
-ctokGetCharFromStreamNoComment(ctok_t *pThis, uchar *pc)
-{
- DEFiRet;
-
- ISOBJ_TYPE_assert(pThis, ctok);
- ASSERT(pc != NULL);
-
- /* end of string or begin of comment terminates the "stream" */
- if(*pThis->pp == '\0') {
- ABORT_FINALIZE(RS_RET_EOS);
- } else {
- *pc = *pThis->pp;
- ++pThis->pp;
- }
-
-finalize_it:
- RETiRet;
-}
-
-
-/* get the next character from the input "stream" (currently just a in-memory
- * string...) -- rgerhards, 2008-02-19
- */
-static rsRetVal
-ctokGetCharFromStream(ctok_t *pThis, uchar *pc)
-{
- DEFiRet;
-
- ISOBJ_TYPE_assert(pThis, ctok);
- ASSERT(pc != NULL);
-
- CHKiRet(ctokGetCharFromStreamNoComment(pThis, pc));
- /* begin of comment terminates the "stream"! */
- if(*pc == '#') {
- ABORT_FINALIZE(RS_RET_EOS);
- }
-
-finalize_it:
- RETiRet;
-}
-
-
-/* skip whitespace in the input "stream".
- * rgerhards, 2008-02-19
- */
-static rsRetVal
-ctokSkipWhitespaceFromStream(ctok_t *pThis)
-{
- DEFiRet;
- uchar c;
-
- ISOBJ_TYPE_assert(pThis, ctok);
-
- CHKiRet(ctokGetCharFromStream(pThis, &c));
- while(isspace(c)) {
- CHKiRet(ctokGetCharFromStream(pThis, &c));
- }
-
- /* we must unget the one non-whitespace we found */
- CHKiRet(ctokUngetCharFromStream(pThis, c));
-
-dbgprintf("skipped whitespace, stream now '%s'\n", pThis->pp);
-finalize_it:
- RETiRet;
-}
-
-
-/* get the next word from the input "stream" (currently just a in-memory
- * string...). A word is anything from the current location until the
- * first non-alphanumeric character. If the word is longer
- * than the provided memory buffer, parsing terminates when buffer length
- * has been reached. A buffer of 128 bytes or more should always be by
- * far sufficient. -- rgerhards, 2008-02-19
- */
-static rsRetVal
-ctokGetWordFromStream(ctok_t *pThis, uchar *pWordBuf, size_t lenWordBuf)
-{
- DEFiRet;
- uchar c;
-
- ISOBJ_TYPE_assert(pThis, ctok);
- ASSERT(pWordBuf != NULL);
- ASSERT(lenWordBuf > 0);
-
- CHKiRet(ctokSkipWhitespaceFromStream(pThis));
-
- CHKiRet(ctokGetCharFromStream(pThis, &c));
- while((isalnum(c) || c == '_' || c == '-') && lenWordBuf > 1) {
- *pWordBuf++ = c;
- --lenWordBuf;
- CHKiRet(ctokGetCharFromStream(pThis, &c));
- }
- *pWordBuf = '\0'; /* there is always space for this - see while() */
-
- /* push back the char that we have read too much */
- CHKiRet(ctokUngetCharFromStream(pThis, c));
-
-finalize_it:
- RETiRet;
-}
-
-
-/* read in a constant number
- * This is the "number" ABNF element
- * rgerhards, 2008-02-19
- */
-static rsRetVal
-ctokGetNumber(ctok_t *pThis, ctok_token_t *pToken)
-{
- DEFiRet;
- number_t n; /* the parsed number */
- uchar c;
- int valC;
- int iBase;
-
- ISOBJ_TYPE_assert(pThis, ctok);
- ASSERT(pToken != NULL);
-
- pToken->tok = ctok_NUMBER;
-
- CHKiRet(ctokGetCharFromStream(pThis, &c));
- if(c == '0') { /* octal? */
- CHKiRet(ctokGetCharFromStream(pThis, &c));
- if(c == 'x') { /* nope, hex! */
- CHKiRet(ctokGetCharFromStream(pThis, &c));
- c = tolower(c);
- iBase = 16;
- } else {
- iBase = 8;
- }
- } else {
- iBase = 10;
- }
-
- n = 0;
- /* this loop is quite simple, a variable name is terminated by whitespace. */
- while(isdigit(c) || (c >= 'a' && c <= 'f')) {
- if(isdigit(c)) {
- valC = c - '0';
- } else {
- valC = c - 'a' + 10;
- }
-
- if(valC >= iBase) {
- if(iBase == 8) {
- ABORT_FINALIZE(RS_RET_INVALID_OCTAL_DIGIT);
- } else {
- ABORT_FINALIZE(RS_RET_INVALID_HEX_DIGIT);
- }
- }
- /* we now have the next value and know it is right */
- n = n * iBase + valC;
- CHKiRet(ctokGetCharFromStream(pThis, &c));
- c = tolower(c);
- }
-
- /* we need to unget the character that made the loop terminate */
- CHKiRet(ctokUngetCharFromStream(pThis, c));
-
- CHKiRet(var.SetNumber(pToken->pVar, n));
-
-finalize_it:
- RETiRet;
-}
-
-
-/* read in a variable
- * This covers both msgvar and sysvar from the ABNF.
- * rgerhards, 2008-02-19
- */
-static rsRetVal
-ctokGetVar(ctok_t *pThis, ctok_token_t *pToken)
-{
- DEFiRet;
- uchar c;
- cstr_t *pstrVal = NULL;
-
- ISOBJ_TYPE_assert(pThis, ctok);
- ASSERT(pToken != NULL);
-
- CHKiRet(ctokGetCharFromStream(pThis, &c));
-
- if(c == '$') { /* second dollar, we have a system variable */
- pToken->tok = ctok_SYSVAR;
- CHKiRet(ctokGetCharFromStream(pThis, &c)); /* "eat" it... */
- } else if(c == '!') { /* cee variable indicator */
- pToken->tok = ctok_CEEVAR;
- CHKiRet(ctokGetCharFromStream(pThis, &c)); /* "eat" it... */
- } else {
- pToken->tok = ctok_MSGVAR;
- }
-
- CHKiRet(cstrConstruct(&pstrVal));
- /* this loop is quite simple, a variable name is terminated when a non-supported
- * character is detected. Note that we currently permit a numerical digit as the
- * first char, which is not permitted by ABNF. -- rgerhards, 2009-03-10
- */
- while(isalpha(c) || isdigit(c) || (c == '_') || (c == '-')) {
- CHKiRet(cstrAppendChar(pstrVal, tolower(c)));
- CHKiRet(ctokGetCharFromStream(pThis, &c));
- }
- CHKiRet(ctokUngetCharFromStream(pThis, c)); /* put not processed char back */
-
- CHKiRet(cstrFinalize(pstrVal));
-
- CHKiRet(var.SetString(pToken->pVar, pstrVal));
- pstrVal = NULL;
-
-finalize_it:
- if(iRet != RS_RET_OK) {
- if(pstrVal != NULL) {
- cstrDestruct(&pstrVal);
- }
- }
-
- RETiRet;
-}
-
-
-/* read in a simple string (simpstr in ABNF)
- * rgerhards, 2008-02-19
- */
-static rsRetVal
-ctokGetSimpStr(ctok_t *pThis, ctok_token_t *pToken)
-{
- DEFiRet;
- uchar c;
- int bInEsc = 0;
- cstr_t *pstrVal;
-
- ISOBJ_TYPE_assert(pThis, ctok);
- ASSERT(pToken != NULL);
-
- pToken->tok = ctok_SIMPSTR;
-
- CHKiRet(cstrConstruct(&pstrVal));
- CHKiRet(ctokGetCharFromStreamNoComment(pThis, &c));
- /* while we are in escape mode (had a backslash), no sequence
- * terminates the loop. If outside, it is terminated by a single quote.
- */
- while(bInEsc || c != '\'') {
- if(bInEsc) {
- CHKiRet(cstrAppendChar(pstrVal, c));
- bInEsc = 0;
- } else {
- if(c == '\\') {
- bInEsc = 1;
- } else {
- CHKiRet(cstrAppendChar(pstrVal, c));
- }
- }
- CHKiRet(ctokGetCharFromStreamNoComment(pThis, &c));
- }
- CHKiRet(cstrFinalize(pstrVal));
-
- CHKiRet(var.SetString(pToken->pVar, pstrVal));
- pstrVal = NULL;
-
-finalize_it:
- if(iRet != RS_RET_OK) {
- if(pstrVal != NULL) {
- cstrDestruct(&pstrVal);
- }
- }
-
- RETiRet;
-}
-
-
-/* Unget a token. The token ungotten will be returned the next time
- * ctokGetToken() is called. Only one token can be ungotten at a time.
- * If a second token is ungotten, the first is lost. This is considered
- * a programming error.
- * rgerhards, 2008-02-20
- */
-static rsRetVal
-ctokUngetToken(ctok_t *pThis, ctok_token_t *pToken)
-{
- DEFiRet;
-
- ISOBJ_TYPE_assert(pThis, ctok);
- ASSERT(pToken != NULL);
- ASSERT(pThis->pUngotToken == NULL);
-
- pThis->pUngotToken = pToken;
-
- RETiRet;
-}
-
-
-/* skip an inine comment (just like a C-comment)
- * rgerhards, 2008-02-20
- */
-static rsRetVal
-ctokSkipInlineComment(ctok_t *pThis)
-{
- DEFiRet;
- uchar c;
- int bHadAsterisk = 0;
-
- ISOBJ_TYPE_assert(pThis, ctok);
-
- CHKiRet(ctokGetCharFromStream(pThis, &c)); /* read a charater */
- while(!(bHadAsterisk && c == '/')) {
- bHadAsterisk = (c == '*') ? 1 : 0;
- CHKiRet(ctokGetCharFromStream(pThis, &c)); /* read next */
- }
-
-finalize_it:
- RETiRet;
-}
-
-
-
-/* Get the *next* token from the input stream. This parses the next token and
- * ignores any whitespace in between. End of stream is communicated via iRet.
- * The returned token must either be destructed by the caller OR being passed
- * back to ctokUngetToken().
- * rgerhards, 2008-02-19
- */
-static rsRetVal
-ctokGetToken(ctok_t *pThis, ctok_token_t **ppToken)
-{
- DEFiRet;
- ctok_token_t *pToken;
- uchar c;
- uchar szWord[128];
- int bRetry = 0; /* retry parse? Only needed for inline comments... */
- cstr_t *pstrVal;
-
- ISOBJ_TYPE_assert(pThis, ctok);
- ASSERT(ppToken != NULL);
-
- /* first check if we have an ungotten token and, if so, provide that
- * one back (without any parsing). -- rgerhards, 2008-02-20
- */
- if(pThis->pUngotToken != NULL) {
- *ppToken = pThis->pUngotToken;
- pThis->pUngotToken = NULL;
- FINALIZE;
- }
-
- /* setup the stage - create our token */
- CHKiRet(ctok_token.Construct(&pToken));
- CHKiRet(ctok_token.ConstructFinalize(pToken));
-
- /* find the next token. We may loop when we have inline comments */
- do {
- bRetry = 0;
- CHKiRet(ctokSkipWhitespaceFromStream(pThis));
- CHKiRet(ctokGetCharFromStream(pThis, &c)); /* read a charater */
- switch(c) {
- case '=': /* == */
- CHKiRet(ctokGetCharFromStream(pThis, &c)); /* read a character */
- pToken->tok = (c == '=')? ctok_CMP_EQ : ctok_INVALID;
- break;
- case '!': /* != */
- CHKiRet(ctokGetCharFromStream(pThis, &c)); /* read a character */
- pToken->tok = (c == '=')? ctok_CMP_NEQ : ctok_INVALID;
- break;
- case '<': /* <, <=, <> */
- CHKiRet(ctokGetCharFromStream(pThis, &c)); /* read a character */
- if(c == '=') {
- pToken->tok = ctok_CMP_LTEQ;
- } else if(c == '>') {
- pToken->tok = ctok_CMP_NEQ;
- } else {
- pToken->tok = ctok_CMP_LT;
- }
- break;
- case '>': /* >, >= */
- CHKiRet(ctokGetCharFromStream(pThis, &c)); /* read a character */
- if(c == '=') {
- pToken->tok = ctok_CMP_GTEQ;
- } else {
- pToken->tok = ctok_CMP_GT;
- }
- break;
- case '+':
- pToken->tok = ctok_PLUS;
- break;
- case '-':
- pToken->tok = ctok_MINUS;
- break;
- case '*':
- pToken->tok = ctok_TIMES;
- break;
- case '/': /* /, /.* ... *./ (comments, mungled here for obvious reasons...) */
- CHKiRet(ctokGetCharFromStream(pThis, &c)); /* read a charater */
- if(c == '*') {
- /* we have a comment and need to skip it */
- ctokSkipInlineComment(pThis);
- bRetry = 1;
- } else {
- CHKiRet(ctokUngetCharFromStream(pThis, c)); /* put back, not processed */
- }
- pToken->tok = ctok_DIV;
- break;
- case '%':
- pToken->tok = ctok_MOD;
- break;
- case '(':
- pToken->tok = ctok_LPAREN;
- break;
- case ')':
- pToken->tok = ctok_RPAREN;
- break;
- case ',':
- pToken->tok = ctok_COMMA;
- break;
- case '&':
- pToken->tok = ctok_STRADD;
- break;
- case '$':
- CHKiRet(ctokGetVar(pThis, pToken));
- break;
- case '\'': /* simple string, this is somewhat more elaborate */
- CHKiRet(ctokGetSimpStr(pThis, pToken));
- break;
- case '"':
- /* TODO: template string parser */
- ABORT_FINALIZE(RS_RET_NOT_IMPLEMENTED);
- break;
- default:
- CHKiRet(ctokUngetCharFromStream(pThis, c)); /* push back, we need it in any case */
- if(isdigit(c)) {
- CHKiRet(ctokGetNumber(pThis, pToken));
- } else { /* now we check if we have a multi-char sequence */
- CHKiRet(ctokGetWordFromStream(pThis, szWord, sizeof(szWord)/sizeof(uchar)));
- if(!strcasecmp((char*)szWord, "and")) {
- pToken->tok = ctok_AND;
- } else if(!strcasecmp((char*)szWord, "or")) {
- pToken->tok = ctok_OR;
- } else if(!strcasecmp((char*)szWord, "not")) {
- pToken->tok = ctok_NOT;
- } else if(!strcasecmp((char*)szWord, "contains")) {
- pToken->tok = ctok_CMP_CONTAINS;
- } else if(!strcasecmp((char*)szWord, "contains_i")) {
- pToken->tok = ctok_CMP_CONTAINSI;
- } else if(!strcasecmp((char*)szWord, "startswith")) {
- pToken->tok = ctok_CMP_STARTSWITH;
- } else if(!strcasecmp((char*)szWord, "startswith_i")) {
- pToken->tok = ctok_CMP_STARTSWITHI;
- } else if(!strcasecmp((char*)szWord, "then")) {
- pToken->tok = ctok_THEN;
- } else {
- /* finally, we check if it is a function */
- CHKiRet(ctokGetCharFromStream(pThis, &c)); /* read a charater */
- if(c == '(') {
- /* push c back, higher level parser needs it */
- CHKiRet(ctokUngetCharFromStream(pThis, c));
- pToken->tok = ctok_FUNCTION;
- /* fill function name */
- CHKiRet(cstrConstruct(&pstrVal));
- CHKiRet(rsCStrSetSzStr(pstrVal, szWord));
- CHKiRet(cstrFinalize(pstrVal));
- CHKiRet(var.SetString(pToken->pVar, pstrVal));
- } else { /* give up... */
- dbgprintf("parser has an invalid word (token) '%s'\n", szWord);
- pToken->tok = ctok_INVALID;
- }
- }
- }
- break;
- }
- } while(bRetry); /* warning: do ... while()! */
-
- *ppToken = pToken;
- dbgoprint((obj_t*) pToken, "token: %d\n", pToken->tok);
-
-finalize_it:
-/*dbgprintf("ctokGetToken, returns %d, returns token %d, addr %p\n", iRet, (*ppToken)->tok, &((*ppToken)->tok));*/
- if(iRet != RS_RET_OK) {
- if(pToken != NULL)
- ctok_token.Destruct(&pToken);
- }
-
- RETiRet;
-}
-
-
-/* property set methods */
-/* simple ones first */
-DEFpropSetMeth(ctok, pp, uchar*)
-
-/* return the current position of pp - most important as currently we do only
- * partial parsing, so the rest must know where to start from...
- * rgerhards, 2008-02-19
- */
-static rsRetVal
-ctokGetpp(ctok_t *pThis, uchar **pp)
-{
- DEFiRet;
- ASSERT(pp != NULL);
- *pp = pThis->pp;
- RETiRet;
-}
-
-
-/* queryInterface function
- * rgerhards, 2008-02-21
- */
-BEGINobjQueryInterface(ctok)
-CODESTARTobjQueryInterface(ctok)
- if(pIf->ifVersion != ctokCURR_IF_VERSION) { /* check for current version, increment on each change */
- ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
- }
-
- /* ok, we have the right interface, so let's fill it
- * Please note that we may also do some backwards-compatibility
- * work here (if we can support an older interface version - that,
- * of course, also affects the "if" above).
- */
- pIf->Construct = ctokConstruct;
- pIf->ConstructFinalize = ctokConstructFinalize;
- pIf->Destruct = ctokDestruct;
- pIf->Getpp = ctokGetpp;
- pIf->GetToken = ctokGetToken;
- pIf->UngetToken = ctokUngetToken;
- pIf->Setpp = ctokSetpp;
-finalize_it:
-ENDobjQueryInterface(ctok)
-
-
-
-BEGINObjClassInit(ctok, 1, OBJ_IS_CORE_MODULE) /* class, version */
- /* request objects we use */
- CHKiRet(objUse(ctok_token, CORE_COMPONENT));
- CHKiRet(objUse(var, CORE_COMPONENT));
-
- OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, ctokConstructFinalize);
-ENDObjClassInit(ctok)
-
-/* vi:set ai:
- */
diff --git a/runtime/ctok.h b/runtime/ctok.h
deleted file mode 100644
index 591f0838..00000000
--- a/runtime/ctok.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* The ctok object (implements a config file tokenizer).
- *
- * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
- *
- * This file is part of the rsyslog runtime library.
- *
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
- */
-#ifndef INCLUDED_CTOK_H
-#define INCLUDED_CTOK_H
-
-#include "obj.h"
-#include "stringbuf.h"
-#include "ctok_token.h"
-
-/* the ctokession object */
-typedef struct ctok_s {
- BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
- uchar *pp; /* this points to the next unread character, it is a reminescent of pp in
- the config parser code ;) */
- ctok_token_t *pUngotToken; /* buffer for ctokUngetToken(), NULL if not set */
-} ctok_t;
-
-
-/* interfaces */
-BEGINinterface(ctok) /* name must also be changed in ENDinterface macro! */
- INTERFACEObjDebugPrint(ctok);
- INTERFACEpropSetMeth(ctok, pp, uchar*);
- rsRetVal (*Construct)(ctok_t **ppThis);
- rsRetVal (*ConstructFinalize)(ctok_t __attribute__((unused)) *pThis);
- rsRetVal (*Destruct)(ctok_t **ppThis);
- rsRetVal (*Getpp)(ctok_t *pThis, uchar **pp);
- rsRetVal (*GetToken)(ctok_t *pThis, ctok_token_t **ppToken);
- rsRetVal (*UngetToken)(ctok_t *pThis, ctok_token_t *pToken);
-ENDinterface(ctok)
-#define ctokCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
-
-
-/* prototypes */
-PROTOTYPEObj(ctok);
-
-#endif /* #ifndef INCLUDED_CTOK_H */
diff --git a/runtime/ctok_token.c b/runtime/ctok_token.c
deleted file mode 100644
index 8c17f693..00000000
--- a/runtime/ctok_token.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/* ctok_token - implements the token_t class.
- *
- * Module begun 2008-02-20 by Rainer Gerhards
- *
- * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
- *
- * This file is part of the rsyslog runtime library.
- *
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
- */
-
-#include "config.h"
-#include <stdlib.h>
-#include <ctype.h>
-#include <strings.h>
-#include <assert.h>
-
-#include "rsyslog.h"
-#include "template.h"
-#include "ctok_token.h"
-
-/* static data */
-DEFobjStaticHelpers
-DEFobjCurrIf(var)
-
-
-/* Standard-Constructor
- */
-BEGINobjConstruct(ctok_token) /* be sure to specify the object type also in END macro! */
- /* TODO: we may optimize the code below and alloc var only if actually
- * needed (but we need it quite often)
- */
- CHKiRet(var.Construct(&pThis->pVar));
- CHKiRet(var.ConstructFinalize(pThis->pVar));
-finalize_it:
-ENDobjConstruct(ctok_token)
-
-
-/* ConstructionFinalizer
- * rgerhards, 2008-01-09
- */
-rsRetVal ctok_tokenConstructFinalize(ctok_token_t __attribute__((unused)) *pThis)
-{
- DEFiRet;
- RETiRet;
-}
-
-
-/* destructor for the ctok object */
-BEGINobjDestruct(ctok_token) /* be sure to specify the object type also in END and CODESTART macros! */
-CODESTARTobjDestruct(ctok_token)
- if(pThis->pVar != NULL) {
- var.Destruct(&pThis->pVar);
- }
-ENDobjDestruct(ctok_token)
-
-
-/* get the cstr_t from the token, but do not destruct it. This is meant to
- * be used by a caller who passes on the string to some other function. The
- * caller is responsible for destructing it.
- * rgerhards, 2008-02-20
- */
-static rsRetVal
-ctok_tokenUnlinkVar(ctok_token_t *pThis, var_t **ppVar)
-{
- DEFiRet;
-
- ISOBJ_TYPE_assert(pThis, ctok_token);
- ASSERT(ppVar != NULL);
-
- *ppVar = pThis->pVar;
- pThis->pVar = NULL;
-
- RETiRet;
-}
-
-
-/* tell the caller if the supplied token is a compare operation */
-static int ctok_tokenIsCmpOp(ctok_token_t *pThis)
-{
- return(pThis->tok >= ctok_CMP_EQ && pThis->tok <= ctok_CMP_GTEQ);
-}
-
-/* queryInterface function
- * rgerhards, 2008-02-21
- */
-BEGINobjQueryInterface(ctok_token)
-CODESTARTobjQueryInterface(ctok_token)
- if(pIf->ifVersion != ctok_tokenCURR_IF_VERSION) { /* check for current version, increment on each change */
- ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
- }
-
- /* ok, we have the right interface, so let's fill it
- * Please note that we may also do some backwards-compatibility
- * work here (if we can support an older interface version - that,
- * of course, also affects the "if" above).
- */
- pIf->Construct = ctok_tokenConstruct;
- pIf->ConstructFinalize = ctok_tokenConstructFinalize;
- pIf->Destruct = ctok_tokenDestruct;
- pIf->UnlinkVar = ctok_tokenUnlinkVar;
- pIf->IsCmpOp = ctok_tokenIsCmpOp;
-finalize_it:
-ENDobjQueryInterface(ctok_token)
-
-
-BEGINObjClassInit(ctok_token, 1, OBJ_IS_CORE_MODULE) /* class, version */
- /* request objects we use */
- CHKiRet(objUse(var, CORE_COMPONENT));
-
- OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, ctok_tokenConstructFinalize);
-ENDObjClassInit(ctok_token)
-
-/* vi:set ai:
- */
diff --git a/runtime/ctok_token.h b/runtime/ctok_token.h
deleted file mode 100644
index 1413c699..00000000
--- a/runtime/ctok_token.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* The ctok_token object
- *
- * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
- *
- * This file is part of the rsyslog runtime library.
- *
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
- */
-#ifndef INCLUDED_CTOK_TOKEN_H
-#define INCLUDED_CTOK_TOKEN_H
-
-#include "obj.h"
-#include "var.h"
-
-/* the tokens... I use numbers below so that the tokens can be easier
- * identified in debug output. These ID's are also partly resused as opcodes.
- * As such, they should be kept below 1,000 so that they do not interfer
- * with the rest of the opcodes.
- */
-typedef struct {
- BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
- enum {
- ctok_INVALID = 0,
- ctok_OR = 1,
- ctok_AND = 2,
- ctok_PLUS = 3,
- ctok_MINUS = 4,
- ctok_TIMES = 5, /* "*" */
- ctok_DIV = 6,
- ctok_MOD = 7,
- ctok_NOT = 8,
- ctok_RPAREN = 9,
- ctok_LPAREN = 10,
- ctok_COMMA = 11,
- ctok_SYSVAR = 12,
- ctok_MSGVAR = 13,
- ctok_SIMPSTR = 14,
- ctok_TPLSTR = 15,
- ctok_NUMBER = 16,
- ctok_FUNCTION = 17,
- ctok_THEN = 18,
- ctok_STRADD = 19,
- ctok_CEEVAR = 20,
- ctok_CMP_EQ = 100, /* all compare operations must be in a row */
- ctok_CMP_NEQ = 101,
- ctok_CMP_LT = 102,
- ctok_CMP_GT = 103,
- ctok_CMP_LTEQ = 104,
- ctok_CMP_CONTAINS = 105,
- ctok_CMP_STARTSWITH = 106,
- ctok_CMP_CONTAINSI = 107,
- ctok_CMP_STARTSWITHI = 108,
- ctok_CMP_GTEQ = 109 /* end compare operations */
- } tok;
- var_t *pVar;
-} ctok_token_t;
-
-
-/* interfaces */
-BEGINinterface(ctok_token) /* name must also be changed in ENDinterface macro! */
- INTERFACEObjDebugPrint(ctok_token);
- rsRetVal (*Construct)(ctok_token_t **ppThis);
- rsRetVal (*ConstructFinalize)(ctok_token_t __attribute__((unused)) *pThis);
- rsRetVal (*Destruct)(ctok_token_t **ppThis);
- rsRetVal (*UnlinkVar)(ctok_token_t *pThis, var_t **ppVar);
- int (*IsCmpOp)(ctok_token_t *pThis);
-ENDinterface(ctok_token)
-#define ctok_tokenCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
-
-
-/* prototypes */
-PROTOTYPEObj(ctok_token);
-
-#endif /* #ifndef INCLUDED_CTOK_TOKEN_H */
diff --git a/runtime/datetime.c b/runtime/datetime.c
index 89452f1c..753d2068 100644
--- a/runtime/datetime.c
+++ b/runtime/datetime.c
@@ -40,7 +40,6 @@
#include "obj.h"
#include "modules.h"
#include "datetime.h"
-#include "sysvar.h"
#include "srUtils.h"
#include "stringbuf.h"
#include "errmsg.h"
diff --git a/runtime/errmsg.c b/runtime/errmsg.c
index 3c3ee02c..d9062931 100644
--- a/runtime/errmsg.c
+++ b/runtime/errmsg.c
@@ -35,7 +35,6 @@
#include "rsyslog.h"
#include "obj.h"
#include "errmsg.h"
-#include "sysvar.h"
#include "srUtils.h"
#include "stringbuf.h"
diff --git a/runtime/expr.c b/runtime/expr.c
deleted file mode 100644
index 01431474..00000000
--- a/runtime/expr.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/* expr.c - an expression class.
- * This module contains all code needed to represent expressions. Most
- * importantly, that means code to parse and execute them. Expressions
- * heavily depend on (loadable) functions, so it works in conjunction
- * with the function manager.
- *
- * Module begun 2007-11-30 by Rainer Gerhards
- *
- * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH.
- *
- * This file is part of the rsyslog runtime library.
- *
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
- */
-
-#include "config.h"
-#include <stdlib.h>
-#include <assert.h>
-
-#include "rsyslog.h"
-#include "template.h"
-#include "expr.h"
-
-/* static data */
-DEFobjStaticHelpers
-DEFobjCurrIf(vmprg)
-DEFobjCurrIf(var)
-DEFobjCurrIf(ctok_token)
-DEFobjCurrIf(ctok)
-
-
-/* ------------------------------ parser functions ------------------------------ */
-/* the following functions implement the parser. They are all static. For
- * simplicity, the function names match their ABNF definition. The ABNF is defined
- * in the doc set. See file expression.html for details. I do *not* reproduce it
- * here in an effort to keep both files in sync.
- *
- * All functions receive the current expression object as parameter as well as the
- * current tokenizer.
- *
- * rgerhards, 2008-02-19
- */
-
-/* forward definition - thanks to recursive ABNF, we can not avoid at least one ;) */
-static rsRetVal expr(expr_t *pThis, ctok_t *tok);
-
-
-static rsRetVal
-function(expr_t *pThis, ctok_t *tok)
-{
- DEFiRet;
- ctok_token_t *pToken = NULL;
- int iNumArgs = 0;
- var_t *pVar;
-
- ISOBJ_TYPE_assert(pThis, expr);
- ISOBJ_TYPE_assert(tok, ctok);
-
- CHKiRet(ctok.GetToken(tok, &pToken));
- /* note: pToken is destructed in finalize_it */
-
- if(pToken->tok == ctok_LPAREN) {
- CHKiRet(ctok_token.Destruct(&pToken)); /* token processed, "eat" it */
- CHKiRet(ctok.GetToken(tok, &pToken)); /* get next one */
- } else
- ABORT_FINALIZE(RS_RET_FUNC_NO_LPAREN);
-
- /* we first push all the params on the stack. Then we call the function */
- while(pToken->tok != ctok_RPAREN) {
- ++iNumArgs;
- CHKiRet(ctok.UngetToken(tok, pToken)); /* not for us, so let others process it */
- CHKiRet(expr(pThis, tok));
- CHKiRet(ctok.GetToken(tok, &pToken)); /* get next one, needed for while() check */
- if(pToken->tok == ctok_COMMA) {
- CHKiRet(ctok_token.Destruct(&pToken)); /* token processed, "eat" it */
- CHKiRet(ctok.GetToken(tok, &pToken)); /* get next one */
- if(pToken->tok == ctok_RPAREN) {
- ABORT_FINALIZE(RS_RET_FUNC_MISSING_EXPR);
- }
- }
- }
-
-
- /* now push number of arguments - this must be on top of the stack */
- CHKiRet(var.Construct(&pVar));
- CHKiRet(var.ConstructFinalize(pVar));
- CHKiRet(var.SetNumber(pVar, iNumArgs));
- CHKiRet(vmprg.AddVarOperation(pThis->pVmprg, opcode_PUSHCONSTANT, pVar)); /* add to program */
-
-
-finalize_it:
- if(pToken != NULL) {
- ctok_token.Destruct(&pToken); /* "eat" processed token */
- }
-
- RETiRet;
-}
-
-
-static rsRetVal
-terminal(expr_t *pThis, ctok_t *tok)
-{
- DEFiRet;
- ctok_token_t *pToken = NULL;
- var_t *pVar;
-
- ISOBJ_TYPE_assert(pThis, expr);
- ISOBJ_TYPE_assert(tok, ctok);
-
- CHKiRet(ctok.GetToken(tok, &pToken));
- /* note: pToken is destructed in finalize_it */
-
- switch(pToken->tok) {
- case ctok_SIMPSTR:
- dbgoprint((obj_t*) pThis, "simpstr\n");
- CHKiRet(ctok_token.UnlinkVar(pToken, &pVar));
- CHKiRet(vmprg.AddVarOperation(pThis->pVmprg, opcode_PUSHCONSTANT, pVar)); /* add to program */
- break;
- case ctok_NUMBER:
- dbgoprint((obj_t*) pThis, "number\n");
- CHKiRet(ctok_token.UnlinkVar(pToken, &pVar));
- CHKiRet(vmprg.AddVarOperation(pThis->pVmprg, opcode_PUSHCONSTANT, pVar)); /* add to program */
- break;
- case ctok_FUNCTION:
- dbgoprint((obj_t*) pThis, "function\n");
- CHKiRet(function(pThis, tok)); /* this creates the stack call frame */
- /* ... but we place the call instruction onto the stack ourselfs (because
- * we have all relevant information)
- */
- CHKiRet(ctok_token.UnlinkVar(pToken, &pVar));
- CHKiRet(var.ConvToString(pVar)); /* make sure we have a string */
- CHKiRet(vmprg.AddCallOperation(pThis->pVmprg, pVar->val.pStr)); /* add to program */
- CHKiRet(var.Destruct(&pVar));
- break;
- case ctok_MSGVAR:
- dbgoprint((obj_t*) pThis, "MSGVAR\n");
- CHKiRet(ctok_token.UnlinkVar(pToken, &pVar));
- CHKiRet(vmprg.AddVarOperation(pThis->pVmprg, opcode_PUSHMSGVAR, pVar)); /* add to program */
- break;
- case ctok_CEEVAR:
- dbgoprint((obj_t*) pThis, "SYSVAR\n");
- CHKiRet(ctok_token.UnlinkVar(pToken, &pVar));
- CHKiRet(vmprg.AddVarOperation(pThis->pVmprg, opcode_PUSHCEEVAR, pVar)); /* add to program */
- break;
- case ctok_SYSVAR:
- dbgoprint((obj_t*) pThis, "SYSVAR\n");
- CHKiRet(ctok_token.UnlinkVar(pToken, &pVar));
- CHKiRet(vmprg.AddVarOperation(pThis->pVmprg, opcode_PUSHSYSVAR, pVar)); /* add to program */
- break;
- case ctok_LPAREN:
- dbgoprint((obj_t*) pThis, "expr\n");
- CHKiRet(ctok_token.Destruct(&pToken)); /* "eat" processed token */
- CHKiRet(expr(pThis, tok));
- CHKiRet(ctok.GetToken(tok, &pToken)); /* get next one */
- if(pToken->tok != ctok_RPAREN)
- ABORT_FINALIZE(RS_RET_SYNTAX_ERROR);
- break;
- default:
- dbgoprint((obj_t*) pThis, "invalid token %d\n", pToken->tok);
- ABORT_FINALIZE(RS_RET_SYNTAX_ERROR);
- break;
- }
-
-finalize_it:
- if(pToken != NULL) {
- ctok_token.Destruct(&pToken); /* "eat" processed token */
- }
-
- RETiRet;
-}
-
-static rsRetVal
-factor(expr_t *pThis, ctok_t *tok)
-{
- DEFiRet;
- ctok_token_t *pToken;
- int bWasNot;
- int bWasUnaryMinus;
-
- ISOBJ_TYPE_assert(pThis, expr);
- ISOBJ_TYPE_assert(tok, ctok);
-
- CHKiRet(ctok.GetToken(tok, &pToken));
- if(pToken->tok == ctok_NOT) {
- dbgprintf("not\n");
- bWasNot = 1;
- CHKiRet(ctok_token.Destruct(&pToken)); /* no longer needed */
- CHKiRet(ctok.GetToken(tok, &pToken)); /* get new one for next check */
- } else {
- bWasNot = 0;
- }
-
- if(pToken->tok == ctok_MINUS) {
- dbgprintf("unary minus\n");
- bWasUnaryMinus = 1;
- CHKiRet(ctok_token.Destruct(&pToken)); /* no longer needed */
- } else {
- bWasUnaryMinus = 0;
- /* we could not process the token, so push it back */
- CHKiRet(ctok.UngetToken(tok, pToken));
- }
-
- CHKiRet(terminal(pThis, tok));
-
- /* warning: the order if the two following ifs is important. Do not change them, this
- * would change the semantics of the expression!
- */
- if(bWasUnaryMinus) {
- CHKiRet(vmprg.AddVarOperation(pThis->pVmprg, opcode_UNARY_MINUS, NULL)); /* add to program */
- }
-
- if(bWasNot == 1) {
- CHKiRet(vmprg.AddVarOperation(pThis->pVmprg, opcode_NOT, NULL)); /* add to program */
- }
-
-finalize_it:
- RETiRet;
-}
-
-
-static rsRetVal
-term(expr_t *pThis, ctok_t *tok)
-{
- DEFiRet;
- ctok_token_t *pToken;
-
- ISOBJ_TYPE_assert(pThis, expr);
- ISOBJ_TYPE_assert(tok, ctok);
-
- CHKiRet(factor(pThis, tok));
-
- /* *(("*" / "/" / "%") factor) part */
- CHKiRet(ctok.GetToken(tok, &pToken));
- while(pToken->tok == ctok_TIMES || pToken->tok == ctok_DIV || pToken->tok == ctok_MOD) {
- dbgoprint((obj_t*) pThis, "/,*,%%\n");
- CHKiRet(factor(pThis, tok));
- CHKiRet(vmprg.AddVarOperation(pThis->pVmprg, (opcode_t) pToken->tok, NULL)); /* add to program */
- CHKiRet(ctok_token.Destruct(&pToken)); /* no longer needed */
- CHKiRet(ctok.GetToken(tok, &pToken));
- }
-
- /* unget the token that made us exit the loop - it's obviously not one
- * we can process.
- */
- CHKiRet(ctok.UngetToken(tok, pToken));
-
-finalize_it:
- RETiRet;
-}
-
-static rsRetVal
-val(expr_t *pThis, ctok_t *tok)
-{
- DEFiRet;
- ctok_token_t *pToken;
-
- ISOBJ_TYPE_assert(pThis, expr);
- ISOBJ_TYPE_assert(tok, ctok);
-
- CHKiRet(term(pThis, tok));
-
- /* *(("+" / "-") term) part */
- CHKiRet(ctok.GetToken(tok, &pToken));
- while(pToken->tok == ctok_PLUS || pToken->tok == ctok_MINUS || pToken->tok == ctok_STRADD) {
- dbgoprint((obj_t*) pThis, "+/-/&\n");
- CHKiRet(term(pThis, tok));
- CHKiRet(vmprg.AddVarOperation(pThis->pVmprg, (opcode_t) pToken->tok, NULL)); /* add to program */
- CHKiRet(ctok_token.Destruct(&pToken)); /* no longer needed */
- CHKiRet(ctok.GetToken(tok, &pToken));
- }
-
- /* unget the token that made us exit the loop - it's obviously not one
- * we can process.
- */
- CHKiRet(ctok.UngetToken(tok, pToken));
-
-finalize_it:
- RETiRet;
-}
-
-
-static rsRetVal
-e_cmp(expr_t *pThis, ctok_t *tok)
-{
- DEFiRet;
- ctok_token_t *pToken;
-
- ISOBJ_TYPE_assert(pThis, expr);
- ISOBJ_TYPE_assert(tok, ctok);
-
- CHKiRet(val(pThis, tok));
-
- /* 0*1(cmp_op val) part */
- CHKiRet(ctok.GetToken(tok, &pToken));
- if(ctok_token.IsCmpOp(pToken)) {
- dbgoprint((obj_t*) pThis, "cmp\n");
- CHKiRet(val(pThis, tok));
- CHKiRet(vmprg.AddVarOperation(pThis->pVmprg, (opcode_t) pToken->tok, NULL)); /* add to program */
- CHKiRet(ctok_token.Destruct(&pToken)); /* no longer needed */
- } else {
- /* we could not process the token, so push it back */
- CHKiRet(ctok.UngetToken(tok, pToken));
- }
-
-
-finalize_it:
- RETiRet;
-}
-
-
-static rsRetVal
-e_and(expr_t *pThis, ctok_t *tok)
-{
- DEFiRet;
- ctok_token_t *pToken;
-
- ISOBJ_TYPE_assert(pThis, expr);
- ISOBJ_TYPE_assert(tok, ctok);
-
- CHKiRet(e_cmp(pThis, tok));
-
- /* *("and" e_cmp) part */
- CHKiRet(ctok.GetToken(tok, &pToken));
- while(pToken->tok == ctok_AND) {
- dbgoprint((obj_t*) pThis, "and\n");
- CHKiRet(e_cmp(pThis, tok));
- CHKiRet(vmprg.AddVarOperation(pThis->pVmprg, opcode_AND, NULL)); /* add to program */
- CHKiRet(ctok_token.Destruct(&pToken)); /* no longer needed */
- CHKiRet(ctok.GetToken(tok, &pToken));
- }
-
- /* unget the token that made us exit the loop - it's obviously not one
- * we can process.
- */
- CHKiRet(ctok.UngetToken(tok, pToken));
-
-finalize_it:
- RETiRet;
-}
-
-
-static rsRetVal
-expr(expr_t *pThis, ctok_t *tok)
-{
- DEFiRet;
- ctok_token_t *pToken;
-
- ISOBJ_TYPE_assert(pThis, expr);
- ISOBJ_TYPE_assert(tok, ctok);
-
- CHKiRet(e_and(pThis, tok));
-
- /* *("or" e_and) part */
- CHKiRet(ctok.GetToken(tok, &pToken));
- while(pToken->tok == ctok_OR) {
- dbgoprint((obj_t*) pThis, "found OR\n");
- CHKiRet(e_and(pThis, tok));
- CHKiRet(vmprg.AddVarOperation(pThis->pVmprg, opcode_OR, NULL)); /* add to program */
- CHKiRet(ctok_token.Destruct(&pToken)); /* no longer needed */
- CHKiRet(ctok.GetToken(tok, &pToken));
- }
-
- /* unget the token that made us exit the loop - it's obviously not one
- * we can process.
- */
- CHKiRet(ctok.UngetToken(tok, pToken));
-
-finalize_it:
- RETiRet;
-}
-
-
-/* ------------------------------ end parser functions ------------------------------ */
-
-
-/* ------------------------------ actual expr object functions ------------------------------ */
-
-/* Standard-Constructor
- * rgerhards, 2008-02-09 (a rainy Tenerife return flight day ;))
- */
-BEGINobjConstruct(expr) /* be sure to specify the object type also in END macro! */
-ENDobjConstruct(expr)
-
-
-/* ConstructionFinalizer
- * rgerhards, 2008-01-09
- */
-rsRetVal exprConstructFinalize(expr_t __attribute__((unused)) *pThis)
-{
- DEFiRet;
-
- ISOBJ_TYPE_assert(pThis, expr);
-
- RETiRet;
-}
-
-
-/* destructor for the expr object */
-BEGINobjDestruct(expr) /* be sure to specify the object type also in END and CODESTART macros! */
-CODESTARTobjDestruct(expr)
- if(pThis->pVmprg != NULL)
- vmprg.Destruct(&pThis->pVmprg);
-ENDobjDestruct(expr)
-
-
-/* parse an expression object based on a given tokenizer
- * rgerhards, 2008-02-19
- */
-rsRetVal
-exprParse(expr_t *pThis, ctok_t *tok)
-{
- DEFiRet;
-
- ISOBJ_TYPE_assert(pThis, expr);
- ISOBJ_TYPE_assert(tok, ctok);
-
- /* first, we need to make sure we have a program where we can add to what we parse... */
- CHKiRet(vmprg.Construct(&pThis->pVmprg));
- CHKiRet(vmprg.ConstructFinalize(pThis->pVmprg));
-
- /* happy parsing... */
- CHKiRet(expr(pThis, tok));
- dbgoprint((obj_t*) pThis, "successfully parsed/created expression\n");
-
-finalize_it:
- RETiRet;
-}
-
-
-/* queryInterface function
- * rgerhards, 2008-02-21
- */
-BEGINobjQueryInterface(expr)
-CODESTARTobjQueryInterface(expr)
- if(pIf->ifVersion != exprCURR_IF_VERSION) { /* check for current version, increment on each change */
- ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
- }
-
- /* ok, we have the right interface, so let's fill it
- * Please note that we may also do some backwards-compatibility
- * work here (if we can support an older interface version - that,
- * of course, also affects the "if" above).
- */
- pIf->Construct = exprConstruct;
- pIf->ConstructFinalize = exprConstructFinalize;
- pIf->Destruct = exprDestruct;
- pIf->Parse = exprParse;
-finalize_it:
-ENDobjQueryInterface(expr)
-
-
-/* Initialize the expr class. Must be called as the very first method
- * before anything else is called inside this class.
- * rgerhards, 2008-02-19
- */
-BEGINObjClassInit(expr, 1, OBJ_IS_CORE_MODULE) /* class, version */
- /* request objects we use */
- CHKiRet(objUse(var, CORE_COMPONENT));
- CHKiRet(objUse(vmprg, CORE_COMPONENT));
- CHKiRet(objUse(var, CORE_COMPONENT));
- CHKiRet(objUse(ctok_token, CORE_COMPONENT));
- CHKiRet(objUse(ctok, CORE_COMPONENT));
-
- OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, exprConstructFinalize);
-ENDObjClassInit(expr)
-
-/* vi:set ai:
- */
diff --git a/runtime/expr.h b/runtime/expr.h
deleted file mode 100644
index 1afe1a1f..00000000
--- a/runtime/expr.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* The expr object.
- *
- * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
- *
- * This file is part of the rsyslog runtime library.
- *
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
- */
-#ifndef INCLUDED_EXPR_H
-#define INCLUDED_EXPR_H
-
-#include "obj.h"
-#include "ctok.h"
-#include "vmprg.h"
-#include "stringbuf.h"
-
-/* a node inside an expression tree */
-typedef struct exprNode_s {
- char dummy;
-} exprNode_t;
-
-
-/* the expression object */
-typedef struct expr_s {
- BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
- vmprg_t *pVmprg; /* the expression in vmprg format - ready to execute */
-} expr_t;
-
-
-/* interfaces */
-BEGINinterface(expr) /* name must also be changed in ENDinterface macro! */
- INTERFACEObjDebugPrint(expr);
- rsRetVal (*Construct)(expr_t **ppThis);
- rsRetVal (*ConstructFinalize)(expr_t __attribute__((unused)) *pThis);
- rsRetVal (*Destruct)(expr_t **ppThis);
- rsRetVal (*Parse)(expr_t *pThis, ctok_t *ctok);
-ENDinterface(expr)
-#define exprCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
-
-/* prototypes */
-PROTOTYPEObj(expr);
-
-#endif /* #ifndef INCLUDED_EXPR_H */
diff --git a/runtime/msg.c b/runtime/msg.c
index c5cbb5c8..b440d6ca 100644
--- a/runtime/msg.c
+++ b/runtime/msg.c
@@ -37,6 +37,7 @@
#include <ctype.h>
#include <sys/socket.h>
#include <netdb.h>
+#include <libestr.h>
#include <libee/libee.h>
#if HAVE_MALLOC_H
# include <malloc.h>
@@ -46,7 +47,6 @@
#include "stringbuf.h"
#include "template.h"
#include "msg.h"
-#include "var.h"
#include "datetime.h"
#include "glbl.h"
#include "regexp.h"
@@ -480,16 +480,13 @@ getRcvFromIP(msg_t *pM)
}
-
-/* map a property name (string) to a property ID */
-rsRetVal propNameToID(cstr_t *pCSPropName, propid_t *pPropID)
+/* map a property name (C string) to a property ID */
+rsRetVal
+propNameStrToID(uchar *pName, propid_t *pPropID)
{
- uchar *pName;
DEFiRet;
- assert(pCSPropName != NULL);
- assert(pPropID != NULL);
- pName = rsCStrGetSzStrNoNULL(pCSPropName);
+ assert(pName != NULL);
/* sometimes there are aliases to the original MonitoWare
* property names. These come after || in the ifs below. */
@@ -577,6 +574,21 @@ rsRetVal propNameToID(cstr_t *pCSPropName, propid_t *pPropID)
}
+/* map a property name (string) to a property ID */
+rsRetVal
+propNameToID(cstr_t *pCSPropName, propid_t *pPropID)
+{
+ uchar *pName;
+ DEFiRet;
+
+ assert(pCSPropName != NULL);
+ assert(pPropID != NULL);
+ pName = rsCStrGetSzStrNoNULL(pCSPropName);
+ iRet = propNameStrToID(pName, pPropID);
+ RETiRet;
+}
+
+
/* map a property ID to a name string (useful for displaying) */
uchar *propIDToName(propid_t propID)
{
@@ -3095,98 +3107,68 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
}
-/* The function returns a cee variable suitable for use with RainerScript. Most importantly, this means
- * that the value is returned in a var_t object. The var_t is constructed inside this function and
- * MUST be freed by the caller.
+/* The function returns a cee variable suitable for use with RainerScript.
+ * Note: caller must free the returned string.
* Note that we need to do a lot of conversions between es_str_t and cstr -- this will go away once
* we have moved larger parts of rsyslog to es_str_t. Acceptable for the moment, especially as we intend
* to rewrite the script engine as well!
* rgerhards, 2010-12-03
*/
-rsRetVal
-msgGetCEEVar(msg_t *pMsg, cstr_t *propName, var_t **ppVar)
+es_str_t*
+msgGetCEEVarNew(msg_t *pMsg, char *name)
{
- DEFiRet;
- var_t *pVar;
- cstr_t *pstrProp;
- es_str_t *str = NULL;
+ es_str_t *estr = NULL;
es_str_t *epropName = NULL;
- int r;
+ struct ee_field *field;
ISOBJ_TYPE_assert(pMsg, msg);
- ASSERT(propName != NULL);
- ASSERT(ppVar != NULL);
- /* make sure we have a var_t instance */
- CHKiRet(var.Construct(&pVar));
- CHKiRet(var.ConstructFinalize(pVar));
-
- epropName = es_newStrFromBuf((char*)propName->pBuf, propName->iStrLen);
- r = ee_getEventFieldAsString(pMsg->event, epropName, &str);
-
- if(r != EE_OK) {
- DBGPRINTF("msgGtCEEVar: libee error %d during ee_getEventFieldAsString\n", r);
- CHKiRet(cstrConstruct(&pstrProp));
- CHKiRet(cstrFinalize(pstrProp));
- } else {
- CHKiRet(cstrConstructFromESStr(&pstrProp, str));
+ if(pMsg->event == NULL) {
+ estr = es_newStr(1);
+ goto done;
}
- /* now create a string object out of it and hand that over to the var */
- CHKiRet(var.SetString(pVar, pstrProp));
- es_deleteStr(str);
-
- /* finally store var */
- *ppVar = pVar;
+ epropName = es_newStrFromCStr(name, strlen(name)); // TODO: optimize (in grammar!)
+ field = ee_getEventField(pMsg->event, epropName);
+ if(field != NULL) {
+ estr = ee_getFieldValueAsStr(field, 0);
+ }
+ if(estr == NULL) {
+ DBGPRINTF("msgGetCEEVar: error obtaining var (field=%p, var='%s')\n",
+ field, name);
+ estr = es_newStrFromCStr("*ERROR*", sizeof("*ERROR*") - 1);
+ }
+ es_deleteStr(epropName);
-finalize_it:
- if(epropName != NULL)
- es_deleteStr(epropName);
- RETiRet;
+done:
+ return estr;
}
-/* The returns a message variable suitable for use with RainerScript. Most importantly, this means
- * that the value is returned in a var_t object. The var_t is constructed inside this function and
- * MUST be freed by the caller.
- * rgerhards, 2008-02-25
+/* Return an es_str_t for given message property.
*/
-rsRetVal
-msgGetMsgVar(msg_t *pThis, cstr_t *pstrPropName, var_t **ppVar)
+es_str_t*
+msgGetMsgVarNew(msg_t *pThis, uchar *name)
{
- DEFiRet;
- var_t *pVar;
size_t propLen;
uchar *pszProp = NULL;
- cstr_t *pstrProp;
propid_t propid;
unsigned short bMustBeFreed = 0;
+ es_str_t *estr;
ISOBJ_TYPE_assert(pThis, msg);
- ASSERT(pstrPropName != NULL);
- ASSERT(ppVar != NULL);
-
- /* make sure we have a var_t instance */
- CHKiRet(var.Construct(&pVar));
- CHKiRet(var.ConstructFinalize(pVar));
/* always call MsgGetProp() without a template specifier */
/* TODO: optimize propNameToID() call -- rgerhards, 2009-06-26 */
- propNameToID(pstrPropName, &propid);
+ propNameStrToID(name, &propid);
pszProp = (uchar*) MsgGetProp(pThis, NULL, propid, NULL, &propLen, &bMustBeFreed);
- /* now create a string object out of it and hand that over to the var */
- CHKiRet(rsCStrConstructFromszStr(&pstrProp, pszProp));
- CHKiRet(var.SetString(pVar, pstrProp));
-
- /* finally store var */
- *ppVar = pVar;
-
-finalize_it:
+dbgprintf("ZZZZ: var %s returns '%s'\n", name, pszProp);
+ estr = es_newStrFromCStr((char*)pszProp, propLen);
if(bMustBeFreed)
free(pszProp);
- RETiRet;
+ return estr;
}
diff --git a/runtime/msg.h b/runtime/msg.h
index 01a1e059..55d2dfc0 100644
--- a/runtime/msg.h
+++ b/runtime/msg.h
@@ -170,6 +170,7 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
size_t *pPropLen, unsigned short *pbMustBeFreed);
char *textpri(char *pRes, size_t pResLen, int pri);
rsRetVal msgGetMsgVar(msg_t *pThis, cstr_t *pstrPropName, var_t **ppVar);
+es_str_t* msgGetMsgVarNew(msg_t *pThis, uchar *name);
rsRetVal MsgEnableThreadSafety(void);
uchar *getRcvFrom(msg_t *pM);
void getTAG(msg_t *pM, uchar **ppBuf, int *piLen);
@@ -177,6 +178,7 @@ char *getTimeReported(msg_t *pM, enum tplFormatTypes eFmt);
char *getPRI(msg_t *pMsg);
void getRawMsg(msg_t *pM, uchar **pBuf, int *piLen);
rsRetVal msgGetCEEVar(msg_t *pThis, cstr_t *propName, var_t **ppVar);
+es_str_t* msgGetCEEVarNew(msg_t *pMsg, char *name);
/* TODO: remove these five (so far used in action.c) */
diff --git a/runtime/rsconf.c b/runtime/rsconf.c
index cb76e6da..5df4c2c8 100644
--- a/runtime/rsconf.c
+++ b/runtime/rsconf.c
@@ -31,6 +31,7 @@
#include <errno.h>
#include <unistd.h>
#include <grp.h>
+#include <stdarg.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -38,6 +39,7 @@
#include "rsyslog.h"
#include "obj.h"
#include "srUtils.h"
+#include "rule.h"
#include "ruleset.h"
#include "modules.h"
#include "conf.h"
@@ -63,16 +65,20 @@
#include "parser.h"
#include "outchannel.h"
#include "threads.h"
+#include "datetime.h"
+#include "parserif.h"
#include "dirty.h"
/* static data */
DEFobjStaticHelpers
+DEFobjCurrIf(rule)
DEFobjCurrIf(ruleset)
DEFobjCurrIf(module)
DEFobjCurrIf(conf)
DEFobjCurrIf(errmsg)
DEFobjCurrIf(glbl)
DEFobjCurrIf(parser)
+DEFobjCurrIf(datetime)
/* exported static data */
rsconf_t *runConf = NULL;/* the currently running config */
@@ -92,6 +98,7 @@ static uchar template_StdPgSQLFmt[] = "\"insert into SystemEvents (Message, Faci
static uchar template_spoofadr[] = "\"%fromhost-ip%\"";
/* end templates */
+void cnfDoCfsysline(char *ln);
/* Standard-Constructor
*/
@@ -212,6 +219,241 @@ CODESTARTobjDebugPrint(rsconf)
ENDobjDebugPrint(rsconf)
+rsRetVal
+cnfDoActlst(struct cnfactlst *actlst, rule_t *pRule)
+{
+ struct cnfcfsyslinelst *cflst;
+ action_t *pAction;
+ uchar *str;
+ DEFiRet;
+
+ while(actlst != NULL) {
+ dbgprintf("aclst %p: ", actlst);
+ if(actlst->actType == CNFACT_V2) {
+ dbgprintf("V2 action type not yet handled\n");
+ } else {
+ dbgprintf("legacy action line:%s\n", actlst->data.legActLine);
+ str = (uchar*) actlst->data.legActLine;
+ iRet = cflineDoAction(loadConf, &str, &pAction);
+ iRet = llAppend(&(pRule)->llActList, NULL, (void*) pAction);
+ }
+ for( cflst = actlst->syslines
+ ; cflst != NULL ; cflst = cflst->next) {
+ cnfDoCfsysline(cflst->line);
+ }
+ actlst = actlst->next;
+ }
+ RETiRet;
+}
+
+/* This function returns the current date in different
+ * variants. It is used to construct the $NOW series of
+ * system properties. The returned buffer must be freed
+ * by the caller when no longer needed. If the function
+ * can not allocate memory, it returns a NULL pointer.
+ * TODO: this was taken from msg.c and we should consolidate it with the code
+ * there. This is especially important when we increase the number of system
+ * variables (what we definitely want to do).
+ */
+typedef enum ENOWType { NOW_NOW, NOW_YEAR, NOW_MONTH, NOW_DAY, NOW_HOUR, NOW_MINUTE } eNOWType;
+static rsRetVal
+getNOW(eNOWType eNow, es_str_t **estr)
+{
+ DEFiRet;
+ uchar szBuf[16];
+ struct syslogTime t;
+ es_size_t len;
+
+ datetime.getCurrTime(&t, NULL);
+ switch(eNow) {
+ case NOW_NOW:
+ len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar),
+ "%4.4d-%2.2d-%2.2d", t.year, t.month, t.day);
+ break;
+ case NOW_YEAR:
+ len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%4.4d", t.year);
+ break;
+ case NOW_MONTH:
+ len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%2.2d", t.month);
+ break;
+ case NOW_DAY:
+ len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%2.2d", t.day);
+ break;
+ case NOW_HOUR:
+ len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%2.2d", t.hour);
+ break;
+ case NOW_MINUTE:
+ len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%2.2d", t.minute);
+ break;
+ }
+
+ /* now create a string object out of it and hand that over to the var */
+ *estr = es_newStrFromCStr((char*)szBuf, len);
+
+ RETiRet;
+}
+
+
+
+static inline es_str_t *
+getSysVar(char *name)
+{
+ es_str_t *estr = NULL;
+ rsRetVal iRet = RS_RET_OK;
+
+ if(!strcmp(name, "now")) {
+ CHKiRet(getNOW(NOW_NOW, &estr));
+ } else if(!strcmp(name, "year")) {
+ CHKiRet(getNOW(NOW_YEAR, &estr));
+ } else if(!strcmp(name, "month")) {
+ CHKiRet(getNOW(NOW_MONTH, &estr));
+ } else if(!strcmp(name, "day")) {
+ CHKiRet(getNOW(NOW_DAY, &estr));
+ } else if(!strcmp(name, "hour")) {
+ CHKiRet(getNOW(NOW_HOUR, &estr));
+ } else if(!strcmp(name, "minute")) {
+ CHKiRet(getNOW(NOW_MINUTE, &estr));
+ } else if(!strcmp(name, "myhostname")) {
+ char *hn = (char*)glbl.GetLocalHostName();
+ estr = es_newStrFromCStr(hn, strlen(hn));
+ } else {
+ ABORT_FINALIZE(RS_RET_SYSVAR_NOT_FOUND);
+ }
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ dbgprintf("getSysVar error iRet %d\n", iRet);
+ if(estr == NULL)
+ estr = es_newStrFromCStr("*ERROR*", sizeof("*ERROR*") - 1);
+ }
+ return estr;
+}
+
+/*------------------------------ interface to flex/bison parser ------------------------------*/
+extern int yylineno;
+
+void
+parser_errmsg(char *fmt, ...)
+{
+ va_list ap;
+ char errBuf[1024];
+
+ va_start(ap, fmt);
+ if(vsnprintf(errBuf, sizeof(errBuf), fmt, ap) == sizeof(errBuf))
+ errBuf[1024] = '\0';
+ errmsg.LogError(0, RS_RET_CONF_PARSE_ERROR,
+ "error during parsing file %s, on or before line %d: %s",
+ cnfcurrfn, yylineno, errBuf);
+ va_end(ap);
+}
+
+int
+yyerror(char *s)
+{
+ parser_errmsg("%s", s);
+ return 0;
+}
+void cnfDoObj(struct cnfobj *o)
+{
+ dbgprintf("cnf:global:obj: ");
+ cnfobjPrint(o);
+ cnfobjDestruct(o);
+}
+
+void cnfDoRule(struct cnfrule *cnfrule)
+{
+ rule_t *pRule;
+ uchar *str;
+ rsRetVal iRet = RS_RET_OK; //DEFiRet;
+
+ dbgprintf("cnf:global:rule\n");
+ cnfrulePrint(cnfrule);
+
+ CHKiRet(rule.Construct(&pRule)); /* create "fresh" selector */
+ CHKiRet(rule.SetAssRuleset(pRule, ruleset.GetCurrent(loadConf)));
+ CHKiRet(rule.ConstructFinalize(pRule));
+
+ switch(cnfrule->filttype) {
+ case CNFFILT_NONE:
+ break;
+ case CNFFILT_PRI:
+ str = (uchar*) cnfrule->filt.s;
+ iRet = cflineProcessTradPRIFilter(&str, pRule);
+ break;
+ case CNFFILT_PROP:
+ dbgprintf("%s\n", cnfrule->filt.s);
+ str = (uchar*) cnfrule->filt.s;
+ iRet = cflineProcessPropFilter(&str, pRule);
+ break;
+ case CNFFILT_SCRIPT:
+ pRule->f_filter_type = FILTER_EXPR;
+ pRule->f_filterData.expr = cnfrule->filt.expr;
+ break;
+ }
+ /* we now check if there are some global (BSD-style) filter conditions
+ * and, if so, we copy them over. rgerhards, 2005-10-18
+ */
+ if(pDfltProgNameCmp != NULL) {
+ CHKiRet(rsCStrConstructFromCStr(&(pRule->pCSProgNameComp), pDfltProgNameCmp));
+ }
+
+ if(eDfltHostnameCmpMode != HN_NO_COMP) {
+ pRule->eHostnameCmpMode = eDfltHostnameCmpMode;
+ CHKiRet(rsCStrConstructFromCStr(&(pRule->pCSHostnameComp), pDfltHostnameCmp));
+ }
+
+ cnfDoActlst(cnfrule->actlst, pRule);
+
+ CHKiRet(ruleset.AddRule(loadConf, rule.GetAssRuleset(pRule), &pRule));
+
+finalize_it:
+ //TODO: do something with error states
+ ;
+}
+
+void cnfDoCfsysline(char *ln)
+{
+ dbgprintf("cnf:global:cfsysline: %s\n", ln);
+ /* the legacy system needs the "$" stripped */
+ conf.cfsysline((uchar*) ln+1);
+ dbgprintf("cnf:cfsysline call done\n");
+}
+
+void cnfDoBSDTag(char *ln)
+{
+ dbgprintf("cnf:global:BSD tag: %s\n", ln);
+ cflineProcessTagSelector((uchar**)&ln);
+}
+
+void cnfDoBSDHost(char *ln)
+{
+ dbgprintf("cnf:global:BSD host: %s\n", ln);
+ cflineProcessHostSelector((uchar**)&ln);
+}
+
+es_str_t*
+cnfGetVar(char *name, void *usrptr)
+{
+ es_str_t *estr;
+ if(name[0] == '$') {
+ if(name[1] == '$')
+ estr = getSysVar(name+2);
+ else if(name[1] == '!')
+ estr = msgGetCEEVarNew((msg_t*) usrptr, name+2);
+ else
+ estr = msgGetMsgVarNew((msg_t*) usrptr, (uchar*)name+1);
+ }
+ if(Debug) {
+ char *s;
+ s = es_str2cstr(estr, NULL);
+ dbgprintf("rainerscript: var '%s': '%s'\n", name, s);
+ free(s);
+ }
+ return estr;
+}
+/*------------------------------ end interface to flex/bison parser ------------------------------*/
+
+
+
/* drop to specified group
* if something goes wrong, the function never returns
* Note that such an abort can cause damage to on-disk structures, so we should
@@ -549,19 +791,6 @@ static rsRetVal setActionResumeInterval(void __attribute__((unused)) *pVal, int
}
-/* this method is needed to shuffle the current conf object down to the
- * IncludeConfig handler.
- */
-static rsRetVal
-doIncludeLine(void *pVal, uchar *pNewVal)
-{
- DEFiRet;
- iRet = conf.doIncludeLine(ourConf, pVal, pNewVal);
- free(pNewVal);
- RETiRet;
-}
-
-
/* set the maximum message size */
static rsRetVal setMaxMsgSize(void __attribute__((unused)) *pVal, long iNewVal)
{
@@ -840,8 +1069,6 @@ initLegacyConf(void)
setActionResumeInterval, NULL, NULL, eConfObjGlobal));
CHKiRet(regCfSysLineHdlr((uchar *)"modload", 0, eCmdHdlrCustomHandler,
conf.doModLoad, NULL, NULL, eConfObjGlobal));
- CHKiRet(regCfSysLineHdlr((uchar *)"includeconfig", 0, eCmdHdlrCustomHandler,
- doIncludeLine, NULL, NULL, eConfObjGlobal));
CHKiRet(regCfSysLineHdlr((uchar *)"maxmessagesize", 0, eCmdHdlrSize,
setMaxMsgSize, NULL, NULL, eConfObjGlobal));
CHKiRet(regCfSysLineHdlr((uchar *)"defaultruleset", 0, eCmdHdlrGetWord,
@@ -990,10 +1217,8 @@ validateConf(void)
rsRetVal
load(rsconf_t **cnf, uchar *confFile)
{
- rsRetVal localRet;
int iNbrActions;
- int bHadConfigErr = 0;
- char cbuf[BUFSIZ];
+ int r;
DEFiRet;
CHKiRet(rsconfConstruct(&loadConf));
@@ -1003,54 +1228,26 @@ ourConf = loadConf; // TODO: remove, once ourConf is gone!
CHKiRet(initLegacyConf());
/* open the configuration file */
- localRet = conf.processConfFile(loadConf, confFile);
- CHKiRet(conf.GetNbrActActions(loadConf, &iNbrActions));
-
- if(localRet != RS_RET_OK && localRet != RS_RET_NONFATAL_CONFIG_ERR) {
- errmsg.LogError(0, localRet, "CONFIG ERROR: could not interpret master config file '%s'.", confFile);
- bHadConfigErr = 1;
- } else if(iNbrActions == 0) {
- errmsg.LogError(0, RS_RET_NO_ACTIONS, "CONFIG ERROR: there are no active actions configured. Inputs will "
- "run, but no output whatsoever is created.");
- bHadConfigErr = 1;
+ r = cnfSetLexFile((char*)confFile);
+ if(r == 0) {
+ r = yyparse();
+ conf.GetNbrActActions(loadConf, &iNbrActions);
}
- if((localRet != RS_RET_OK && localRet != RS_RET_NONFATAL_CONFIG_ERR) || iNbrActions == 0) {
-
- /* rgerhards: this code is executed to set defaults when the
- * config file could not be opened. We might think about
- * abandoning the run in this case - but this, too, is not
- * very clever... So we stick with what we have.
- * We ignore any errors while doing this - we would be lost anyhow...
- */
- errmsg.LogError(0, NO_ERRCODE, "EMERGENCY CONFIGURATION ACTIVATED - fix rsyslog config file!");
-
- /* note: we previously used _POSIY_TTY_NAME_MAX+1, but this turned out to be
- * too low on linux... :-S -- rgerhards, 2008-07-28
- */
- char szTTYNameBuf[128];
- rule_t *pRule = NULL; /* initialization to NULL is *vitally* important! */
- conf.cfline(loadConf, UCHAR_CONSTANT("*.ERR\t" _PATH_CONSOLE), &pRule);
- conf.cfline(loadConf, UCHAR_CONSTANT("syslog.*\t" _PATH_CONSOLE), &pRule);
- conf.cfline(loadConf, UCHAR_CONSTANT("*.PANIC\t*"), &pRule);
- conf.cfline(loadConf, UCHAR_CONSTANT("syslog.*\troot"), &pRule);
- if(ttyname_r(0, szTTYNameBuf, sizeof(szTTYNameBuf)) == 0) {
- snprintf(cbuf,sizeof(cbuf), "*.*\t%s", szTTYNameBuf);
- conf.cfline(loadConf, (uchar*)cbuf, &pRule);
- } else {
- DBGPRINTF("error %d obtaining controlling terminal, not using that emergency rule\n", errno);
- }
- ruleset.AddRule(loadConf, ruleset.GetCurrent(loadConf), &pRule);
+ if(r == 1) {
+ errmsg.LogError(0, RS_RET_CONF_PARSE_ERROR,
+ "CONFIG ERROR: could not interpret master "
+ "config file '%s'.", confFile);
+ ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR);
+ } else if(iNbrActions == 0) {
+ errmsg.LogError(0, RS_RET_NO_ACTIONS, "CONFIG ERROR: there are no "
+ "active actions configured. Inputs will "
+ "run, but no output whatsoever is created.");
+ ABORT_FINALIZE(RS_RET_NO_ACTIONS);
}
CHKiRet(validateConf());
-
- /* return warning state if we had some acceptable problems */
- if(bHadConfigErr) {
- iRet = RS_RET_NONFATAL_CONFIG_ERR;
- }
-
/* we are done checking the config - now validate if we should actually run or not.
* If not, terminate. -- rgerhards, 2008-07-25
* TODO: iConfigVerify -- should it be pulled from the config, or leave as is (option)?
@@ -1065,7 +1262,7 @@ ourConf = loadConf; // TODO: remove, once ourConf is gone!
*cnf = loadConf;
// TODO: enable this once all config code is moved to here! loadConf = NULL;
- dbgprintf("rsyslog finished loading initial config %p\n", loadConf);
+ dbgprintf("rsyslog finished loading master config %p\n", loadConf);
rsconfDebugPrint(loadConf);
finalize_it:
@@ -1102,10 +1299,12 @@ ENDobjQueryInterface(rsconf)
BEGINObjClassInit(rsconf, 1, OBJ_IS_CORE_MODULE) /* class, version */
/* request objects we use */
CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ CHKiRet(objUse(rule, CORE_COMPONENT));
CHKiRet(objUse(module, CORE_COMPONENT));
CHKiRet(objUse(conf, CORE_COMPONENT));
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
CHKiRet(objUse(parser, CORE_COMPONENT));
/* now set our own handlers */
@@ -1117,11 +1316,13 @@ ENDObjClassInit(rsconf)
/* De-initialize the rsconf class.
*/
BEGINObjClassExit(rsconf, OBJ_IS_CORE_MODULE) /* class, version */
+ objRelease(rule, CORE_COMPONENT);
objRelease(ruleset, CORE_COMPONENT);
objRelease(module, CORE_COMPONENT);
objRelease(conf, CORE_COMPONENT);
objRelease(errmsg, CORE_COMPONENT);
objRelease(glbl, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
objRelease(parser, CORE_COMPONENT);
ENDObjClassExit(rsconf)
diff --git a/runtime/rsyslog.c b/runtime/rsyslog.c
index 2b8f2b64..cbab06b7 100644
--- a/runtime/rsyslog.c
+++ b/runtime/rsyslog.c
@@ -62,16 +62,9 @@
#include "rsyslog.h"
#include "obj.h"
-#include "vm.h"
-#include "sysvar.h"
#include "stringbuf.h"
#include "wti.h"
#include "wtp.h"
-#include "expr.h"
-#include "ctok.h"
-#include "vmop.h"
-#include "vmstk.h"
-#include "vmprg.h"
#include "datetime.h"
#include "queue.h"
#include "conf.h"
@@ -178,22 +171,6 @@ rsrtInit(char **ppErrObj, obj_if_t *pObjIF)
CHKiRet(glblClassInit(NULL));
if(ppErrObj != NULL) *ppErrObj = "msg";
CHKiRet(msgClassInit(NULL));
- if(ppErrObj != NULL) *ppErrObj = "ctok_token";
- CHKiRet(ctok_tokenClassInit(NULL));
- if(ppErrObj != NULL) *ppErrObj = "ctok";
- CHKiRet(ctokClassInit(NULL));
- if(ppErrObj != NULL) *ppErrObj = "vmstk";
- CHKiRet(vmstkClassInit(NULL));
- if(ppErrObj != NULL) *ppErrObj = "sysvar";
- CHKiRet(sysvarClassInit(NULL));
- if(ppErrObj != NULL) *ppErrObj = "vm";
- CHKiRet(vmClassInit(NULL));
- if(ppErrObj != NULL) *ppErrObj = "vmop";
- CHKiRet(vmopClassInit(NULL));
- if(ppErrObj != NULL) *ppErrObj = "vmprg";
- CHKiRet(vmprgClassInit(NULL));
- if(ppErrObj != NULL) *ppErrObj = "expr";
- CHKiRet(exprClassInit(NULL));
if(ppErrObj != NULL) *ppErrObj = "rule";
CHKiRet(ruleClassInit(NULL));
if(ppErrObj != NULL) *ppErrObj = "ruleset";
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index 0b0dc921..39f00ebc 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -360,6 +360,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_CMD_GONE_AWAY = -2204,/**< config directive existed, but no longer supported */
RS_RET_ERR_SCHED_PARAMS = -2205,/**< there is a problem with configured thread scheduling params */
RS_RET_SOCKNAME_MISSING = -2206,/**< no socket name configured where one is required */
+ RS_RET_CONF_PARSE_ERROR = -2207,/**< (fatal) error parsing config file */
/* RainerScript error messages (range 1000.. 1999) */
RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */
diff --git a/runtime/rule.c b/runtime/rule.c
index 3dcee877..cbd2660d 100644
--- a/runtime/rule.c
+++ b/runtime/rule.c
@@ -36,18 +36,15 @@
#include "action.h"
#include "rule.h"
#include "errmsg.h"
-#include "vm.h"
-#include "var.h"
#include "srUtils.h"
#include "batch.h"
+#include "parserif.h"
#include "unicode-helper.h"
/* static data */
DEFobjStaticHelpers
DEFobjCurrIf(errmsg)
-DEFobjCurrIf(expr)
DEFobjCurrIf(var)
-DEFobjCurrIf(vm)
/* support for simple textual representation of FIOP names
@@ -123,8 +120,6 @@ shouldProcessThisMessage(rule_t *pRule, msg_t *pMsg, sbool *bProcessMsg)
uchar *pszPropVal;
int bRet = 0;
size_t propLen;
- vm_t *pVM = NULL;
- var_t *pResult = NULL;
ISOBJ_TYPE_assert(pRule, rule);
assert(pMsg != NULL);
@@ -186,14 +181,8 @@ shouldProcessThisMessage(rule_t *pRule, msg_t *pMsg, sbool *bProcessMsg)
else
bRet = 1;
} else if(pRule->f_filter_type == FILTER_EXPR) {
- CHKiRet(vm.Construct(&pVM));
- CHKiRet(vm.ConstructFinalize(pVM));
- CHKiRet(vm.SetMsg(pVM, pMsg));
- CHKiRet(vm.ExecProg(pVM, pRule->f_filterData.f_expr->pVmprg));
- CHKiRet(vm.PopBoolFromStack(pVM, &pResult));
- dbgprintf("result of rainerscript filter evaluation: %lld\n", pResult->val.num);
- /* VM is destructed on function exit */
- bRet = (pResult->val.num) ? 1 : 0;
+ bRet = cnfexprEvalBool(pRule->f_filterData.expr, pMsg);
+ dbgprintf("result of rainerscript filter evaluation: %d\n", bRet);
} else {
assert(pRule->f_filter_type == FILTER_PROP); /* assert() just in case... */
pszPropVal = MsgGetProp(pMsg, NULL, pRule->f_filterData.prop.propID,
@@ -271,13 +260,6 @@ shouldProcessThisMessage(rule_t *pRule, msg_t *pMsg, sbool *bProcessMsg)
}
finalize_it:
- /* destruct in any case, not just on error, but it makes error handling much easier */
- if(pVM != NULL)
- vm.Destruct(&pVM);
-
- if(pResult != NULL)
- var.Destruct(&pResult);
-
*bProcessMsg = bRet;
RETiRet;
}
@@ -356,9 +338,6 @@ CODESTARTobjDestruct(rule)
rsCStrRegexDestruct(&pThis->f_filterData.prop.regex_cache);
if(pThis->f_filterData.prop.propName != NULL)
es_deleteStr(pThis->f_filterData.prop.propName);
- } else if(pThis->f_filter_type == FILTER_EXPR) {
- if(pThis->f_filterData.f_expr != NULL)
- expr.Destruct(&pThis->f_filterData.f_expr);
}
llDestroy(&pThis->llActList);
@@ -476,9 +455,7 @@ ENDobjQueryInterface(rule)
*/
BEGINObjClassExit(rule, OBJ_IS_CORE_MODULE) /* class, version */
objRelease(errmsg, CORE_COMPONENT);
- objRelease(expr, CORE_COMPONENT);
objRelease(var, CORE_COMPONENT);
- objRelease(vm, CORE_COMPONENT);
ENDObjClassExit(rule)
@@ -489,9 +466,7 @@ ENDObjClassExit(rule)
BEGINObjClassInit(rule, 1, OBJ_IS_CORE_MODULE) /* class, version */
/* request objects we use */
CHKiRet(objUse(errmsg, CORE_COMPONENT));
- CHKiRet(objUse(expr, CORE_COMPONENT));
CHKiRet(objUse(var, CORE_COMPONENT));
- CHKiRet(objUse(vm, CORE_COMPONENT));
/* set our own handlers */
OBJSetMethodHandler(objMethod_DEBUGPRINT, ruleDebugPrint);
diff --git a/runtime/rule.h b/runtime/rule.h
index 3b34e11a..76ed5f0b 100644
--- a/runtime/rule.h
+++ b/runtime/rule.h
@@ -2,7 +2,7 @@
*
* This implements rules within rsyslog.
*
- * Copyright 2009 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2009-2011 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@@ -28,7 +28,7 @@
#include "libestr.h"
#include "linkedlist.h"
#include "regexp.h"
-#include "expr.h"
+#include "rainerscript.h"
/* the rule object */
struct rule_s {
@@ -52,7 +52,7 @@ struct rule_s {
propid_t propID; /* ID of the requested property */
es_str_t *propName; /* name of property for CEE-based filters */
} prop;
- expr_t *f_expr; /* expression object */
+ struct cnfexpr *expr; /* expression object */
} f_filterData;
ruleset_t *pRuleset; /* associated ruleset */
diff --git a/runtime/statsobj.c b/runtime/statsobj.c
index e1a89cf4..d1213a34 100644
--- a/runtime/statsobj.c
+++ b/runtime/statsobj.c
@@ -36,7 +36,6 @@
#include "unicode-helper.h"
#include "obj.h"
#include "statsobj.h"
-#include "sysvar.h"
#include "srUtils.h"
#include "stringbuf.h"
diff --git a/runtime/sysvar.c b/runtime/sysvar.c
deleted file mode 100644
index ecc31e2d..00000000
--- a/runtime/sysvar.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/* sysvar.c - imlements rsyslog system variables
- *
- * At least for now, this class only has static functions and no
- * instances.
- *
- * Module begun 2008-02-25 by Rainer Gerhards
- *
- * Copyright (C) 2008 by Rainer Gerhards and Adiscon GmbH.
- *
- * This file is part of the rsyslog runtime library.
- *
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
- */
-
-#include "config.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include "rsyslog.h"
-#include "obj.h"
-#include "stringbuf.h"
-#include "sysvar.h"
-#include "datetime.h"
-
-/* static data */
-DEFobjStaticHelpers
-DEFobjCurrIf(var)
-DEFobjCurrIf(datetime)
-DEFobjCurrIf(glbl)
-
-
-/* Standard-Constructor
- */
-BEGINobjConstruct(sysvar) /* be sure to specify the object type also in END macro! */
-ENDobjConstruct(sysvar)
-
-
-/* ConstructionFinalizer
- * rgerhards, 2008-01-09
- */
-static rsRetVal
-sysvarConstructFinalize(sysvar_t __attribute__((unused)) *pThis)
-{
- DEFiRet;
- RETiRet;
-}
-
-
-/* destructor for the sysvar object */
-BEGINobjDestruct(sysvar) /* be sure to specify the object type also in END and CODESTART macros! */
-CODESTARTobjDestruct(sysvar)
-ENDobjDestruct(sysvar)
-
-
-/* This function returns the current date in different
- * variants. It is used to construct the $NOW series of
- * system properties. The returned buffer must be freed
- * by the caller when no longer needed. If the function
- * can not allocate memory, it returns a NULL pointer.
- * Added 2007-07-10 rgerhards
- * TODO: this was taken from msg.c and we should consolidate it with the code
- * there. This is especially important when we increase the number of system
- * variables (what we definitely want to do).
- */
-typedef enum ENOWType { NOW_NOW, NOW_YEAR, NOW_MONTH, NOW_DAY, NOW_HOUR, NOW_MINUTE } eNOWType;
-static rsRetVal
-getNOW(eNOWType eNow, cstr_t **ppStr)
-{
- DEFiRet;
- uchar szBuf[16];
- struct syslogTime t;
-
- datetime.getCurrTime(&t, NULL);
- switch(eNow) {
- case NOW_NOW:
- snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%4.4d-%2.2d-%2.2d", t.year, t.month, t.day);
- break;
- case NOW_YEAR:
- snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%4.4d", t.year);
- break;
- case NOW_MONTH:
- snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%2.2d", t.month);
- break;
- case NOW_DAY:
- snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%2.2d", t.day);
- break;
- case NOW_HOUR:
- snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%2.2d", t.hour);
- break;
- case NOW_MINUTE:
- snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%2.2d", t.minute);
- break;
- }
-
- /* now create a string object out of it and hand that over to the var */
- CHKiRet(rsCStrConstructFromszStr(ppStr, szBuf));
-
-finalize_it:
- RETiRet;
-}
-
-
-/* The function returns a system variable suitable for use with RainerScript. Most importantly, this means
- * that the value is returned in a var_t object. The var_t is constructed inside this function and
- * MUST be freed by the caller.
- * rgerhards, 2008-02-25
- */
-static rsRetVal
-GetVar(cstr_t *pstrVarName, var_t **ppVar)
-{
- DEFiRet;
- var_t *pVar;
- cstr_t *pstrProp;
-
- ASSERT(pstrVarName != NULL);
- ASSERT(ppVar != NULL);
-
- /* make sure we have a var_t instance */
- CHKiRet(var.Construct(&pVar));
- CHKiRet(var.ConstructFinalize(pVar));
-
- /* now begin the actual variable evaluation */
- if(!rsCStrSzStrCmp(pstrVarName, (uchar*)"now", sizeof("now") - 1)) {
- CHKiRet(getNOW(NOW_NOW, &pstrProp));
- } else if(!rsCStrSzStrCmp(pstrVarName, (uchar*)"year", sizeof("year") - 1)) {
- CHKiRet(getNOW(NOW_YEAR, &pstrProp));
- } else if(!rsCStrSzStrCmp(pstrVarName, (uchar*)"month", sizeof("month") - 1)) {
- CHKiRet(getNOW(NOW_MONTH, &pstrProp));
- } else if(!rsCStrSzStrCmp(pstrVarName, (uchar*)"day", sizeof("day") - 1)) {
- CHKiRet(getNOW(NOW_DAY, &pstrProp));
- } else if(!rsCStrSzStrCmp(pstrVarName, (uchar*)"hour", sizeof("hour") - 1)) {
- CHKiRet(getNOW(NOW_HOUR, &pstrProp));
- } else if(!rsCStrSzStrCmp(pstrVarName, (uchar*)"minute", sizeof("minute") - 1)) {
- CHKiRet(getNOW(NOW_MINUTE, &pstrProp));
- } else if(!rsCStrSzStrCmp(pstrVarName, (uchar*)"myhostname", sizeof("myhostname") - 1)) {
- CHKiRet(rsCStrConstructFromszStr(&pstrProp, glbl.GetLocalHostName()));
- } else {
- ABORT_FINALIZE(RS_RET_SYSVAR_NOT_FOUND);
- }
-
- /* now hand the string over to the var object */
- CHKiRet(var.SetString(pVar, pstrProp));
-
- /* finally store var */
- *ppVar = pVar;
-
-finalize_it:
- RETiRet;
-}
-
-
-/* queryInterface function
- * rgerhards, 2008-02-21
- */
-BEGINobjQueryInterface(sysvar)
-CODESTARTobjQueryInterface(sysvar)
- if(pIf->ifVersion != sysvarCURR_IF_VERSION) { /* check for current version, increment on each change */
- ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
- }
-
- /* ok, we have the right interface, so let's fill it
- * Please note that we may also do some backwards-compatibility
- * work here (if we can support an older interface version - that,
- * of course, also affects the "if" above).
- */
- pIf->Construct = sysvarConstruct;
- pIf->ConstructFinalize = sysvarConstructFinalize;
- pIf->Destruct = sysvarDestruct;
- pIf->GetVar = GetVar;
-finalize_it:
-ENDobjQueryInterface(sysvar)
-
-
-/* Initialize the sysvar class. Must be called as the very first method
- * before anything else is called inside this class.
- * rgerhards, 2008-02-19
- */
-BEGINObjClassInit(sysvar, 1, OBJ_IS_CORE_MODULE) /* class, version */
- /* request objects we use */
- CHKiRet(objUse(var, CORE_COMPONENT));
- CHKiRet(objUse(datetime, CORE_COMPONENT));
- CHKiRet(objUse(glbl, CORE_COMPONENT));
-
- /* set our own handlers */
- OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, sysvarConstructFinalize);
-ENDObjClassInit(sysvar)
-
-/* vi:set ai:
- */
diff --git a/runtime/sysvar.h b/runtime/sysvar.h
deleted file mode 100644
index 35051b64..00000000
--- a/runtime/sysvar.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* The sysvar object. So far, no instance can be defined (makes logically no
- * sense).
- *
- * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
- *
- * This file is part of the rsyslog runtime library.
- *
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
- */
-#ifndef INCLUDED_SYSVAR_H
-#define INCLUDED_SYSVAR_H
-
-/* the sysvar object - not really used... */
-typedef struct sysvar_s {
- BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
-} sysvar_t;
-
-
-/* interfaces */
-BEGINinterface(sysvar) /* name must also be changed in ENDinterface macro! */
- INTERFACEObjDebugPrint(sysvar);
- rsRetVal (*Construct)(sysvar_t **ppThis);
- rsRetVal (*ConstructFinalize)(sysvar_t __attribute__((unused)) *pThis);
- rsRetVal (*Destruct)(sysvar_t **ppThis);
- rsRetVal (*GetVar)(cstr_t *pstrPropName, var_t **ppVar);
-ENDinterface(sysvar)
-#define sysvarCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
-
-
-/* prototypes */
-PROTOTYPEObj(sysvar);
-
-#endif /* #ifndef INCLUDED_SYSVAR_H */
diff --git a/runtime/vm.c b/runtime/vm.c
deleted file mode 100644
index bbc8d346..00000000
--- a/runtime/vm.c
+++ /dev/null
@@ -1,869 +0,0 @@
-/* vm.c - the arithmetic stack of a virtual machine.
- *
- * Module begun 2008-02-22 by Rainer Gerhards
- *
- * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
- *
- * This file is part of the rsyslog runtime library.
- *
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
- */
-
-#include "config.h"
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <ctype.h>
-
-#include "rsyslog.h"
-#include "obj.h"
-#include "vm.h"
-#include "sysvar.h"
-#include "stringbuf.h"
-#include "unicode-helper.h"
-
-/* static data */
-DEFobjStaticHelpers
-DEFobjCurrIf(vmstk)
-DEFobjCurrIf(var)
-DEFobjCurrIf(sysvar)
-
-static pthread_mutex_t mutGetenv; /* we need to make this global because otherwise we can not guarantee proper init! */
-
-/* ------------------------------ function registry code and structures ------------------------------ */
-
-/* we maintain a registry of known functions */
-/* currently, this is a singly-linked list, this shall become a binary
- * tree when we add the real call interface. So far, entries are added
- * at the root, only.
- */
-typedef struct s_rsf_entry {
- cstr_t *pName; /* function name */
- prsf_t rsf; /* pointer to function code */
- struct s_rsf_entry *pNext; /* Pointer to next element or NULL */
-} rsf_entry_t;
-rsf_entry_t *funcRegRoot = NULL;
-
-
-/* add a function to the function registry.
- * The handed-over cstr_t* object must no longer be used by the caller.
- * A duplicate function name is an error.
- * rgerhards, 2009-04-06
- */
-static rsRetVal
-rsfrAddFunction(uchar *szName, prsf_t rsf)
-{
- rsf_entry_t *pEntry;
- size_t lenName;
- DEFiRet;
-
- assert(szName != NULL);
- assert(rsf != NULL);
-
- /* first check if we have a duplicate name, with the current approach this means
- * we need to go through the whole list.
- */
- lenName = strlen((char*)szName);
- for(pEntry = funcRegRoot ; pEntry != NULL ; pEntry = pEntry->pNext)
- if(!rsCStrSzStrCmp(pEntry->pName, szName, lenName))
- ABORT_FINALIZE(RS_RET_DUP_FUNC_NAME);
-
- /* unique name, so add to head of list */
- CHKmalloc(pEntry = calloc(1, sizeof(rsf_entry_t)));
- CHKiRet(rsCStrConstructFromszStr(&pEntry->pName, szName));
- CHKiRet(cstrFinalize(pEntry->pName));
- pEntry->rsf = rsf;
- pEntry->pNext = funcRegRoot;
- funcRegRoot = pEntry;
-
-finalize_it:
- if(iRet != RS_RET_OK && iRet != RS_RET_DUP_FUNC_NAME)
- free(pEntry);
-
- RETiRet;
-}
-
-
-/* find a function inside the function registry
- * The caller provides a cstr_t with the function name and receives
- * a function pointer back. If no function is found, an RS_RET_UNKNW_FUNC
- * error is returned. So if the function returns with RS_RET_OK, the caller
- * can savely assume the function pointer is valid.
- * rgerhards, 2009-04-06
- */
-static rsRetVal
-findRSFunction(cstr_t *pcsName, prsf_t *prsf)
-{
- rsf_entry_t *pEntry;
- rsf_entry_t *pFound;
- DEFiRet;
-
- assert(prsf != NULL);
-
- /* find function by list walkthrough. */
- pFound = NULL;
- for(pEntry = funcRegRoot ; pEntry != NULL && pFound == NULL ; pEntry = pEntry->pNext)
- if(!rsCStrCStrCmp(pEntry->pName, pcsName))
- pFound = pEntry;
-
- if(pFound == NULL)
- ABORT_FINALIZE(RS_RET_UNKNW_FUNC);
-
- *prsf = pFound->rsf;
-
-finalize_it:
- RETiRet;
-}
-
-
-/* find the name of a RainerScript function whom's function pointer
- * is known. This function returns the cstr_t object, which MUST NOT
- * be modified by the caller.
- * rgerhards, 2009-04-06
- */
-static rsRetVal
-findRSFunctionName(prsf_t rsf, cstr_t **ppcsName)
-{
- rsf_entry_t *pEntry;
- rsf_entry_t *pFound;
- DEFiRet;
-
- assert(rsf != NULL);
- assert(ppcsName != NULL);
-
- /* find function by list walkthrough. */
- pFound = NULL;
- for(pEntry = funcRegRoot ; pEntry != NULL && pFound == NULL ; pEntry = pEntry->pNext)
- if(pEntry->rsf == rsf)
- pFound = pEntry;
-
- if(pFound == NULL)
- ABORT_FINALIZE(RS_RET_UNKNW_FUNC);
-
- *ppcsName = pFound->pName;
-
-finalize_it:
- RETiRet;
-}
-
-
-/* free the whole function registry
- */
-static void
-rsfrRemoveAll(void)
-{
- rsf_entry_t *pEntry;
- rsf_entry_t *pEntryDel;
-
- BEGINfunc
- pEntry = funcRegRoot;
- while(pEntry != NULL) {
- pEntryDel = pEntry;
- pEntry = pEntry->pNext;
- cstrDestruct(&pEntryDel->pName);
- free(pEntryDel);
- }
- funcRegRoot = NULL;
- ENDfunc
-}
-
-
-/* ------------------------------ end function registry code and structures ------------------------------ */
-
-
-/* ------------------------------ instruction set implementation ------------------------------ *
- * The following functions implement the VM's instruction set.
- */
-#define BEGINop(instruction) \
- static rsRetVal op##instruction(vm_t *pThis, __attribute__((unused)) vmop_t *pOp) \
- { \
- DEFiRet;
-
-#define CODESTARTop(instruction) \
- ISOBJ_TYPE_assert(pThis, vm);
-
-#define PUSHRESULTop(operand, res) \
- /* we have a result, so let's push it */ \
- var.SetNumber(operand, res); \
- vmstk.Push(pThis->pStk, operand); /* result */
-
-#define ENDop(instruction) \
- RETiRet; \
- }
-
-/* code generator for boolean operations */
-#define BOOLOP(name, OPERATION) \
-BEGINop(name) /* remember to set the instruction also in the ENDop macro! */ \
- var_t *operand1; \
- var_t *operand2; \
-CODESTARTop(name) \
- vmstk.PopBool(pThis->pStk, &operand1); \
- vmstk.PopBool(pThis->pStk, &operand2); \
- if(operand1->val.num OPERATION operand2->val.num) { \
- CHKiRet(var.SetNumber(operand1, 1)); \
- } else { \
- CHKiRet(var.SetNumber(operand1, 0)); \
- } \
- vmstk.Push(pThis->pStk, operand1); /* result */ \
- var.Destruct(&operand2); /* no longer needed */ \
-finalize_it: \
-ENDop(name)
-BOOLOP(OR, ||)
-BOOLOP(AND, &&)
-#undef BOOLOP
-
-
-/* code generator for numerical operations */
-#define NUMOP(name, OPERATION) \
-BEGINop(name) /* remember to set the instruction also in the ENDop macro! */ \
- var_t *operand1; \
- var_t *operand2; \
-CODESTARTop(name) \
- vmstk.PopNumber(pThis->pStk, &operand1); \
- vmstk.PopNumber(pThis->pStk, &operand2); \
- operand1->val.num = operand1->val.num OPERATION operand2->val.num; \
- vmstk.Push(pThis->pStk, operand1); /* result */ \
- var.Destruct(&operand2); /* no longer needed */ \
-ENDop(name)
-NUMOP(PLUS, +)
-NUMOP(MINUS, -)
-NUMOP(TIMES, *)
-NUMOP(DIV, /)
-NUMOP(MOD, %)
-#undef BOOLOP
-
-
-/* code generator for compare operations */
-#define BEGINCMPOP(name) \
-BEGINop(name) \
- var_t *operand1; \
- var_t *operand2; \
- number_t bRes; \
-CODESTARTop(name) \
- CHKiRet(vmstk.Pop2CommOp(pThis->pStk, &operand1, &operand2)); \
- /* data types are equal (so we look only at operand1), but we must \
- * check which type we have to deal with... \
- */ \
- switch(operand1->varType) {
-#define ENDCMPOP(name) \
- default: \
- bRes = 0; /* we do not abort just so that we have a value. TODO: reconsider */ \
- break; \
- } \
- \
- /* we have a result, so let's push it */ \
- var.SetNumber(operand1, bRes); \
- vmstk.Push(pThis->pStk, operand1); /* result */ \
- var.Destruct(&operand2); /* no longer needed */ \
-finalize_it: \
-ENDop(name)
-
-BEGINCMPOP(CMP_EQ) /* remember to change the name also in the END macro! */
- case VARTYPE_NUMBER:
- bRes = operand1->val.num == operand2->val.num;
- break;
- case VARTYPE_STR:
- bRes = !rsCStrCStrCmp(operand1->val.pStr, operand2->val.pStr);
- break;
-ENDCMPOP(CMP_EQ)
-
-BEGINCMPOP(CMP_NEQ) /* remember to change the name also in the END macro! */
- case VARTYPE_NUMBER:
- bRes = operand1->val.num != operand2->val.num;
- break;
- case VARTYPE_STR:
- bRes = rsCStrCStrCmp(operand1->val.pStr, operand2->val.pStr);
- break;
-ENDCMPOP(CMP_NEQ)
-
-BEGINCMPOP(CMP_LT) /* remember to change the name also in the END macro! */
- case VARTYPE_NUMBER:
- bRes = operand1->val.num < operand2->val.num;
- break;
- case VARTYPE_STR:
- bRes = rsCStrCStrCmp(operand1->val.pStr, operand2->val.pStr) < 0;
- break;
-ENDCMPOP(CMP_LT)
-
-BEGINCMPOP(CMP_GT) /* remember to change the name also in the END macro! */
- case VARTYPE_NUMBER:
- bRes = operand1->val.num > operand2->val.num;
- break;
- case VARTYPE_STR:
- bRes = rsCStrCStrCmp(operand1->val.pStr, operand2->val.pStr) > 0;
- break;
-ENDCMPOP(CMP_GT)
-
-BEGINCMPOP(CMP_LTEQ) /* remember to change the name also in the END macro! */
- case VARTYPE_NUMBER:
- bRes = operand1->val.num <= operand2->val.num;
- break;
- case VARTYPE_STR:
- bRes = rsCStrCStrCmp(operand1->val.pStr, operand2->val.pStr) <= 0;
- break;
-ENDCMPOP(CMP_LTEQ)
-
-BEGINCMPOP(CMP_GTEQ) /* remember to change the name also in the END macro! */
- case VARTYPE_NUMBER:
- bRes = operand1->val.num >= operand2->val.num;
- break;
- case VARTYPE_STR:
- bRes = rsCStrCStrCmp(operand1->val.pStr, operand2->val.pStr) >= 0;
- break;
-ENDCMPOP(CMP_GTEQ)
-
-#undef BEGINCMPOP
-#undef ENDCMPOP
-/* end regular compare operations */
-
-/* comare operations that work on strings, only */
-BEGINop(CMP_CONTAINS) /* remember to set the instruction also in the ENDop macro! */
- var_t *operand1;
- var_t *operand2;
- number_t bRes;
-CODESTARTop(CMP_CONTAINS)
- /* operand2 is on top of stack, so needs to be popped first */
- vmstk.PopString(pThis->pStk, &operand2);
- vmstk.PopString(pThis->pStk, &operand1);
- /* TODO: extend cstr class so that it supports location of cstr inside cstr */
- bRes = (rsCStrLocateInSzStr(operand2->val.pStr, rsCStrGetSzStr(operand1->val.pStr)) == -1) ? 0 : 1;
-
- /* we have a result, so let's push it */
- PUSHRESULTop(operand1, bRes);
- var.Destruct(&operand2); /* no longer needed */
-ENDop(CMP_CONTAINS)
-
-
-BEGINop(CMP_CONTAINSI) /* remember to set the instruction also in the ENDop macro! */
- var_t *operand1;
- var_t *operand2;
- number_t bRes;
-CODESTARTop(CMP_CONTAINSI)
- /* operand2 is on top of stack, so needs to be popped first */
- vmstk.PopString(pThis->pStk, &operand2);
- vmstk.PopString(pThis->pStk, &operand1);
-var.DebugPrint(operand1); \
-var.DebugPrint(operand2); \
- /* TODO: extend cstr class so that it supports location of cstr inside cstr */
- bRes = (rsCStrCaseInsensitiveLocateInSzStr(operand2->val.pStr, rsCStrGetSzStr(operand1->val.pStr)) == -1) ? 0 : 1;
-
- /* we have a result, so let's push it */
- PUSHRESULTop(operand1, bRes);
- var.Destruct(&operand2); /* no longer needed */
-ENDop(CMP_CONTAINSI)
-
-
-BEGINop(CMP_STARTSWITH) /* remember to set the instruction also in the ENDop macro! */
- var_t *operand1;
- var_t *operand2;
- number_t bRes;
-CODESTARTop(CMP_STARTSWITH)
- /* operand2 is on top of stack, so needs to be popped first */
- vmstk.PopString(pThis->pStk, &operand2);
- vmstk.PopString(pThis->pStk, &operand1);
- /* TODO: extend cstr class so that it supports location of cstr inside cstr */
- bRes = (rsCStrStartsWithSzStr(operand1->val.pStr, rsCStrGetSzStr(operand2->val.pStr),
- rsCStrLen(operand2->val.pStr)) == 0) ? 1 : 0;
-
- /* we have a result, so let's push it */
- PUSHRESULTop(operand1, bRes);
- var.Destruct(&operand2); /* no longer needed */
-ENDop(CMP_STARTSWITH)
-
-
-BEGINop(CMP_STARTSWITHI) /* remember to set the instruction also in the ENDop macro! */
- var_t *operand1;
- var_t *operand2;
- number_t bRes;
-CODESTARTop(CMP_STARTSWITHI)
- /* operand2 is on top of stack, so needs to be popped first */
- vmstk.PopString(pThis->pStk, &operand2);
- vmstk.PopString(pThis->pStk, &operand1);
- /* TODO: extend cstr class so that it supports location of cstr inside cstr */
- bRes = (rsCStrCaseInsensitveStartsWithSzStr(operand1->val.pStr, rsCStrGetSzStr(operand2->val.pStr),
- rsCStrLen(operand2->val.pStr)) == 0) ? 1 : 0;
-
- /* we have a result, so let's push it */
- PUSHRESULTop(operand1, bRes);
- var.Destruct(&operand2); /* no longer needed */
-ENDop(CMP_STARTSWITHI)
-
-/* end comare operations that work on strings, only */
-
-BEGINop(STRADD) /* remember to set the instruction also in the ENDop macro! */
- var_t *operand1;
- var_t *operand2;
-CODESTARTop(STRADD)
- vmstk.PopString(pThis->pStk, &operand2);
- vmstk.PopString(pThis->pStk, &operand1);
-
- CHKiRet(rsCStrAppendCStr(operand1->val.pStr, operand2->val.pStr));
- CHKiRet(cstrFinalize(operand1->val.pStr));
-
- /* we have a result, so let's push it */
- vmstk.Push(pThis->pStk, operand1);
- var.Destruct(&operand2); /* no longer needed */
-finalize_it:
-ENDop(STRADD)
-
-BEGINop(NOT) /* remember to set the instruction also in the ENDop macro! */
- var_t *operand;
-CODESTARTop(NOT)
- vmstk.PopBool(pThis->pStk, &operand);
- PUSHRESULTop(operand, !operand->val.num);
-ENDop(NOT)
-
-BEGINop(UNARY_MINUS) /* remember to set the instruction also in the ENDop macro! */
- var_t *operand;
-CODESTARTop(UNARY_MINUS)
- vmstk.PopNumber(pThis->pStk, &operand);
- PUSHRESULTop(operand, -operand->val.num);
-ENDop(UNARY_MINUS)
-
-
-BEGINop(PUSHCONSTANT) /* remember to set the instruction also in the ENDop macro! */
- var_t *pVarDup; /* we need to duplicate the var, as we need to hand it over */
-CODESTARTop(PUSHCONSTANT)
- CHKiRet(var.Duplicate(pOp->operand.pVar, &pVarDup));
- vmstk.Push(pThis->pStk, pVarDup);
-finalize_it:
-ENDop(PUSHCONSTANT)
-
-
-BEGINop(PUSHMSGVAR) /* remember to set the instruction also in the ENDop macro! */
- var_t *pVal; /* the value to push */
- cstr_t *pstrVal;
-CODESTARTop(PUSHMSGVAR)
-dbgprintf("XXX: pushMSGVAR, var '%s'\n", rsCStrGetSzStr(pOp->operand.pVar->val.pStr));
- if(pThis->pMsg == NULL) {
- /* TODO: flag an error message! As a work-around, we permit
- * execution to continue here with an empty string
- */
- /* TODO: create a method in var to create a string var? */
- CHKiRet(var.Construct(&pVal));
- CHKiRet(var.ConstructFinalize(pVal));
- CHKiRet(rsCStrConstructFromszStr(&pstrVal, (uchar*)""));
- CHKiRet(var.SetString(pVal, pstrVal));
- } else {
- /* we have a message, so pull value from there */
- CHKiRet(msgGetMsgVar(pThis->pMsg, pOp->operand.pVar->val.pStr, &pVal));
- }
-
- /* if we reach this point, we have a valid pVal and can push it */
- vmstk.Push(pThis->pStk, pVal);
-finalize_it:
-ENDop(PUSHMSGVAR)
-
-
-BEGINop(PUSHCEEVAR) /* remember to set the instruction also in the ENDop macro! */
- var_t *pVal; /* the value to push */
- cstr_t *pstrVal;
-CODESTARTop(PUSHCEEVAR)
-dbgprintf("XXX: pushCEEVAR, var '%s'\n", rsCStrGetSzStr(pOp->operand.pVar->val.pStr));
- if(pThis->pMsg == NULL) {
- /* TODO: flag an error message! As a work-around, we permit
- * execution to continue here with an empty string
- */
- CHKiRet(var.Construct(&pVal));
- CHKiRet(var.ConstructFinalize(pVal));
- CHKiRet(rsCStrConstructFromszStr(&pstrVal, (uchar*)""));
- CHKiRet(var.SetString(pVal, pstrVal));
- } else {
- /* we have a message, so pull value from there */
- CHKiRet(msgGetCEEVar(pThis->pMsg, pOp->operand.pVar->val.pStr, &pVal));
- }
-
- /* if we reach this point, we have a valid pVal and can push it */
- vmstk.Push(pThis->pStk, pVal);
-dbgprintf("XXX: pushCEEVAR, result '%s'\n", rsCStrGetSzStr(pVal->val.pStr));
-finalize_it:
-ENDop(PUSHCEEVAR)
-
-
-BEGINop(PUSHSYSVAR) /* remember to set the instruction also in the ENDop macro! */
- var_t *pVal; /* the value to push */
-CODESTARTop(PUSHSYSVAR)
- CHKiRet(sysvar.GetVar(pOp->operand.pVar->val.pStr, &pVal));
- vmstk.Push(pThis->pStk, pVal);
-finalize_it:
- if(Debug && iRet != RS_RET_OK) {
- if(iRet == RS_RET_SYSVAR_NOT_FOUND) {
- DBGPRINTF("rainerscript: sysvar '%s' not found\n",
- rsCStrGetSzStrNoNULL(pOp->operand.pVar->val.pStr));
- } else {
- DBGPRINTF("rainerscript: error %d trying to obtain sysvar '%s'\n",
- iRet, rsCStrGetSzStrNoNULL(pOp->operand.pVar->val.pStr));
- }
- }
-ENDop(PUSHSYSVAR)
-
-/* The function call operation is only very roughly implemented. While the plumbing
- * to reach this instruction is fine, the instruction itself currently supports only
- * functions with a single argument AND with a name that we know.
- * TODO: later, we can add here the real logic, that involves looking up function
- * names, loading them dynamically ... and all that...
- * implementation begun 2009-03-10 by rgerhards
- */
-BEGINop(FUNC_CALL) /* remember to set the instruction also in the ENDop macro! */
- var_t *numOperands;
-CODESTARTop(FUNC_CALL)
- vmstk.PopNumber(pThis->pStk, &numOperands);
- CHKiRet((*pOp->operand.rsf)(pThis->pStk, numOperands->val.num));
- var.Destruct(&numOperands); /* no longer needed */
-finalize_it:
-ENDop(FUNC_CALL)
-
-
-/* ------------------------------ end instruction set implementation ------------------------------ */
-
-
-/* ------------------------------ begin built-in function implementation ------------------------------ */
-/* note: this shall probably be moved to a separate module, but for the time being we do it directly
- * in here. This is on our way to get from a dirty to a clean solution via baby steps that are
- * a bit less dirty each time...
- *
- * The advantage of doing it here is that we do not yet need to think about how to handle the
- * exit case, where we must not unload function modules which functions are still referenced.
- *
- * CALLING INTERFACE:
- * The function must pop its parameters off the stack and pop its result onto
- * the stack when it is finished. The number of parameters the function was
- * called with is provided to it. If the argument count is less then what the function
- * expected, it may handle the situation with defaults (or return an error). If the
- * argument count is greater than expected, returnung an error is highly
- * recommended (use RS_RET_INVLD_NBR_ARGUMENTS for these cases).
- *
- * All function names are prefixed with "rsf_" (RainerScript Function) to have
- * a separate "name space".
- *
- * rgerhards, 2009-04-06
- */
-
-
-/* The strlen function, also probably a prototype of how all functions should be
- * implemented.
- * rgerhards, 2009-04-06
- */
-static rsRetVal
-rsf_strlen(vmstk_t *pStk, int numOperands)
-{
- DEFiRet;
- var_t *operand1;
- int iStrlen;
-
- if(numOperands != 1)
- ABORT_FINALIZE(RS_RET_INVLD_NBR_ARGUMENTS);
-
- /* pop args and do operaton (trivial case here...) */
- vmstk.PopString(pStk, &operand1);
- iStrlen = strlen((char*) rsCStrGetSzStr(operand1->val.pStr));
-
- /* Store result and cleanup */
- var.SetNumber(operand1, iStrlen);
- vmstk.Push(pStk, operand1);
-finalize_it:
- RETiRet;
-}
-
-
-/* The getenv function. Note that we guard the OS call by a mutex, as that
- * function is not guaranteed to be thread-safe. This implementation here is far from
- * being optimal, at least we should cache the result. This is left TODO for
- * a later revision.
- * rgerhards, 2009-11-03
- */
-static rsRetVal
-rsf_getenv(vmstk_t *pStk, int numOperands)
-{
- DEFiRet;
- var_t *operand1;
- char *envResult;
- cstr_t *pCstr;
-
- if(numOperands != 1)
- ABORT_FINALIZE(RS_RET_INVLD_NBR_ARGUMENTS);
-
- /* pop args and do operaton (trivial case here...) */
- vmstk.PopString(pStk, &operand1);
- d_pthread_mutex_lock(&mutGetenv);
- envResult = getenv((char*) rsCStrGetSzStr(operand1->val.pStr));
- DBGPRINTF("rsf_getenv(): envvar '%s', return '%s'\n", rsCStrGetSzStr(operand1->val.pStr),
- envResult == NULL ? "(NULL)" : envResult);
- iRet = rsCStrConstructFromszStr(&pCstr, (envResult == NULL) ? UCHAR_CONSTANT("") : (uchar*)envResult);
- d_pthread_mutex_unlock(&mutGetenv);
- if(iRet != RS_RET_OK)
- FINALIZE; /* need to do this after mutex is unlocked! */
-
- /* Store result and cleanup */
- var.SetString(operand1, pCstr);
- vmstk.Push(pStk, operand1);
-finalize_it:
- RETiRet;
-}
-
-
-/* The "tolower" function, which converts its sole argument to lower case.
- * Quite honestly, currently this is primarily a test driver for me...
- * rgerhards, 2009-04-06
- */
-static rsRetVal
-rsf_tolower(vmstk_t *pStk, int numOperands)
-{
- DEFiRet;
- var_t *operand1;
- uchar *pSrc;
- cstr_t *pcstr;
- int iStrlen;
-
- if(numOperands != 1)
- ABORT_FINALIZE(RS_RET_INVLD_NBR_ARGUMENTS);
-
- /* pop args and do operaton */
- CHKiRet(cstrConstruct(&pcstr));
- vmstk.PopString(pStk, &operand1);
- pSrc = cstrGetSzStr(operand1->val.pStr);
- iStrlen = strlen((char*)pSrc); // TODO: use count from string!
- while(iStrlen--) {
- CHKiRet(cstrAppendChar(pcstr, tolower(*pSrc++)));
- }
-
- /* Store result and cleanup */
- CHKiRet(cstrFinalize(pcstr));
- var.SetString(operand1, pcstr);
- vmstk.Push(pStk, operand1);
-finalize_it:
- RETiRet;
-}
-
-
-/* Standard-Constructor
- */
-BEGINobjConstruct(vm) /* be sure to specify the object type also in END macro! */
-ENDobjConstruct(vm)
-
-
-/* ConstructionFinalizer
- * rgerhards, 2008-01-09
- */
-static rsRetVal
-vmConstructFinalize(vm_t __attribute__((unused)) *pThis)
-{
- DEFiRet;
- ISOBJ_TYPE_assert(pThis, vm);
-
- CHKiRet(vmstk.Construct(&pThis->pStk));
- CHKiRet(vmstk.ConstructFinalize(pThis->pStk));
-
-finalize_it:
- RETiRet;
-}
-
-
-/* destructor for the vm object */
-BEGINobjDestruct(vm) /* be sure to specify the object type also in END and CODESTART macros! */
-CODESTARTobjDestruct(vm)
- if(pThis->pStk != NULL)
- vmstk.Destruct(&pThis->pStk);
- if(pThis->pMsg != NULL)
- msgDestruct(&pThis->pMsg);
-ENDobjDestruct(vm)
-
-
-/* debugprint for the vm object */
-BEGINobjDebugPrint(vm) /* be sure to specify the object type also in END and CODESTART macros! */
-CODESTARTobjDebugPrint(vm)
- dbgoprint((obj_t*) pThis, "rsyslog virtual machine, currently no state info available\n");
-ENDobjDebugPrint(vm)
-
-
-/* execute a program
- */
-static rsRetVal
-execProg(vm_t *pThis, vmprg_t *pProg)
-{
- DEFiRet;
- vmop_t *pCurrOp; /* virtual instruction pointer */
-
- ISOBJ_TYPE_assert(pThis, vm);
- ISOBJ_TYPE_assert(pProg, vmprg);
-
-#define doOP(OP) case opcode_##OP: DBGPRINTF("rainerscript: opcode %s\n", #OP); \
- CHKiRet(op##OP(pThis, pCurrOp)); break
- pCurrOp = pProg->vmopRoot; /* TODO: do this via a method! */
- while(pCurrOp != NULL && pCurrOp->opcode != opcode_END_PROG) {
- DBGPRINTF("rainerscript: executing step, opcode %d...\n", pCurrOp->opcode);
- switch(pCurrOp->opcode) {
- doOP(OR);
- doOP(AND);
- doOP(CMP_EQ);
- doOP(CMP_NEQ);
- doOP(CMP_LT);
- doOP(CMP_GT);
- doOP(CMP_LTEQ);
- doOP(CMP_GTEQ);
- doOP(CMP_CONTAINS);
- doOP(CMP_CONTAINSI);
- doOP(CMP_STARTSWITH);
- doOP(CMP_STARTSWITHI);
- doOP(NOT);
- doOP(PUSHCONSTANT);
- doOP(PUSHMSGVAR);
- doOP(PUSHCEEVAR);
- doOP(PUSHSYSVAR);
- doOP(STRADD);
- doOP(PLUS);
- doOP(MINUS);
- doOP(TIMES);
- doOP(DIV);
- doOP(MOD);
- doOP(UNARY_MINUS);
- doOP(FUNC_CALL);
- default:
- dbgoprint((obj_t*) pThis, "invalid instruction %d in vmprg\n", pCurrOp->opcode);
- ABORT_FINALIZE(RS_RET_INVALID_VMOP);
- break;
- }
- /* so far, we have plain sequential execution, so on to next... */
- pCurrOp = pCurrOp->pNext;
- }
-#undef doOP
-
- /* if we reach this point, our program has intintionally terminated
- * (no error state).
- */
-
-finalize_it:
- DBGPRINTF("rainerscript: script execution terminated with state %d\n", iRet);
- RETiRet;
-}
-
-
-/* Set the current message object for the VM. It *is* valid to set a
- * NULL message object, what simply means there is none. Message
- * objects are properly reference counted.
- */
-static rsRetVal
-SetMsg(vm_t *pThis, msg_t *pMsg)
-{
- DEFiRet;
- if(pThis->pMsg != NULL) {
- msgDestruct(&pThis->pMsg);
- }
-
- if(pMsg != NULL) {
- pThis->pMsg = MsgAddRef(pMsg);
- }
-
- RETiRet;
-}
-
-
-/* Pop a var from the stack and return it to caller. The variable type is not
- * changed, it is taken from the stack as is. This functionality is
- * partly needed. We may (or may not ;)) be able to remove it once we have
- * full RainerScript support. -- rgerhards, 2008-02-25
- */
-static rsRetVal
-PopVarFromStack(vm_t *pThis, var_t **ppVar)
-{
- DEFiRet;
- CHKiRet(vmstk.Pop(pThis->pStk, ppVar));
-finalize_it:
- RETiRet;
-}
-
-
-/* Pop a boolean from the stack and return it to caller. This functionality is
- * partly needed. We may (or may not ;)) be able to remove it once we have
- * full RainerScript support. -- rgerhards, 2008-02-25
- */
-static rsRetVal
-PopBoolFromStack(vm_t *pThis, var_t **ppVar)
-{
- DEFiRet;
- CHKiRet(vmstk.PopBool(pThis->pStk, ppVar));
-finalize_it:
- RETiRet;
-}
-
-
-/* queryInterface function
- * rgerhards, 2008-02-21
- */
-BEGINobjQueryInterface(vm)
-CODESTARTobjQueryInterface(vm)
- if(pIf->ifVersion != vmCURR_IF_VERSION) { /* check for current version, increment on each change */
- ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
- }
-
- /* ok, we have the right interface, so let's fill it
- * Please note that we may also do some backwards-compatibility
- * work here (if we can support an older interface version - that,
- * of course, also affects the "if" above).
- */
- pIf->Construct = vmConstruct;
- pIf->ConstructFinalize = vmConstructFinalize;
- pIf->Destruct = vmDestruct;
- pIf->DebugPrint = vmDebugPrint;
- pIf->ExecProg = execProg;
- pIf->PopBoolFromStack = PopBoolFromStack;
- pIf->PopVarFromStack = PopVarFromStack;
- pIf->SetMsg = SetMsg;
- pIf->FindRSFunction = findRSFunction;
- pIf->FindRSFunctionName = findRSFunctionName;
-finalize_it:
-ENDobjQueryInterface(vm)
-
-
-/* Exit the vm class.
- * rgerhards, 2009-04-06
- */
-BEGINObjClassExit(vm, OBJ_IS_CORE_MODULE) /* class, version */
- rsfrRemoveAll();
- objRelease(sysvar, CORE_COMPONENT);
- objRelease(var, CORE_COMPONENT);
- objRelease(vmstk, CORE_COMPONENT);
-
- pthread_mutex_destroy(&mutGetenv);
-ENDObjClassExit(vm)
-
-
-/* Initialize the vm class. Must be called as the very first method
- * before anything else is called inside this class.
- * rgerhards, 2008-02-19
- */
-BEGINObjClassInit(vm, 1, OBJ_IS_CORE_MODULE) /* class, version */
- /* request objects we use */
- CHKiRet(objUse(vmstk, CORE_COMPONENT));
- CHKiRet(objUse(var, CORE_COMPONENT));
- CHKiRet(objUse(sysvar, CORE_COMPONENT));
-
- /* set our own handlers */
- OBJSetMethodHandler(objMethod_DEBUGPRINT, vmDebugPrint);
- OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, vmConstructFinalize);
-
- /* register built-in functions // TODO: move to its own module */
- CHKiRet(rsfrAddFunction((uchar*)"strlen", rsf_strlen));
- CHKiRet(rsfrAddFunction((uchar*)"tolower", rsf_tolower));
- CHKiRet(rsfrAddFunction((uchar*)"getenv", rsf_getenv));
-
- pthread_mutex_init(&mutGetenv, NULL);
-
-ENDObjClassInit(vm)
-
-/* vi:set ai:
- */
diff --git a/runtime/vm.h b/runtime/vm.h
deleted file mode 100644
index cb3c69d0..00000000
--- a/runtime/vm.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* The vm object.
- *
- * This implements the rsyslog virtual machine. The initial implementation is
- * done to support complex user-defined expressions, but it may evolve into a
- * much more useful thing over time.
- *
- * The virtual machine uses rsyslog variables as its memory storage system.
- * All computation is done on a stack (vmstk). The vm supports a given
- * instruction set and executes programs of type vmprg, which consist of
- * single operations defined in vmop (which hold the instruction and the
- * data).
- *
- * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
- *
- * This file is part of the rsyslog runtime library.
- *
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
- */
-#ifndef INCLUDED_VM_H
-#define INCLUDED_VM_H
-
-#include "msg.h"
-#include "vmstk.h"
-#include "vmprg.h"
-
-/* the vm object */
-typedef struct vm_s {
- BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
- vmstk_t *pStk; /* The stack */
- msg_t *pMsg; /* the current message (or NULL, if we have none) */
-} vm_t;
-
-
-/* interfaces */
-BEGINinterface(vm) /* name must also be changed in ENDinterface macro! */
- INTERFACEObjDebugPrint(vm);
- rsRetVal (*Construct)(vm_t **ppThis);
- rsRetVal (*ConstructFinalize)(vm_t __attribute__((unused)) *pThis);
- rsRetVal (*Destruct)(vm_t **ppThis);
- rsRetVal (*ExecProg)(vm_t *pThis, vmprg_t *pProg);
- rsRetVal (*PopBoolFromStack)(vm_t *pThis, var_t **ppVar); /* there are a few cases where we need this... */
- rsRetVal (*PopVarFromStack)(vm_t *pThis, var_t **ppVar); /* there are a few cases where we need this... */
- rsRetVal (*SetMsg)(vm_t *pThis, msg_t *pMsg); /* there are a few cases where we need this... */
- /* v2 (4.1.7) */
- rsRetVal (*FindRSFunction)(cstr_t *pcsName, prsf_t *prsf); /* 2009-06-04 */
- rsRetVal (*FindRSFunctionName)(prsf_t rsf, cstr_t **ppcsName); /* 2009-06-04 */
-ENDinterface(vm)
-#define vmCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */
-
-
-/* prototypes */
-PROTOTYPEObj(vm);
-
-#endif /* #ifndef INCLUDED_VM_H */
diff --git a/runtime/vmop.c b/runtime/vmop.c
deleted file mode 100644
index ea627220..00000000
--- a/runtime/vmop.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/* vmop.c - abstracts an operation (instructed) supported by the
- * rsyslog virtual machine
- *
- * Module begun 2008-02-20 by Rainer Gerhards
- *
- * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH.
- *
- * This file is part of the rsyslog runtime library.
- *
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
- */
-
-#include "config.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include "rsyslog.h"
-#include "obj.h"
-#include "vmop.h"
-#include "vm.h"
-
-/* static data */
-DEFobjStaticHelpers
-DEFobjCurrIf(var)
-DEFobjCurrIf(vm)
-
-
-/* forward definitions */
-static rsRetVal vmopOpcode2Str(vmop_t *pThis, uchar **ppName);
-
-/* Standard-Constructor
- */
-BEGINobjConstruct(vmop) /* be sure to specify the object type also in END macro! */
-ENDobjConstruct(vmop)
-
-
-/* ConstructionFinalizer
- * rgerhards, 2008-01-09
- */
-rsRetVal vmopConstructFinalize(vmop_t __attribute__((unused)) *pThis)
-{
- DEFiRet;
- ISOBJ_TYPE_assert(pThis, vmop);
- RETiRet;
-}
-
-
-/* destructor for the vmop object */
-BEGINobjDestruct(vmop) /* be sure to specify the object type also in END and CODESTART macros! */
-CODESTARTobjDestruct(vmop)
- if(pThis->opcode != opcode_FUNC_CALL) {
- if(pThis->operand.pVar != NULL)
- var.Destruct(&pThis->operand.pVar);
- }
-ENDobjDestruct(vmop)
-
-
-/* DebugPrint support for the vmop object */
-BEGINobjDebugPrint(vmop) /* be sure to specify the object type also in END and CODESTART macros! */
- uchar *pOpcodeName;
- cstr_t *pStrVar;
-CODESTARTobjDebugPrint(vmop)
- vmopOpcode2Str(pThis, &pOpcodeName);
- if(pThis->opcode == opcode_FUNC_CALL) {
- CHKiRet(vm.FindRSFunctionName(pThis->operand.rsf, &pStrVar));
- assert(pStrVar != NULL);
- } else {
- CHKiRet(rsCStrConstruct(&pStrVar));
- if(pThis->operand.pVar != NULL) {
- CHKiRet(var.Obj2Str(pThis->operand.pVar, pStrVar));
- }
- }
- CHKiRet(cstrFinalize(pStrVar));
- dbgoprint((obj_t*) pThis, "%.12s\t%s\n", pOpcodeName, rsCStrGetSzStrNoNULL(pStrVar));
- if(pThis->opcode != opcode_FUNC_CALL)
- rsCStrDestruct(&pStrVar);
-finalize_it:
-ENDobjDebugPrint(vmop)
-
-
-/* This function is similar to DebugPrint, but does not send its output to
- * the debug log but instead to a caller-provided string. The idea here is that
- * we can use this string to get a textual representation of an operation.
- * Among others, this is useful for creating testbenches, our first use case for
- * it. Here, it enables simple comparison of the resulting program to a
- * reference program by simple string compare.
- * Note that the caller must initialize the string object. We always add
- * data to it. So, it can be easily combined into a chain of methods
- * to generate the final string.
- * rgerhards, 2008-07-04
- */
-static rsRetVal
-Obj2Str(vmop_t *pThis, cstr_t *pstrPrg)
-{
- uchar *pOpcodeName;
- cstr_t *pcsFuncName;
- uchar szBuf[2048];
- size_t lenBuf;
- DEFiRet;
-
- ISOBJ_TYPE_assert(pThis, vmop);
- assert(pstrPrg != NULL);
- vmopOpcode2Str(pThis, &pOpcodeName);
- lenBuf = snprintf((char*) szBuf, sizeof(szBuf), "%s\t", pOpcodeName);
- CHKiRet(rsCStrAppendStrWithLen(pstrPrg, szBuf, lenBuf));
- if(pThis->opcode == opcode_FUNC_CALL) {
- CHKiRet(vm.FindRSFunctionName(pThis->operand.rsf, &pcsFuncName));
- CHKiRet(rsCStrAppendCStr(pstrPrg, pcsFuncName));
- } else {
- if(pThis->operand.pVar != NULL)
- CHKiRet(var.Obj2Str(pThis->operand.pVar, pstrPrg));
- }
- CHKiRet(cstrAppendChar(pstrPrg, '\n'));
-
-finalize_it:
- RETiRet;
-}
-
-
-/* set function
- * rgerhards, 2009-04-06
- */
-static rsRetVal
-vmopSetFunc(vmop_t *pThis, cstr_t *pcsFuncName)
-{
- prsf_t rsf; /* pointer to function */
- DEFiRet;
- ISOBJ_TYPE_assert(pThis, vmop);
- CHKiRet(vm.FindRSFunction(pcsFuncName, &rsf)); /* check if function exists and obtain pointer to it */
- assert(rsf != NULL); /* just double-check, would be very hard to find! */
- pThis->operand.rsf = rsf;
-finalize_it:
- RETiRet;
-}
-
-
-/* set operand (variant case)
- * rgerhards, 2008-02-20
- */
-static rsRetVal
-vmopSetVar(vmop_t *pThis, var_t *pVar)
-{
- DEFiRet;
- ISOBJ_TYPE_assert(pThis, vmop);
- ISOBJ_TYPE_assert(pVar, var);
- pThis->operand.pVar = pVar;
- RETiRet;
-}
-
-
-/* set operation
- * rgerhards, 2008-02-20
- */
-static rsRetVal
-vmopSetOpcode(vmop_t *pThis, opcode_t opcode)
-{
- DEFiRet;
- ISOBJ_TYPE_assert(pThis, vmop);
- pThis->opcode = opcode;
- RETiRet;
-}
-
-
-/* a way to turn an opcode into a readable string
- */
-static rsRetVal
-vmopOpcode2Str(vmop_t *pThis, uchar **ppName)
-{
- DEFiRet;
- ISOBJ_TYPE_assert(pThis, vmop);
-
- switch(pThis->opcode) {
- case opcode_OR:
- *ppName = (uchar*) "or";
- break;
- case opcode_AND:
- *ppName = (uchar*) "and";
- break;
- case opcode_PLUS:
- *ppName = (uchar*) "add";
- break;
- case opcode_MINUS:
- *ppName = (uchar*) "sub";
- break;
- case opcode_TIMES:
- *ppName = (uchar*) "mul";
- break;
- case opcode_DIV:
- *ppName = (uchar*) "div";
- break;
- case opcode_MOD:
- *ppName = (uchar*) "mod";
- break;
- case opcode_NOT:
- *ppName = (uchar*) "not";
- break;
- case opcode_CMP_EQ:
- *ppName = (uchar*) "cmp_==";
- break;
- case opcode_CMP_NEQ:
- *ppName = (uchar*) "cmp_!=";
- break;
- case opcode_CMP_LT:
- *ppName = (uchar*) "cmp_<";
- break;
- case opcode_CMP_GT:
- *ppName = (uchar*) "cmp_>";
- break;
- case opcode_CMP_LTEQ:
- *ppName = (uchar*) "cmp_<=";
- break;
- case opcode_CMP_CONTAINS:
- *ppName = (uchar*) "contains";
- break;
- case opcode_CMP_STARTSWITH:
- *ppName = (uchar*) "startswith";
- break;
- case opcode_CMP_GTEQ:
- *ppName = (uchar*) "cmp_>=";
- break;
- case opcode_PUSHSYSVAR:
- *ppName = (uchar*) "push_sysvar";
- break;
- case opcode_PUSHMSGVAR:
- *ppName = (uchar*) "push_msgvar";
- break;
- case opcode_PUSHCONSTANT:
- *ppName = (uchar*) "push_const";
- break;
- case opcode_POP:
- *ppName = (uchar*) "pop";
- break;
- case opcode_UNARY_MINUS:
- *ppName = (uchar*) "unary_minus";
- break;
- case opcode_STRADD:
- *ppName = (uchar*) "strconcat";
- break;
- case opcode_FUNC_CALL:
- *ppName = (uchar*) "func_call";
- break;
- default:
- *ppName = (uchar*) "!invalid_opcode!";
- break;
- }
-
- RETiRet;
-}
-
-
-/* queryInterface function
- * rgerhards, 2008-02-21
- */
-BEGINobjQueryInterface(vmop)
-CODESTARTobjQueryInterface(vmop)
- if(pIf->ifVersion != vmopCURR_IF_VERSION) { /* check for current version, increment on each change */
- ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
- }
-
- /* ok, we have the right interface, so let's fill it
- * Please note that we may also do some backwards-compatibility
- * work here (if we can support an older interface version - that,
- * of course, also affects the "if" above).
- */
- pIf->Construct = vmopConstruct;
- pIf->ConstructFinalize = vmopConstructFinalize;
- pIf->Destruct = vmopDestruct;
- pIf->DebugPrint = vmopDebugPrint;
- pIf->SetFunc = vmopSetFunc;
- pIf->SetOpcode = vmopSetOpcode;
- pIf->SetVar = vmopSetVar;
- pIf->Opcode2Str = vmopOpcode2Str;
- pIf->Obj2Str = Obj2Str;
-finalize_it:
-ENDobjQueryInterface(vmop)
-
-
-/* Initialize the vmop class. Must be called as the very first method
- * before anything else is called inside this class.
- * rgerhards, 2008-02-19
- */
-BEGINObjClassInit(vmop, 1, OBJ_IS_CORE_MODULE) /* class, version */
- /* request objects we use */
- CHKiRet(objUse(var, CORE_COMPONENT));
- CHKiRet(objUse(vm, CORE_COMPONENT));
-
- OBJSetMethodHandler(objMethod_DEBUGPRINT, vmopDebugPrint);
- OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, vmopConstructFinalize);
-ENDObjClassInit(vmop)
-
-/* vi:set ai:
- */
diff --git a/runtime/vmop.h b/runtime/vmop.h
deleted file mode 100644
index c085a940..00000000
--- a/runtime/vmop.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/* The vmop object.
- *
- * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
- *
- * This file is part of rsyslog.
- *
- * This file is part of the rsyslog runtime library.
- *
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
- */
-#ifndef INCLUDED_VMOP_H
-#define INCLUDED_VMOP_H
-
-#include "ctok_token.h"
-#include "vmstk.h"
-#include "stringbuf.h"
-
-/* machine instructions types */
-typedef enum { /* do NOT start at 0 to detect uninitialized types after calloc() */
- opcode_INVALID = 0,
- /* for simplicity of debugging and reading dumps, we use the same IDs
- * that the tokenizer uses where this applicable.
- */
- opcode_OR = ctok_OR,
- opcode_AND = ctok_AND,
- opcode_STRADD= ctok_STRADD,
- opcode_PLUS = ctok_PLUS,
- opcode_MINUS = ctok_MINUS,
- opcode_TIMES = ctok_TIMES, /* "*" */
- opcode_DIV = ctok_DIV,
- opcode_MOD = ctok_MOD,
- opcode_NOT = ctok_NOT,
- opcode_CMP_EQ = ctok_CMP_EQ, /* all compare operations must be in a row */
- opcode_CMP_NEQ = ctok_CMP_NEQ,
- opcode_CMP_LT = ctok_CMP_LT,
- opcode_CMP_GT = ctok_CMP_GT,
- opcode_CMP_LTEQ = ctok_CMP_LTEQ,
- opcode_CMP_CONTAINS = ctok_CMP_CONTAINS,
- opcode_CMP_STARTSWITH = ctok_CMP_STARTSWITH,
- opcode_CMP_CONTAINSI = ctok_CMP_CONTAINSI,
- opcode_CMP_STARTSWITHI = ctok_CMP_STARTSWITHI,
- opcode_CMP_GTEQ = ctok_CMP_GTEQ, /* end compare operations */
- /* here we start our own codes */
- opcode_POP = 1000, /* requires var operand to receive result */
- opcode_PUSHSYSVAR = 1001, /* requires var operand */
- opcode_PUSHMSGVAR = 1002, /* requires var operand */
- opcode_PUSHCONSTANT = 1003, /* requires var operand */
- opcode_PUSHCEEVAR = 1004, /* requires var operand */
- opcode_UNARY_MINUS = 1010,
- opcode_FUNC_CALL = 1012,
- opcode_END_PROG = 2000
-} opcode_t;
-
-
-/* Additional doc, operation specific
-
- FUNC_CALL
- All parameter passing is via the stack. Parameters are placed onto the stack in reverse order,
- that means the last parameter is on top of the stack, the first at the bottom location.
- At the actual top of the stack is the number of parameters. This permits functions to be
- called with variable number of arguments. The function itself is responsible for poping
- the right number of parameters of the stack and complaining if the number is incorrect.
- On exit, a single return value must be pushed onto the stack. The FUNC_CALL operation
- is generic. Its pVar argument contains the function name string (TODO: very slow, make
- faster in later releases).
-
- Sample Function call: sampleFunc(p1, p2, p3) ; returns number 4711 (sample)
- Stacklayout on entry (order is top to bottom):
- 3
- p3
- p2
- p1
- ... other vars ...
-
- Stack on exit
- 4711
- ... other vars ...
-
- */
-
-
-/* the vmop object */
-typedef struct vmop_s {
- BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
- opcode_t opcode;
- union {
- var_t *pVar;
- prsf_t rsf; /* pointer to function for "call" instruction */
- } operand;
- struct vmop_s *pNext; /* next operation or NULL, if end of program (logically this belongs to vmprg) */
-} vmop_t;
-
-
-/* interfaces */
-BEGINinterface(vmop) /* name must also be changed in ENDinterface macro! */
- INTERFACEObjDebugPrint(vmop);
- rsRetVal (*Construct)(vmop_t **ppThis);
- rsRetVal (*ConstructFinalize)(vmop_t __attribute__((unused)) *pThis);
- rsRetVal (*Destruct)(vmop_t **ppThis);
- rsRetVal (*SetOpcode)(vmop_t *pThis, opcode_t opcode);
- rsRetVal (*SetVar)(vmop_t *pThis, var_t *pVar);
- rsRetVal (*Opcode2Str)(vmop_t *pThis, uchar **ppName);
- rsRetVal (*Obj2Str)(vmop_t *pThis, cstr_t *pstr);
- /* v2 */
- rsRetVal (*SetFunc)(vmop_t *pThis, cstr_t *pcsFuncName);
-ENDinterface(vmop)
-#define vmopCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */
-/* interface changes, v1 -> v2
- * added SetFuct after existing function pointers -- rgerhards, 2009-04-06
- */
-
-/* the remaining prototypes */
-PROTOTYPEObj(vmop);
-
-#endif /* #ifndef INCLUDED_VMOP_H */
diff --git a/runtime/vmprg.c b/runtime/vmprg.c
deleted file mode 100644
index 07757b98..00000000
--- a/runtime/vmprg.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/* vmprg.c - abstracts a program (bytecode) for the rsyslog virtual machine
- *
- * Module begun 2008-02-20 by Rainer Gerhards
- *
- * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH.
- *
- * This file is part of the rsyslog runtime library.
- *
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
- */
-
-#include "config.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include "rsyslog.h"
-#include "obj.h"
-#include "vmprg.h"
-#include "stringbuf.h"
-
-/* static data */
-DEFobjStaticHelpers
-DEFobjCurrIf(vmop)
-
-
-/* Standard-Constructor
- */
-BEGINobjConstruct(vmprg) /* be sure to specify the object type also in END macro! */
-ENDobjConstruct(vmprg)
-
-
-/* ConstructionFinalizer
- * rgerhards, 2008-01-09
- */
-static rsRetVal
-vmprgConstructFinalize(vmprg_t __attribute__((unused)) *pThis)
-{
- DEFiRet;
- ISOBJ_TYPE_assert(pThis, vmprg);
- RETiRet;
-}
-
-
-/* destructor for the vmprg object */
-BEGINobjDestruct(vmprg) /* be sure to specify the object type also in END and CODESTART macros! */
- vmop_t *pOp;
- vmop_t *pTmp;
-CODESTARTobjDestruct(vmprg)
- /* we need to destruct the program elements! */
- for(pOp = pThis->vmopRoot ; pOp != NULL ; ) {
- pTmp = pOp;
- pOp = pOp->pNext;
- vmop.Destruct(&pTmp);
- }
-ENDobjDestruct(vmprg)
-
-
-/* destructor for the vmop object */
-BEGINobjDebugPrint(vmprg) /* be sure to specify the object type also in END and CODESTART macros! */
- vmop_t *pOp;
-CODESTARTobjDebugPrint(vmprg)
- dbgoprint((obj_t*) pThis, "VM Program:\n");
- for(pOp = pThis->vmopRoot ; pOp != NULL ; pOp = pOp->pNext) {
- vmop.DebugPrint(pOp);
- }
-ENDobjDebugPrint(vmprg)
-
-
-/* This function is similar to DebugPrint, but does not send its output to
- * the debug log but instead to a caller-provided string. The idea here is that
- * we can use this string to get a textual representation of a bytecode program.
- * Among others, this is useful for creating testbenches, our first use case for
- * it. Here, it enables simple comparison of the resulting program to a
- * reference program by simple string compare.
- * Note that the caller must initialize the string object. We always add
- * data to it. So, it can be easily combined into a chain of methods
- * to generate the final string.
- * rgerhards, 2008-07-04
- */
-static rsRetVal
-Obj2Str(vmprg_t *pThis, cstr_t *pstrPrg)
-{
- uchar szAddr[12];
- vmop_t *pOp;
- int i;
- int lenAddr;
- DEFiRet;
-
- ISOBJ_TYPE_assert(pThis, vmprg);
- assert(pstrPrg != NULL);
- i = 0; /* "program counter" */
- for(pOp = pThis->vmopRoot ; pOp != NULL ; pOp = pOp->pNext) {
- lenAddr = snprintf((char*)szAddr, sizeof(szAddr), "%8.8d: ", i++);
- CHKiRet(rsCStrAppendStrWithLen(pstrPrg, szAddr, lenAddr));
- vmop.Obj2Str(pOp, pstrPrg);
- }
-
-finalize_it:
- RETiRet;
-}
-
-
-/* add an operation (instruction) to the end of the current program. This
- * function is expected to be called while creating the program, but never
- * again after this is done and it is being executed. Results are undefined if
- * it is called after execution.
- */
-static rsRetVal
-vmprgAddOperation(vmprg_t *pThis, vmop_t *pOp)
-{
- DEFiRet;
-
- ISOBJ_TYPE_assert(pThis, vmprg);
- ISOBJ_TYPE_assert(pOp, vmop);
-
- if(pThis->vmopRoot == NULL) {
- pThis->vmopRoot = pOp;
- } else {
- pThis->vmopLast->pNext = pOp;
- }
- pThis->vmopLast = pOp;
-
- RETiRet;
-}
-
-
-/* this is a shortcut for high-level callers. It creates a new vmop, sets its
- * parameters and adds it to the program - all in one big step. If there is no
- * var associated with this operation, the caller can simply supply NULL as
- * pVar.
- */
-static rsRetVal
-vmprgAddVarOperation(vmprg_t *pThis, opcode_t opcode, var_t *pVar)
-{
- DEFiRet;
- vmop_t *pOp;
-
- ISOBJ_TYPE_assert(pThis, vmprg);
-
- /* construct and fill vmop */
- CHKiRet(vmop.Construct(&pOp));
- CHKiRet(vmop.ConstructFinalize(pOp));
- CHKiRet(vmop.SetOpcode(pOp, opcode));
- if(pVar != NULL)
- CHKiRet(vmop.SetVar(pOp, pVar));
-
- /* and add it to the program */
- CHKiRet(vmprgAddOperation(pThis, pOp));
-
-finalize_it:
- RETiRet;
-}
-
-
-/* this is another shortcut for high-level callers. It is similar to vmprgAddVarOperation
- * but adds a call operation. Among others, this include a check if the function
- * is known.
- */
-static rsRetVal
-vmprgAddCallOperation(vmprg_t *pThis, cstr_t *pcsName)
-{
- DEFiRet;
- vmop_t *pOp;
-
- ISOBJ_TYPE_assert(pThis, vmprg);
-
- /* construct and fill vmop */
- CHKiRet(vmop.Construct(&pOp));
- CHKiRet(vmop.ConstructFinalize(pOp));
- CHKiRet(vmop.SetFunc(pOp, pcsName));
- CHKiRet(vmop.SetOpcode(pOp, opcode_FUNC_CALL));
-
- /* and add it to the program */
- CHKiRet(vmprgAddOperation(pThis, pOp));
-
-finalize_it:
- RETiRet;
-}
-
-
-/* queryInterface function
- * rgerhards, 2008-02-21
- */
-BEGINobjQueryInterface(vmprg)
-CODESTARTobjQueryInterface(vmprg)
- if(pIf->ifVersion != vmprgCURR_IF_VERSION) { /* check for current version, increment on each change */
- ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
- }
-
- /* ok, we have the right interface, so let's fill it
- * Please note that we may also do some backwards-compatibility
- * work here (if we can support an older interface version - that,
- * of course, also affects the "if" above).
- */
- pIf->Construct = vmprgConstruct;
- pIf->ConstructFinalize = vmprgConstructFinalize;
- pIf->Destruct = vmprgDestruct;
- pIf->DebugPrint = vmprgDebugPrint;
- pIf->Obj2Str = Obj2Str;
- pIf->AddOperation = vmprgAddOperation;
- pIf->AddVarOperation = vmprgAddVarOperation;
- pIf->AddCallOperation = vmprgAddCallOperation;
-finalize_it:
-ENDobjQueryInterface(vmprg)
-
-
-/* Initialize the vmprg class. Must be called as the very first method
- * before anything else is called inside this class.
- * rgerhards, 2008-02-19
- */
-BEGINObjClassInit(vmprg, 1, OBJ_IS_CORE_MODULE) /* class, version */
- /* request objects we use */
- CHKiRet(objUse(vmop, CORE_COMPONENT));
-
- /* set our own handlers */
- OBJSetMethodHandler(objMethod_DEBUGPRINT, vmprgDebugPrint);
- OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, vmprgConstructFinalize);
-ENDObjClassInit(vmprg)
-
-/* vi:set ai:
- */
diff --git a/runtime/vmprg.h b/runtime/vmprg.h
deleted file mode 100644
index 66f03913..00000000
--- a/runtime/vmprg.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* The vmprg object.
- *
- * The program is made up of vmop_t's, one after another. When we support
- * branching (or user-defined functions) at some time, well do this via
- * special branch opcodes. They will then contain the actual memory
- * address of a logical program entry that we shall branch to. Other than
- * that, all execution is serial - that is one opcode is executed after
- * the other. This class implements a logical program store, modelled
- * after real main memory. A linked list of opcodes is used to implement it.
- * In the future, we may use linked lists of array's to enhance performance,
- * but for the time being we have taken the simplistic approach (which also
- * reduces risk of bugs during initial development). The necessary pointers
- * for this are already implemented in vmop. Though this is not the 100%
- * correct place, we have opted this time in favor of performance, which
- * made them go there.
- *
- * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
- *
- * This file is part of the rsyslog runtime library.
- *
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
- */
-#ifndef INCLUDED_VMPRG_H
-#define INCLUDED_VMPRG_H
-
-#include "vmop.h"
-#include "stringbuf.h"
-
-/* the vmprg object */
-typedef struct vmprg_s {
- BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
- vmop_t *vmopRoot; /* start of program */
- vmop_t *vmopLast; /* last vmop of program (for adding new ones) */
-} vmprg_t;
-
-
-/* interfaces */
-BEGINinterface(vmprg) /* name must also be changed in ENDinterface macro! */
- INTERFACEObjDebugPrint(vmprg);
- rsRetVal (*Construct)(vmprg_t **ppThis);
- rsRetVal (*ConstructFinalize)(vmprg_t __attribute__((unused)) *pThis);
- rsRetVal (*Destruct)(vmprg_t **ppThis);
- rsRetVal (*AddOperation)(vmprg_t *pThis, vmop_t *pOp);
- rsRetVal (*AddVarOperation)(vmprg_t *pThis, opcode_t opcode, var_t *pVar);
- rsRetVal (*Obj2Str)(vmprg_t *pThis, cstr_t *pstr);
- /* v2 (4.1.7) */
- rsRetVal (*AddCallOperation)(vmprg_t *pThis, cstr_t *pVar); /* added 2009-04-06 */
-ENDinterface(vmprg)
-#define vmprgCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */
-
-
-/* prototypes */
-PROTOTYPEObj(vmprg);
-
-#endif /* #ifndef INCLUDED_VMPRG_H */
diff --git a/runtime/vmstk.c b/runtime/vmstk.c
deleted file mode 100644
index 1ee3d485..00000000
--- a/runtime/vmstk.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/* vmstk.c - the arithmetic stack of a virtual machine.
- *
- * Module begun 2008-02-21 by Rainer Gerhards
- *
- * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
- *
- * This file is part of the rsyslog runtime library.
- *
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
- */
-
-#include "config.h"
-#include <stdlib.h>
-#include <assert.h>
-
-#include "rsyslog.h"
-#include "obj.h"
-#include "vmstk.h"
-
-/* static data */
-DEFobjStaticHelpers
-DEFobjCurrIf(var)
-
-
-/* Standard-Constructor
- */
-BEGINobjConstruct(vmstk) /* be sure to specify the object type also in END macro! */
-ENDobjConstruct(vmstk)
-
-
-/* ConstructionFinalizer
- * rgerhards, 2008-01-09
- */
-static rsRetVal
-vmstkConstructFinalize(vmstk_t __attribute__((unused)) *pThis)
-{
- DEFiRet;
- ISOBJ_TYPE_assert(pThis, vmstk);
- RETiRet;
-}
-
-
-/* destructor for the vmstk object */
-BEGINobjDestruct(vmstk) /* be sure to specify the object type also in END and CODESTART macros! */
-CODESTARTobjDestruct(vmstk)
-ENDobjDestruct(vmstk)
-
-
-/* debugprint for the vmstk object */
-BEGINobjDebugPrint(vmstk) /* be sure to specify the object type also in END and CODESTART macros! */
-CODESTARTobjDebugPrint(vmstk)
- dbgoprint((obj_t*) pThis, "stack contents:\n");
-ENDobjDebugPrint(vmstk)
-
-
-/* push a value on the stack. The provided pVar is now owned
- * by the stack. If the user intends to continue use it, it
- * must be duplicated.
- */
-static rsRetVal
-push(vmstk_t *pThis, var_t *pVar)
-{
- DEFiRet;
-
- ISOBJ_TYPE_assert(pThis, vmstk);
- ISOBJ_TYPE_assert(pVar, var);
-
- if(pThis->iStkPtr >= VMSTK_SIZE)
- ABORT_FINALIZE(RS_RET_OUT_OF_STACKSPACE);
-
- pThis->vStk[pThis->iStkPtr++] = pVar;
-
-finalize_it:
- RETiRet;
-}
-
-
-/* pop a value from the stack
- * IMPORTANT: the stack pointer always points to the NEXT FREE entry. So in
- * order to pop, we must access the element one below the stack pointer.
- * The user is responsible for destructing the ppVar returned.
- */
-static rsRetVal
-pop(vmstk_t *pThis, var_t **ppVar)
-{
- DEFiRet;
-
- ISOBJ_TYPE_assert(pThis, vmstk);
- ASSERT(ppVar != NULL);
-
- if(pThis->iStkPtr == 0)
- ABORT_FINALIZE(RS_RET_STACK_EMPTY);
-
- *ppVar = pThis->vStk[--pThis->iStkPtr];
-
-finalize_it:
- RETiRet;
-}
-
-
-/* pop a boolean value from the stack
- * The user is responsible for destructing the ppVar returned.
- */
-static rsRetVal
-popBool(vmstk_t *pThis, var_t **ppVar)
-{
- DEFiRet;
-
- /* assertions are done in pop(), we do not duplicate here */
- CHKiRet(pop(pThis, ppVar));
- CHKiRet(var.ConvToBool(*ppVar));
-
-finalize_it:
- RETiRet;
-}
-
-
-/* pop a number value from the stack
- * The user is responsible for destructing the ppVar returned.
- */
-static rsRetVal
-popNumber(vmstk_t *pThis, var_t **ppVar)
-{
- DEFiRet;
-
- /* assertions are done in pop(), we do not duplicate here */
- CHKiRet(pop(pThis, ppVar));
- CHKiRet(var.ConvToNumber(*ppVar));
-
-finalize_it:
- RETiRet;
-}
-
-
-/* pop a number value from the stack
- * The user is responsible for destructing the ppVar returned.
- */
-static rsRetVal
-popString(vmstk_t *pThis, var_t **ppVar)
-{
- DEFiRet;
-
- /* assertions are done in pop(), we do not duplicate here */
- CHKiRet(pop(pThis, ppVar));
- CHKiRet(var.ConvToString(*ppVar));
-
-finalize_it:
- RETiRet;
-}
-
-
-/* pop two variables for a common operation, e.g. a compare. When this
- * functions returns, both variables have the same type, but the type
- * is not set to anything specific.
- * The user is responsible for destructing the ppVar's returned.
- * A quick note on the name: it means pop 2 variable for a common
- * opertion - just in case you wonder (I don't really like the name,
- * but I didn't come up with a better one...).
- * rgerhards, 2008-02-25
- */
-static rsRetVal
-pop2CommOp(vmstk_t *pThis, var_t **ppVar1, var_t **ppVar2)
-{
- DEFiRet;
-
- /* assertions are done in pop(), we do not duplicate here */
- /* operand two must be popped first, because it is at the top of stack */
- CHKiRet(pop(pThis, ppVar2));
- CHKiRet(pop(pThis, ppVar1));
- CHKiRet(var.ConvForOperation(*ppVar1, *ppVar2));
-
-finalize_it:
- RETiRet;
-}
-
-
-/* queryInterface function
- * rgerhards, 2008-02-21
- */
-BEGINobjQueryInterface(vmstk)
-CODESTARTobjQueryInterface(vmstk)
- if(pIf->ifVersion != vmstkCURR_IF_VERSION) { /* check for current version, increment on each change */
- ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
- }
-
- /* ok, we have the right interface, so let's fill it
- * Please note that we may also do some backwards-compatibility
- * work here (if we can support an older interface version - that,
- * of course, also affects the "if" above).
- */
- pIf->Construct = vmstkConstruct;
- pIf->ConstructFinalize = vmstkConstructFinalize;
- pIf->Destruct = vmstkDestruct;
- pIf->DebugPrint = vmstkDebugPrint;
- pIf->Push = push;
- pIf->Pop = pop;
- pIf->PopBool = popBool;
- pIf->PopNumber = popNumber;
- pIf->PopString = popString;
- pIf->Pop2CommOp = pop2CommOp;
-
-finalize_it:
-ENDobjQueryInterface(vmstk)
-
-
-/* Initialize the vmstk class. Must be called as the very first method
- * before anything else is called inside this class.
- * rgerhards, 2008-02-19
- */
-BEGINObjClassInit(vmstk, 1, OBJ_IS_CORE_MODULE) /* class, version */
- /* request objects we use */
- CHKiRet(objUse(var, CORE_COMPONENT));
-
- /* set our own handlers */
- OBJSetMethodHandler(objMethod_DEBUGPRINT, vmstkDebugPrint);
- OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, vmstkConstructFinalize);
-ENDObjClassInit(vmstk)
-
-/* vi:set ai:
- */
diff --git a/runtime/vmstk.h b/runtime/vmstk.h
deleted file mode 100644
index 06657cf4..00000000
--- a/runtime/vmstk.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* The vmstk object.
- *
- * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
- *
- * This file is part of the rsyslog runtime library.
- *
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
- */
-#ifndef INCLUDED_VMSTK_H
-#define INCLUDED_VMSTK_H
-
-/* The max size of the stack - TODO: make configurable */
-#define VMSTK_SIZE 256
-
-/* the vmstk object */
-struct vmstk_s {
- BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
- var_t *vStk[VMSTK_SIZE];/* the actual stack */
- int iStkPtr; /* stack pointer, points to next free location, grows from 0 --> topend */
-};
-
-
-/* interfaces */
-BEGINinterface(vmstk) /* name must also be changed in ENDinterface macro! */
- INTERFACEObjDebugPrint(vmstk);
- rsRetVal (*Construct)(vmstk_t **ppThis);
- rsRetVal (*ConstructFinalize)(vmstk_t __attribute__((unused)) *pThis);
- rsRetVal (*Destruct)(vmstk_t **ppThis);
- rsRetVal (*Push)(vmstk_t *pThis, var_t *pVar);
- rsRetVal (*Pop)(vmstk_t *pThis, var_t **ppVar);
- rsRetVal (*PopBool)(vmstk_t *pThis, var_t **ppVar);
- rsRetVal (*PopNumber)(vmstk_t *pThis, var_t **ppVar);
- rsRetVal (*PopString)(vmstk_t *pThis, var_t **ppVar);
- rsRetVal (*Pop2CommOp)(vmstk_t *pThis, var_t **ppVar1, var_t **ppVar2);
-ENDinterface(vmstk)
-#define vmstkCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
-
-
-/* prototypes */
-PROTOTYPEObj(vmstk);
-
-#endif /* #ifndef INCLUDED_VMSTK_H */