/*
- * ircd_parser.y: A yacc/bison parser for ircd config files.
+ * ircd_lexer.l: A lexical scanner for ircd config files.
* This is part of ircu, an Internet Relay Chat server.
* The contents of this file are Copyright(C) 2001 by Andrew Miller, the
* ircd-hybrid team and the ircu team.
%{
#include <unistd.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "config.h"
#include "ircd.h"
+#include "ircd_alloc.h"
+#include "ircd_string.h"
+#include "s_debug.h"
#include "y.tab.h"
extern int lineno;
+static struct lexer_token {
+ const char *string;
+ int value;
+} tokens[] = {
+#define TOKEN(NAME) { #NAME, NAME }
+ TOKEN(ADMIN),
+ TOKEN(GENERAL),
+ TOKEN(LOCATION),
+ TOKEN(CONTACT),
+ TOKEN(CLASS),
+ TOKEN(PINGFREQ),
+ TOKEN(CONNECT),
+ TOKEN(CONNECTFREQ),
+ TOKEN(MAXLINKS),
+ TOKEN(MAXHOPS),
+ TOKEN(SENDQ),
+ TOKEN(NAME),
+ TOKEN(HOST),
+ TOKEN(IP),
+ TOKEN(USERNAME),
+ TOKEN(PASS),
+ TOKEN(SECONDS),
+ TOKEN(MINUTES),
+ TOKEN(HOURS),
+ TOKEN(DAYS),
+ TOKEN(WEEKS),
+ TOKEN(MONTHS),
+ TOKEN(YEARS),
+ TOKEN(DECADES),
+ TOKEN(BYTES),
+ TOKEN(KBYTES),
+ TOKEN(MBYTES),
+ TOKEN(GBYTES),
+ TOKEN(TBYTES),
+ TOKEN(PORT),
+ TOKEN(SERVER),
+ TOKEN(YES),
+ TOKEN(NO),
+ TOKEN(HUB),
+ TOKEN(LEAF),
+ TOKEN(UWORLD),
+ TOKEN(OPER),
+ TOKEN(LOCAL),
+ TOKEN(VHOST),
+ TOKEN(MASK),
+ TOKEN(HIDDEN),
+ TOKEN(MOTD),
+ TOKEN(NUMERIC),
+ TOKEN(NICK),
+ TOKEN(JUPE),
+ TOKEN(DESCRIPTION),
+ TOKEN(CLIENT),
+ TOKEN(REAL),
+ TOKEN(REASON),
+ TOKEN(RULE),
+ TOKEN(ALL),
+ TOKEN(CRULE),
+ TOKEN(KILL),
+ TOKEN(QUARANTINE),
+ TOKEN(IAUTH),
+ TOKEN(TIMEOUT),
+ TOKEN(FEATURES),
+ TOKEN(CHANNEL),
+ TOKEN(PSEUDO),
+ TOKEN(PREPEND),
+ TOKEN(USERMODE),
+ TOKEN(FAST),
+ TOKEN(AUTOCONNECT),
+ TOKEN(PROGRAM),
+ TOKEN(DNS),
+#undef TOKEN
+ { "administrator", ADMIN },
+ { "apass_opmode", TPRIV_APASS_OPMODE },
+ { "auto", AUTOCONNECT },
+ { "b", BYTES },
+ { "badchan", TPRIV_BADCHAN },
+ { "chan_limit", TPRIV_CHAN_LIMIT },
+ { "deop_lchan", TPRIV_DEOP_LCHAN },
+ { "die", TPRIV_DIE },
+ { "display", TPRIV_DISPLAY },
+ { "file", TFILE },
+ { "force_local_opmode", TPRIV_FORCE_LOCAL_OPMODE },
+ { "force_opmode", TPRIV_FORCE_OPMODE },
+ { "gb", GBYTES },
+ { "gigabytes", GBYTES },
+ { "gline", TPRIV_GLINE },
+ { "ipv4", TOK_IPV4 },
+ { "ipv6", TOK_IPV6 },
+ { "kb", KBYTES },
+ { "kilobytes", KBYTES },
+ { "list_chan", TPRIV_LIST_CHAN },
+ { "local_badchan", TPRIV_LOCAL_BADCHAN },
+ { "local_gline", TPRIV_LOCAL_GLINE },
+ { "local_jupe", TPRIV_LOCAL_JUPE },
+ { "local_kill", TPRIV_LOCAL_KILL },
+ { "local_opmode", TPRIV_LOCAL_OPMODE },
+ { "mb", MBYTES },
+ { "megabytes", MBYTES },
+ { "mode_lchan", TPRIV_MODE_LCHAN },
+ { "operator", OPER },
+ { "opmode", TPRIV_OPMODE },
+ { "password", PASS },
+ { "propagate", TPRIV_PROPAGATE },
+ { "realname", REAL },
+ { "rehash", TPRIV_REHASH },
+ { "restart", TPRIV_RESTART },
+ { "see_chan", TPRIV_SEE_CHAN },
+ { "see_opers", TPRIV_SEE_OPERS },
+ { "set", TPRIV_SET },
+ { "show_all_invis", TPRIV_SHOW_ALL_INVIS },
+ { "show_invis", TPRIV_SHOW_INVIS },
+ { "tb", TBYTES },
+ { "terabytes", TBYTES },
+ { "unlimit_query", TPRIV_UNLIMIT_QUERY },
+ { "walk_lchan", TPRIV_WALK_LCHAN },
+ { "wide_gline", TPRIV_WIDE_GLINE },
+ { "whox", TPRIV_WHOX },
+ { NULL, 0 }
+};
+static int ntokens;
+
+static int
+token_compare(const void *pa, const void *pb)
+{
+ const struct lexer_token *ta = pa;
+ const struct lexer_token *tb = pb;
+ unsigned int ii = 0;
+ int res;
+ while (ta->string[ii] && (ToLower(ta->string[ii]) == ToLower(tb->string[ii])))
+ ii++;
+ res = ToLower(tb->string[ii]) - ToLower(ta->string[ii]);
+ return res;
+}
+
+static void
+init_ntokens(void)
+{
+ for (ntokens = 0; tokens[ntokens].string; ++ntokens) ;
+ qsort(tokens, ntokens, sizeof(tokens[0]), token_compare);
+}
+
+static int
+find_token(char *token)
+{
+ struct lexer_token *tok;
+ if (!ntokens)
+ init_ntokens();
+ tok = bsearch(&token, tokens, ntokens, sizeof(tokens[0]), token_compare);
+ return tok ? tok->value : 0;
+}
+
void
init_lexer(void)
{
yyin = fopen(configfile, "r");
if (yyin == NULL)
- yy_fatal_error("Could not open the configuration file.");
+ {
+#ifdef YY_FATAL_ERROR
+ YY_FATAL_ERROR("Could not open the configuration file.");
+#else
+ fprintf(stderr, "Could not open the configuration file.");
+#endif
+ }
+#ifdef YY_NEW_FILE
YY_NEW_FILE;
+#endif
lineno = 1;
}
%}
-%option noyywrap
-%option case-insensitive
-%option nounput
-
WHITE [ \t\r]+
SHCOMMENT #[^\n]*
QSTRING \"[^"\n]+[\"\n]
%%
-{QSTRING} {yytext[yyleng-1] = 0; yylval.text = yytext+1; return QSTRING;}
+{QSTRING} {yytext[yyleng-1] = 0; DupString(yylval.text, yytext+1); return QSTRING;}
{NUMBER} {yylval.num = strtoul(yytext, NULL, 10); return NUMBER;}
{WHITE} ;
{SHCOMMENT} ;
-admin return ADMIN;
-administrator return ADMIN;
-general return GENERAL;
-location return LOCATION;
-contact return CONTACT;
-connect return CONNECT;
-class return CLASS;
-pingfreq return PINGFREQ;
-connectfreq return CONNECTFREQ;
-maxlinks return MAXLINKS;
-sendq return SENDQ;
-name return NAME;
-host return HOST;
-password return PASS;
-pass return PASS;
-seconds return SECONDS;
-minutes return MINUTES;
-hours return HOURS;
-days return DAYS;
-weeks return WEEKS;
-months return MONTHS;
-years return YEARS;
-decades return DECADES;
-bytes return BYTES;
-b return BYTES;
-kbytes return KBYTES;
-kilobytes return KBYTES;
-kb return KBYTES;
-mbytes return MBYTES;
-megabytes return MBYTES;
-mb return MBYTES;
-gbytes return GBYTES;
-gigabytes return GBYTES;
-gb return GBYTES;
-tbytes return TBYTES;
-terabytes return TBYTES;
-tb return TBYTES;
-port return PORT;
-server return SERVER;
-yes return YES;
-no return NO;
-hub return HUB;
-leaf return LEAF;
-uworld return UWORLD;
-operator return OPER;
-oper return OPER;
-local return LOCAL;
-vhost return VHOST;
-mask return MASK;
-hidden return HIDDEN;
-motd return MOTD;
-numeric return NUMERIC;
-nick return NICK;
-jupe return JUPE;
-description return DESCRIPTION;
-client return CLIENT;
-real return REAL;
-realname return REAL;
-reason return REASON;
-file return TFILE;
-rule return RULE;
-all return ALL;
-ip return IP;
-crule return CRULE;
-kill return KILL;
-quarantine return QUARANTINE;
-iauth return IAUTH;
-timeout return TIMEOUT;
-features return FEATURES;
-channel return CHANNEL;
-chan_limit return TPRIV_CHAN_LIMIT;
-mode_lchan return TPRIV_MODE_LCHAN;
-deop_lchan return TPRIV_DEOP_LCHAN;
-walk_lchan return TPRIV_WALK_LCHAN;
-local_kill return TPRIV_LOCAL_KILL;
-rehash return TPRIV_REHASH;
-restart return TPRIV_RESTART;
-die return TPRIV_DIE;
-gline return TPRIV_GLINE;
-local_gline return TPRIV_LOCAL_GLINE;
-local_jupe return TPRIV_LOCAL_JUPE;
-opmode return TPRIV_OPMODE;
-set return TPRIV_SET;
-whox return TPRIV_WHOX;
-badchan return TPRIV_BADCHAN;
-local_badchan return TPRIV_LOCAL_BADCHAN;
-see_chan return TPRIV_SEE_CHAN;
-show_invis return TPRIV_SHOW_INVIS;
-show_all_invis return TPRIV_SHOW_ALL_INVIS;
-propagate return TPRIV_PROPAGATE;
-unlimit_query return TPRIV_UNLIMIT_QUERY;
-display return TPRIV_DISPLAY;
-see_opers return TPRIV_SEE_OPERS;
-wide_gline return TPRIV_WIDE_GLINE;
-force_opmode return TPRIV_FORCE_OPMODE;
-force_local_opmode return TPRIV_FORCE_LOCAL_OPMODE;
-pseudo return PSEUDO;
-prepend return PREPEND;
-usermode return USERMODE;
+[a-zA-Z_][a-zA-Z_0-9]* { int res = find_token(yytext); if (res) return res; else REJECT; }
\n lineno++;
. return yytext[0];