Currently disabled by default.
silly
core/hooks.c
lib/sstring.{c,h}
+y.tab.{c,h}
+lex.yy.c
BUILDID @shell@ (hg id || echo "unknown") | sed -e "s/+ /-/;s/ /-/" @shellend@
@endif@
-.SUFFIXES: .so
+.SUFFIXES: .so .y .l
.o.so:
@-ldline-@ $(LDFLAGS)
+.y.c: ;
+
+.l.c: ;
+
CFLAGS+=-Wall -g -finline-functions -funroll-loops -std=c99 -I./ -DBUILDID=$(BUILDID)
CFLAGS+=-fPIC -export-dynamic
@include@ @includel@../build.mk@includel@
-CFLAGS+=$(INCPCRE)
+CFLAGS+=$(INCPCRE) -DYY_NO_UNPUT
LDFLAGS+=$(LIBPCRE)
.PHONY: all
all: newsearch.so
-newsearch.so: newsearch.o formats.o ns-not.o ns-and.o ns-or.o ns-eq.o ns-match.o ns-hostmask.o ns-realname.o ns-modes.o ns-nick.o ns-ident.o ns-regex.o ns-host.o ns-channel.o ns-lt.o ns-gt.o ns-timestamp.o ns-country.o ns-authname.o ns-ip.o ns-kill.o ns-gline.o ns-exists.o ns-services.o ns-size.o ns-name.o ns-topic.o ns-oppct.o ns-hostpct.o ns-authedpct.o ns-length.o ns-kick.o ns-authts.o ns-channels.o ns-server.o ns-authid.o ns-notice.o newsearch_ast.o ns-any.o ns-channeliter.o ns-var.o ns-all.o ns-cumodes.o ns-cidr.o
+newsearch.so: newsearch.o formats.o y.tab.o lex.yy.o parser.o ns-not.o ns-and.o ns-or.o ns-eq.o ns-match.o ns-hostmask.o ns-realname.o ns-modes.o ns-nick.o ns-ident.o ns-regex.o ns-host.o ns-channel.o ns-lt.o ns-gt.o ns-timestamp.o ns-country.o ns-authname.o ns-ip.o ns-kill.o ns-gline.o ns-exists.o ns-services.o ns-size.o ns-name.o ns-topic.o ns-oppct.o ns-hostpct.o ns-authedpct.o ns-length.o ns-kick.o ns-authts.o ns-channels.o ns-server.o ns-authid.o ns-notice.o newsearch_ast.o ns-any.o ns-channeliter.o ns-var.o ns-all.o ns-cumodes.o ns-cidr.o
+
+y.tab.c y.tab.h: newsearch.y
+ ${YACC} -d newsearch.y
+
+lex.yy.c: newsearch.l y.tab.h
+ ${LEX} newsearch.l
+
+clean:
+ rm -f *.o *.so y.tab.c y.tab.h lex.yy.c
#include "../lib/strlfunc.h"
#include "../lib/array.h"
#include "newsearch.h"
+#include "parser.h"
MODULE_VERSION("");
int do_nicksearch_real(replyFunc reply, wallFunc wall, void *source, int cargc, char **cargv) {
nick *sender = source;
- struct searchNode *search;
int limit=500;
int arg=0;
NickDisplayFunc display=defaultnickfn;
- searchCtx ctx;
int ret;
+#ifndef NEWSEARCH_NEWPARSER
+ searchCtx ctx;
+ struct searchNode *search;
+#else
+ parsertree *tree;
+#endif
if (cargc<1) {
reply( sender, "Usage: [flags] <criteria>");
rejoinline(cargv[arg],cargc-arg);
}
+#ifndef NEWSEARCH_NEWPARSER
newsearch_ctxinit(&ctx, search_parse, reply, wall, NULL, reg_nicksearch, sender, display, limit);
-
if (!(search = ctx.parser(&ctx, cargv[arg]))) {
reply(sender,"Parse error: %s",parseError);
return CMD_ERROR;
nicksearch_exe(search, &ctx);
(search->free)(&ctx, search);
+#else
+ tree = parse_string(reg_nicksearch, cargv[arg]);
+ if(!tree) {
+ reply(sender,"Parse error: %s", parseStrError);
+ return CMD_ERROR;
+ }
+
+ ast_nicksearch(tree->root, reply, sender, wall, display, NULL, NULL, limit);
+
+ parse_free(tree);
+#endif
return CMD_OK;
}
int do_chansearch_real(replyFunc reply, wallFunc wall, void *source, int cargc, char **cargv) {
nick *sender = source;
- struct searchNode *search;
int limit=500;
int arg=0;
ChanDisplayFunc display=defaultchanfn;
- searchCtx ctx;
int ret;
+#ifndef NEWSEARCH_NEWPARSER
+ struct searchNode *search;
+ searchCtx ctx;
+#else
+ parsertree *tree;
+#endif
if (cargc<1) {
reply( sender, "Usage: [flags] <criteria>");
rejoinline(cargv[arg],cargc-arg);
}
+#ifndef NEWSEARCH_NEWPARSER
newsearch_ctxinit(&ctx, search_parse, reply, wall, NULL, reg_chansearch, sender, display, limit);
if (!(search = ctx.parser(&ctx, cargv[arg]))) {
reply(sender,"Parse error: %s",parseError);
chansearch_exe(search, &ctx);
(search->free)(&ctx, search);
+#else
+ tree = parse_string(reg_chansearch, cargv[arg]);
+ if(!tree) {
+ reply(sender,"Parse error: %s", parseStrError);
+ return CMD_ERROR;
+ }
+
+ ast_chansearch(tree->root, reply, sender, wall, display, NULL, NULL, limit);
+
+ parse_free(tree);
+#endif
return CMD_OK;
}
int do_usersearch_real(replyFunc reply, wallFunc wall, void *source, int cargc, char **cargv) {
nick *sender = source;
- struct searchNode *search;
int limit=500;
int arg=0;
UserDisplayFunc display=defaultuserfn;
- searchCtx ctx;
int ret;
+#ifndef NEWSEARCH_NEWPARSER
+ struct searchNode *search;
+ searchCtx ctx;
+#else
+ parsertree *tree;
+#endif
if (cargc<1) {
reply( sender, "Usage: [flags] <criteria>");
rejoinline(cargv[arg],cargc-arg);
}
+#ifndef NEWSEARCH_NEWPARSER
newsearch_ctxinit(&ctx, search_parse, reply, wall, NULL, reg_usersearch, sender, display, limit);
if (!(search = ctx.parser(&ctx, cargv[arg]))) {
usersearch_exe(search, &ctx);
(search->free)(&ctx, search);
+#else
+ tree = parse_string(reg_usersearch, cargv[arg]);
+ if(!tree) {
+ reply(sender,"Parse error: %s", parseStrError);
+ return CMD_ERROR;
+ }
+
+ ast_usersearch(tree->root, reply, sender, wall, display, NULL, NULL, limit);
+
+ parse_free(tree);
+#endif
return CMD_OK;
}
return 1;
}
-/* search_parse:
- * Given an input string, return a searchNode.
- */
-
struct searchNode *search_parse(searchCtx *ctx, char *cinput) {
/* OK, we need to split the input into chunks on spaces and brackets.. */
char *argvector[100];
--- /dev/null
+%option noyywrap
+
+%{
+#include "y.tab.h"
+#include <string.h>
+
+#define YYSTYPE char *
+extern YYSTYPE yylval;
+
+#include <stdlib.h>
+#include "../lib/stringbuf.h"
+
+#define MAX_STR_CONST 512
+%}
+
+digit [0-9]
+letter [a-zA-Z]
+
+%x str
+%%
+
+ char bufdata[MAX_STR_CONST];
+ StringBuf buf;
+
+\" {
+ sbinit(&buf, bufdata, sizeof(bufdata));
+ BEGIN(str);
+ }
+
+<str>{
+ \" {
+ BEGIN(INITIAL);
+ sbterminate(&buf);
+ yylval = strdup(bufdata);
+ return STRING;
+ }
+ \\\\ { sbaddchar(&buf, '\\'); }
+ \\\" { sbaddchar(&buf, '"'); }
+ [^\\] { sbaddchar(&buf, *yytext); }
+}
+
+"(" { return LPAREN; }
+")" { return RPAREN; }
+[ \t]+ { return WHITESPACE; }
+{letter}+ {
+ yylval = strdup(yytext);
+ return IDENTIFIER;
+ }
+
+[\n\r] /* ignore */;
+
+<<EOF>> {
+ BEGIN(INITIAL);
+ yyterminate();
+ }
+%%
--- /dev/null
+%{
+#include <stdio.h>
+#include <string.h>
+#include "../lib/stringbuf.h"
+#include "newsearch.h"
+#include "parser.h"
+
+#define YYSTYPE char *
+
+int yylex(void);
+extern char *parseStrError;
+int position;
+
+#define MAXSTACKSIZE 50
+
+typedef struct parserlist {
+ searchASTExpr expr;
+ struct parserlist *next;
+} parserlist;
+
+void yyerror(const char *str) {
+ parseStrError = (char *)str;
+}
+
+static int stackpos;
+static parserlist *stack[MAXSTACKSIZE];
+static int stackcount[MAXSTACKSIZE];
+static fnFinder functionfinder;
+static void *fnfarg;
+static parsertree **presult, sresult;
+
+void resetparser(fnFinder fnf, void *arg, parsertree **result) {
+ presult = result;
+
+ sresult.exprlist = NULL;
+ sresult.strlist = NULL;
+ sresult.finished = 0;
+
+ functionfinder = fnf;
+ fnfarg = arg;
+
+ stackpos = 0;
+}
+
+%}
+
+%token LPAREN RPAREN WHITESPACE IDENTIFIER STRING
+
+%%
+invocation: LPAREN function argumentlist RPAREN
+ {
+ char *str = $2;
+ int i, count;
+ searchASTExpr *ap, *root;
+ parserlist *pp, *npp;
+ expressionlist *xl;
+ parseFunc pfn;
+
+ stackpos--;
+ count = stackcount[stackpos];
+
+ pfn = functionfinder(str, fnfarg);
+ if(!pfn) {
+ parse_free(&sresult);
+ YYERROR;
+ }
+ /* if we're at the top of the stack we're the root of the tree */
+ if(stackpos != 0) {
+ /*
+ * we store this function containing its children in the stack list
+ * as there might be functions or other stuff after it, such as:
+ * (fn (fn2) moo moo)
+ */
+ parserlist *rootp = malloc(sizeof(searchASTExpr) + sizeof(parserlist));
+ root = &rootp->expr;
+
+ stackcount[stackpos-1]++;
+ rootp->next = stack[stackpos-1];
+ stack[stackpos-1] = rootp;
+ } else {
+ /* need space for the final result and real root */
+ *presult = malloc(sizeof(parsertree) + sizeof(searchASTExpr));
+
+ memcpy(*presult, &sresult, sizeof(parsertree));
+ (*presult)->finished = 1;
+
+ root = (*presult)->root;
+ }
+
+ xl = malloc(sizeof(expressionlist) + sizeof(searchASTExpr) * count);
+ xl->next = (*presult)->exprlist;
+ (*presult)->exprlist = xl;
+
+ ap = xl->expr;
+ for(i=count-1,pp=stack[stackpos];i>=0;i--,pp=npp) {
+ npp = pp->next;
+ memcpy(&ap[i], &pp->expr, sizeof(searchASTExpr));
+ free(pp);
+ }
+ *root = NSASTManualNode(pfn, count, ap);
+
+ free(str);
+ }
+
+function: IDENTIFIER
+ {
+ if(stackpos >= MAXSTACKSIZE - 1)
+ YYERROR;
+
+ stackcount[stackpos] = 0;
+ stack[stackpos] = NULL;
+
+ stackpos++;
+ };
+
+argumentlist: /* empty */ | WHITESPACE argument argumentlist;
+
+argument:
+ invocation | literal
+ {
+ char *str = $1;
+ parserlist *l = malloc(sizeof(parserlist) + sizeof(stringlist));
+ stringlist *sl;
+
+ l->expr = NSASTLiteral(str);
+ l->next = stack[stackpos - 1];
+ stack[stackpos - 1] = l;
+ stackcount[stackpos - 1]++;
+
+ /* HACK */
+ sl = (stringlist *)(l + 1);
+
+ sl->next = (*presult)->strlist;
+ (*presult)->strlist = sl;
+ }
+ ;
+
+literal: IDENTIFIER | STRING;
\ No newline at end of file
--- /dev/null
+#include <stdio.h>
+#include "newsearch.h"
+#include "parser.h"
+
+struct yy_buffer_state;
+
+struct yy_buffer_state *yy_scan_string(const char *);
+void yy_delete_buffer(struct yy_buffer_state *);
+void yy_flush_buffer(struct yy_buffer_state *);
+
+int yyparse(void);
+char *parseStrError;
+
+parseFunc fnfinder(char *name, void *arg) {
+ searchCmd *cmdtree = arg;
+ struct Command *cmd;
+ parseFunc ret;
+
+ if (!(cmd=findcommandintree(cmdtree->searchtree, name, 1))) {
+ parseError = "Unknown command (for valid command list, see help <searchcmd>)";
+ return NULL;
+ }
+ ret = (parseFunc)cmd->handler;
+ /* TODO */
+
+ /*
+ if (!controlpermitted(ret->level, ret->sender)) {
+ parseError = "Access denied (for valid command list, see help <searchcmd>)";
+ return NULL;
+ }
+ return ((parseFunc)cmd->handler)(ctx, j, argvector+1);
+ }*/
+
+ return ret;
+}
+
+parsertree *parse_string(searchCmd *cmd, const char *str) {
+ int ret;
+ struct yy_buffer_state *b;
+ parsertree *pt;
+
+ b = yy_scan_string(str);
+ if(!b) {
+ parseStrError = "string buffer creation error";
+ return NULL;
+ }
+
+ resetparser(fnfinder, cmd, &pt);
+ ret = yyparse();
+
+ yy_flush_buffer(b);
+ yy_delete_buffer(b);
+
+ if(ret) /* error occured, parseStrError has it */
+ return NULL;
+
+ parseStrError = "not yet implemented";
+ return pt;
+}
+
+void parse_free(parsertree *pt) {
+ stringlist *sl, *nsl;
+ expressionlist *xl, *nxl;
+
+ for(sl=pt->strlist;sl;sl=nsl) {
+ nsl = sl->next;
+ free(sl);
+ }
+
+ for(xl=pt->exprlist;xl;xl=nxl) {
+ nxl = xl->next;
+ free(xl);
+ }
+
+ if(pt->finished)
+ free(pt);
+}
--- /dev/null
+#ifndef NEWSEARCH_PARSER_H
+#define NEWSEARCH_PARSER_H
+
+#include "newsearch.h"
+
+typedef struct stringlist {
+ struct stringlist *next;
+ char data[];
+} stringlist;
+
+typedef struct expressionlist {
+ struct expressionlist *next;
+ searchASTExpr expr[];
+} expressionlist;
+
+typedef struct parsertree {
+ expressionlist *exprlist;
+ stringlist *strlist;
+ int finished;
+ searchASTExpr root[];
+} parsertree;
+
+typedef parseFunc (*fnFinder)(char *, void *);
+
+parsertree *parse_string(searchCmd *, const char *);
+void parse_free(parsertree *);
+
+void resetparser(fnFinder fnf, void *arg, parsertree **result);
+
+extern char *parseStrError;
+
+#endif