Merge branch 'u2_10_12_branch' of git://git.code.sf.net/p/undernet-ircu/ircu2
[ircu2.10.12-pk.git] / ircd / ircd_lexer.l
diff --git a/ircd/ircd_lexer.l b/ircd/ircd_lexer.l
new file mode 100644 (file)
index 0000000..78818e8
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * 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.
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ *  USA.
+ * $Id$
+ */
+
+%{
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "config.h"
+#include "fileio.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;
+}
+
+static FBFILE *lexer_input;
+
+#undef YY_INPUT
+#define YY_INPUT(buf, res, size) res = (fbgets(buf, size, lexer_input) ? strlen(buf) : 0)
+
+int
+init_lexer(void)
+{
+  lexer_input = fbopen(configfile, "r");
+  if (lexer_input == NULL)
+  {
+#ifdef YY_FATAL_ERROR
+    YY_FATAL_ERROR("Could not open the configuration file.");
+#else
+    fprintf(stderr, "Could not open the configuration file.");
+#endif
+    return 0;
+  }
+#ifdef YY_NEW_FILE
+  YY_NEW_FILE;
+#endif
+  lineno = 1;
+  return 1;
+}
+
+void deinit_lexer(void)
+{
+  if (lexer_input != NULL)
+  {
+    fbclose(lexer_input);
+    lexer_input = NULL;
+  }
+}
+
+int
+yywrap(void)
+{
+  return 1;
+}
+
+%}
+
+WHITE [ \t\r]+
+SHCOMMENT #[^\n]*
+NUMBER [0-9]+
+QSTRING \"[^"\n]+[\"\n]
+%%
+
+{QSTRING} {yytext[yyleng-1] = 0; DupString(yylval.text, yytext+1); return QSTRING;}
+{NUMBER} {yylval.num = strtoul(yytext, NULL, 10); return NUMBER;}
+{WHITE} ;
+{SHCOMMENT} ;
+
+[a-zA-Z_][a-zA-Z_0-9]* { int res = find_token(yytext); if (res) return res; else REJECT; }
+\n lineno++;
+. return yytext[0];