Browse files

''Added awkbot to repository''

git-svn-id: http://svn.blisted.org/trunk/awkbot@8 ebfa9934-6f10-0410-9599-894cdf3d53f0
  • Loading branch information...
0 parents commit ac4b41fd36cbd9d86a69b9c6d88cfd02d7a76738 scottmc committed Apr 5, 2006
Showing with 1,769 additions and 0 deletions.
  1. +47 −0 awkbot.sql
  2. +8 −0 awkpaste.awk
  3. +3 −0 awkpaste.cgi
  4. +323 −0 bin/awkpp
  5. +119 −0 bin/awkpp.awk
  6. +169 −0 bin/pawk
  7. +27 −0 etc/awkbot.conf
  8. +122 −0 lib/awkbot.awk
  9. +78 −0 lib/awkbot_db_mysql.awk
  10. +35 −0 lib/awkdoc.awk
  11. +17 −0 lib/cgi-lib.awk
  12. +64 −0 lib/config.awk
  13. +15 −0 lib/crand.awk
  14. +185 −0 lib/irc.awk
  15. +108 −0 lib/mysql.awk
  16. +66 −0 lib/queue.awk
  17. +5 −0 start
  18. +94 −0 t/awkbot
  19. +74 −0 t/awkbot.old
  20. +94 −0 t/awkbot.old2
  21. +13 −0 t/base_modules
  22. +24 −0 t/irc_test.awk
  23. +20 −0 t/queue_test.awk
  24. +18 −0 t/test_config.awk
  25. +7 −0 t/test_config.conf
  26. +34 −0 t/xmb_test_config.awk
47 awkbot.sql
@@ -0,0 +1,47 @@
+-- MySQL dump 9.11
+--
+-- Host: localhost Database: awkbot
+-- ------------------------------------------------------
+-- Server version 4.0.23_Debian-1-log
+
+--
+-- Table structure for table `karma`
+--
+
+CREATE TABLE `karma` (
+ `nick` varchar(100) NOT NULL default '',
+ `karma` int(11) default NULL,
+ PRIMARY KEY (`nick`)
+) TYPE=MyISAM;
+
+--
+-- Dumping data for table `karma`
+--
+
+INSERT INTO `karma` VALUES ('tag',5);
+INSERT INTO `karma` VALUES ('awkbot',0);
+INSERT INTO `karma` VALUES ('xmb',1);
+INSERT INTO `karma` VALUES ('paul',11);
+
+--
+-- Table structure for table `qna`
+--
+
+CREATE TABLE `qna` (
+ `question` varchar(100) default NULL,
+ `answer` varchar(255) default NULL
+) TYPE=MyISAM;
+
+--
+-- Dumping data for table `qna`
+--
+
+INSERT INTO `qna` VALUES ('is','is I use it\r');
+INSERT INTO `qna` VALUES ('paul','the man');
+INSERT INTO `qna` VALUES ('tag','the author');
+INSERT INTO `qna` VALUES ('awk','the tool used to write me');
+INSERT INTO `qna` VALUES ('mysql','the RDBM I use, just because tag is too lazy to write a pg.awk too.');
+INSERT INTO `qna` VALUES ('mysql_quote','something tag really needs to add to mysql.awk');
+INSERT INTO `qna` VALUES ('xmb','the guy with incompatible libraries');
+INSERT INTO `qna` VALUES ('mysql.awk','http://www.blisted.org/svn/modules/mysql.awk/ until tag writes documentation');
+
8 awkpaste.awk
@@ -0,0 +1,8 @@
+#!/usr/bin/awk -f
+
+BEGIN {
+ params(Query)
+ for (key in Query) {
+ print key, ":", Query[key]
+ }
+}
3 awkpaste.cgi
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+exec awk -f cgi-lib.awk -f awkpaste.awk
323 bin/awkpp
@@ -0,0 +1,323 @@
+#!/usr/bin/awk -f
+# AWK PP, the awk preprocessor
+# -----------------------------------------------------------------------------
+# "THE BEER-WARE LICENSE" (Revision 43) borrowed from FreeBSD's jail.c:
+# <tag@cpan.org> wrote this file. As long as you retain this notice you
+# can do whatever you want with this stuff. If we meet some day, and you think
+# this stuff is worth it, you can buy me a beer in return. Scott S. McCoy
+# -----------------------------------------------------------------------------
+
+# ord.awk --- do ord and chr
+
+# Global identifiers:
+# _ord_: numerical values indexed by characters
+# _ord_init: function to initialize _ord_
+#
+# Arnold Robbins, arnold@gnu.org, Public Domain
+# 16 January, 1992
+# 20 July, 1992, revised
+
+BEGIN { _ord_init() }
+
+function _ord_init( low, high, i, t)
+{
+ low = sprintf("%c", 7) # BEL is ascii 7
+ if (low == "\a") { # regular ascii
+ low = 0
+ high = 127
+ } else if (sprintf("%c", 128 + 7) == "\a") {
+ # ascii, mark parity
+ low = 128
+ high = 255
+ } else { # ebcdic(!)
+ low = 0
+ high = 255
+ }
+
+ for (i = low; i <= high; i++) {
+ t = sprintf("%c", i)
+ _ord_[t] = i
+ }
+}
+function ord(str, c)
+{
+ # only first character is of interest
+ c = substr(str, 1, 1)
+ return _ord_[c]
+}
+
+function chr(c)
+{
+ # force c to be numeric by adding 0
+ return sprintf("%c", c + 0)
+}
+# assert --- assert that a condition is true. Otherwise exit.
+
+#
+# Arnold Robbins, arnold@gnu.org, Public Domain
+# May, 1993
+
+function assert(condition, string)
+{
+ if (! condition) {
+ printf("%s:%d: assertion failed: %s\n",
+ FILENAME, FNR, string) > "/dev/stderr"
+ _assert_exit = 1
+ exit 1
+ }
+}
+
+END {
+ if (_assert_exit)
+ exit 1
+}
+# awkbot/config.awk - A library for simple configuration file parsing
+# -----------------------------------------------------------------------------
+# "THE BEER-WARE LICENSE" (Revision 43) borrowed from FreeBSD's jail.c:
+# <tag@cpan.org> wrote this file. As long as you retain this notice you
+# can do whatever you want with this stuff. If we meet some day, and you think
+# this stuff is worth it, you can buy me a beer in return. Scott S. McCoy
+# -----------------------------------------------------------------------------
+# deps: assert.awk
+
+function config_load (filename) {
+ _config["config", "filename"] = filename
+ config_parse(_config, 0, filename)
+}
+
+# Recurse over new levels
+function config_parse (config_data,level,filename ,l,t,current,closing) {
+ if (config_data["debug"])
+ printf "config_parse(ARRAY, %s, %s)\n", level, filename
+
+ while ( getline < filename ) {
+ # Strip coments
+ sub(/#.*$/, "")
+
+ if (config_data["debug"]) {
+ printf "read:%s:%d %s\n", filename, NR, $0
+ print "Current namespace", level
+ }
+
+ if (/<[^/][^>]*>/) {
+ match($0, /<([^/][^>]*)>/, l)
+ if (config_data["debug"]) print "Opening: ", l[1]
+ if (level) config_parse(config_data, level SUBSEP l[1], filename)
+ else config_parse(config_data, l[1], filename)
+ }
+ else if (/<[/][^>]*>/) {
+ match($0, /<[/]([^>]*)>/, l)
+ t = split(l[1], l, SUBSEP)
+ closing = l[t]
+ t = split(level, l, SUBSEP)
+ current = l[t]
+
+ if (config_data["debug"]) print "Open", current, "close", closing
+ assert((current == closing), "Inconsistent open/close tags")
+ return
+ }
+ else {
+ if (match($0, /([^ ][^ ]*)[ ]*(..*)/, l)) {
+ if (config_data["debug"]) print level SUBSEP l[1], "=", l[2]
+ if (level) config_data[level, l[1]] = l[2]
+ else config_data[l[1]] = l[2]
+ }
+ }
+ }
+}
+
+function config (item, value ,element) {
+ element = gensub(/\./, SUBSEP, "g", item)
+
+ if (value) _config[element] = value
+ if (_config["debug"]) print "config():", item, "(" element ")", value
+# We should just treat undefined stuff as undefined *shrug*
+# assert(_config[element], "config(): " element " is of no value")
+ return _config[element]
+}
+# getopt.awk --- do C library getopt(3) function in awk
+#
+# Arnold Robbins, arnold@gnu.org, Public Domain
+#
+# Initial version: March, 1991
+# Revised: May, 1993
+
+# External variables:
+# Optind -- index in ARGV of first nonoption argument
+# Optarg -- string value of argument to current option
+# Opterr -- if nonzero, print our own diagnostic
+# Optopt -- current option letter
+
+# Returns:
+# -1 at end of options
+# ? for unrecognized option
+# <c> a character representing the current option
+
+# Private Data:
+# _opti -- index in multi-flag option, e.g., -abc
+function getopt(argc, argv, options, thisopt, i)
+{
+ if (length(options) == 0) # no options given
+ return -1
+
+ if (argv[Optind] == "--") { # all done
+ Optind++
+ _opti = 0
+ return -1
+ } else if (argv[Optind] !~ /^-[^: \t\n\f\r\v\b]/) {
+ _opti = 0
+ return -1
+ }
+ if (_opti == 0)
+ _opti = 2
+ thisopt = substr(argv[Optind], _opti, 1)
+ Optopt = thisopt
+ i = index(options, thisopt)
+ if (i == 0) {
+ if (Opterr)
+ printf("%c -- invalid option\n",
+ thisopt) > "/dev/stderr"
+ if (_opti >= length(argv[Optind])) {
+ Optind++
+ _opti = 0
+ } else
+ _opti++
+ return "?"
+ }
+ if (substr(options, i + 1, 1) == ":") {
+ # get option argument
+ if (length(substr(argv[Optind], _opti + 1)) > 0)
+ Optarg = substr(argv[Optind], _opti + 1)
+ else
+ Optarg = argv[++Optind]
+ _opti = 0
+ } else
+ Optarg = ""
+ if (_opti == 0 || _opti >= length(argv[Optind])) {
+ Optind++
+ _opti = 0
+ } else
+ _opti++
+ return thisopt
+}
+BEGIN {
+ Opterr = 1 # default is to diagnose
+ Optind = 1 # skip ARGV[0]
+
+ # test program
+ if (_getopt_test) {
+ while ((_go_c = getopt(ARGC, ARGV, "ab:cd")) != -1)
+ printf("c = <%c>, optarg = <%s>\n",
+ _go_c, Optarg)
+ printf("non-option arguments:\n")
+ for (; Optind < ARGC; Optind++)
+ printf("\tARGV[%d] = <%s>\n",
+ Optind, ARGV[Optind])
+ }
+}
+
+BEGIN {
+ # We need to do a better job of determining what awk we're running in here
+ awk = "awk -f -"
+
+ while ((opt = getopt(ARGC, ARGV, "sc:")) != -1) {
+ if (opt == "c") config_file = Optarg
+ if (opt == "s") awk = "cat"
+ }
+
+ if (config_file) {
+ config_load(config_file)
+
+ if (config("awkpp.define") ~ /^[0-9]+/) {
+ for (i = 1; i <= config("awkpp.define"); i++) {
+ # Define stuff
+ }
+ }
+ else if (config("awkpp.define")) {
+ # define one
+ }
+ if (config("awkpp.load") ~ /^[0-9]+/) {
+ # include loop
+ }
+ else if (config("awkpp.load")) {
+ # include one
+ }
+ }
+
+ # File to processes
+ filename = ARGV[--ARGC]
+
+ for (i = 2; i <= ARGC; i++) {
+ awk = awk " " ARGV[i]
+ delete ARGV[i]
+ }
+
+# while (ARGC > 1) proc_include(ARGV[--ARGC])
+ proc_include(filename)
+
+ printf chr(10) | awk
+ close(awk)
+}
+
+function proc_include (filename ,stop,il,path,k,location,test,junk) {
+ split(ENVIRON["AWKPATH"], path, ":")
+
+ for (k = 1; path[k]; k++) {
+ test = path[k] "/" filename
+ if ((getline junk <test) >= 0) {
+ close(test)
+ location = test
+ break
+ }
+ }
+
+ assert(location, "Unable to locate: " filename " in " ENVIRON["AWKPATH"])
+
+ while (getline < location) proc_run(location)
+}
+
+function proc_run (location ,il,junk,macro) {
+ if (match($0, /^#define ([[:alnum:]]*) *([^\\]*)\\? *$/, il)) {
+ define[il[1]] = il[2]
+ while ($NF == "\\") {
+ getline junk < location
+ define[il[1]] = define[il[1]] junk
+ }
+ }
+ else if (match($0, /^#if(n?)def ([[:alnum:]]*)$/, il)) {
+ if ((il[1] && ! define[il[2]]) || define[il[2]]) {
+ while (getline < location) {
+ if (/^#else/) {
+ while (!/^#endif/) getline < location
+ return
+ }
+ if (/^#endif/) return
+ proc_run(location)
+ }
+ }
+ else {
+ while (getline < location) {
+ if (/^#else/) {
+ getline < location # Skip this line
+ while (!/^#endif/) {
+ proc_run(location) # This strange way of
+ getline < location # doing things is to make
+ } # sure the macros get
+ return # stripped
+ }
+ }
+ }
+ }
+ else if (match($0, /^#include <([^>]+)>/, il)) {
+ if (!included[il[1]]) {
+ included[il[1]] = 1
+ proc_include(il[1])
+ }
+ }
+ else {
+ for (macro in define) gsub(macro, define[macro])
+ print | awk
+ }
+}
+
+
119 bin/awkpp.awk
@@ -0,0 +1,119 @@
+#!/usr/bin/awk -f
+# AWK PP, the awk preprocessor
+# -----------------------------------------------------------------------------
+# "THE BEER-WARE LICENSE" (Revision 43) borrowed from FreeBSD's jail.c:
+# <tag@cpan.org> wrote this file. As long as you retain this notice you
+# can do whatever you want with this stuff. If we meet some day, and you think
+# this stuff is worth it, you can buy me a beer in return. Scott S. McCoy
+# -----------------------------------------------------------------------------
+
+#include <ord.awk>
+#include <assert.awk>
+#include <config.awk>
+#include <getopt.awk>
+#define STRAPPED 1
+
+BEGIN {
+ # We need to do a better job of determining what awk we're running in here
+ awk = "awk -f -"
+
+ while ((opt = getopt(ARGC, ARGV, "sc:")) != -1) {
+ if (opt == "c") config_file = Optarg
+ if (opt == "s") awk = "cat"
+ }
+
+ if (config_file) {
+ config_load(config_file)
+
+ if (config("awkpp.define") ~ /^[0-9]+/) {
+ for (i = 1; i <= config("awkpp.define"); i++) {
+ # Define stuff
+ }
+ }
+ else if (config("awkpp.define")) {
+ # define one
+ }
+ if (config("awkpp.load") ~ /^[0-9]+/) {
+ # include loop
+ }
+ else if (config("awkpp.load")) {
+ # include one
+ }
+ }
+
+ # File to processes
+ filename = ARGV[--ARGC]
+
+ for (i = 2; i <= ARGC; i++) {
+ awk = awk " " ARGV[i]
+ delete ARGV[i]
+ }
+
+# while (ARGC > 1) proc_include(ARGV[--ARGC])
+ proc_include(filename)
+
+ printf chr(10) | awk
+ close(awk)
+}
+
+function proc_include (filename ,stop,il,path,k,location,test,junk) {
+ split(ENVIRON["AWKPATH"], path, ":")
+
+ for (k = 1; path[k]; k++) {
+ test = path[k] "/" filename
+ if ((getline junk <test) >= 0) {
+ close(test)
+ location = test
+ break
+ }
+ }
+
+ assert(location, "Unable to locate: " filename " in " ENVIRON["AWKPATH"])
+
+ while (getline < location) proc_run(location)
+}
+
+function proc_run (location ,il,junk,macro) {
+ if (match($0, /^#define ([[:alnum:]]*) *([^\\]*)\\? *$/, il)) {
+ define[il[1]] = il[2]
+ while ($NF == "\\") {
+ getline junk < location
+ define[il[1]] = define[il[1]] junk
+ }
+ }
+ else if (match($0, /^#if(n?)def ([[:alnum:]]*)$/, il)) {
+ if ((il[1] && ! define[il[2]]) || define[il[2]]) {
+ while (getline < location) {
+ if (/^#else/) {
+ while (!/^#endif/) getline < location
+ return
+ }
+ if (/^#endif/) return
+ proc_run(location)
+ }
+ }
+ else {
+ while (getline < location) {
+ if (/^#else/) {
+ getline < location # Skip this line
+ while (!/^#endif/) {
+ proc_run(location) # This strange way of
+ getline < location # doing things is to make
+ } # sure the macros get
+ return # stripped
+ }
+ }
+ }
+ }
+ else if (match($0, /^#include <([^>]+)>/, il)) {
+ if (!included[il[1]]) {
+ included[il[1]] = 1
+ proc_include(il[1])
+ }
+ }
+ else {
+ for (macro in define) gsub(macro, define[macro])
+ print | awk
+ }
+}
+
169 bin/pawk
@@ -0,0 +1,169 @@
+#!/usr/bin/awk -f
+# AWK Proc, the awk preprocessor
+# -----------------------------------------------------------------------------
+# "THE BEER-WARE LICENSE" (Revision 43) borrowed from FreeBSD's jail.c:
+# <tag@cpan.org> wrote this file. As long as you retain this notice you
+# can do whatever you want with this stuff. If we meet some day, and you think
+# this stuff is worth it, you can buy me a beer in return. Scott S. McCoy
+# -----------------------------------------------------------------------------
+
+#include <ord.awk>
+#include <assert.awk>
+#include <config.awk>
+#include <getopt.awk>
+
+BEGIN {
+ # We need to do a better job of determining what awk we're running in here
+ awk = "cat"
+
+# while ((opt = getopt(ARGC, ARGV, "sc:")) != -1) {
+# if (opt == "c") configfile = Optarg
+# if (opt == "s") awk = "cat"
+# }
+
+ # File to processes
+ filename = ARGV[--ARGC]
+
+ if (filename == "-c") {
+ configfile = ARGV[--ARGC]
+ filename = ARGV[--ARGC]
+ }
+
+ while (ARGC > 1) {
+ awk = awk " " ARGV[--ARGC]
+ }
+
+ proc_include(filename)
+ printf chr(10) | awk
+ close(awk)
+}
+
+function proc_include (filename ,stop,il,path,k,location,test,junk) {
+ split(ENVIRON["AWKPATH"], path, ":")
+
+ for (k = 1; path[k]; k++) {
+ test = path[k] "/" filename
+ if ((getline junk <test) >= 0) {
+ close(test)
+ location = test
+ break
+ }
+ }
+
+ assert(location, "Unable to locate: " filename " in " ENVIRON["AWKPATH"])
+
+ while (getline < location) proc_run(location)
+}
+
+function proc_run (location ,il,junk) {
+ if (match($0, /^#define ([[:alnum:]]*) (.*)/, il)) {
+ define[il[1]] = il[2]
+ while ($NF == "\\") {
+ getline junk < location
+ define[il[1]] = define[il[1]] junk
+ }
+ }
+ else if (match($0, /^#ifdef ([[:alnum:]]*)$/, il)) {
+ if (define[il[1]]) {
+ while (getline < location) {
+ if (/^#else/) {
+ while (!/^#endif/) getline < location
+ return
+ }
+ if (/^#endif/) return
+ proc_run(location)
+ }
+ }
+ else {
+ while (getline < location) {
+ if (/^#else/) {
+ getline < location # Skip this line
+ while (!/^#endif/) {
+ proc_run(location) # This strange way of
+ getline < location # doing things is to make
+ } # sure the macros get
+ return # stripped
+ }
+ }
+ }
+ }
+ else if (match($0, /^#include <([^>]+)>/, il)) {
+ if (!included[il[1]]) {
+ included[il[1]] = 1
+ proc_include(il[1])
+ }
+ }
+ else {
+ print | awk
+ }
+}
+
+
+# This is actually a library, but we cannot #include its since we ARE the
+# preprocessor ;-)
+# ord.awk --- do ord and chr
+
+# Global identifiers:
+# _ord_: numerical values indexed by characters
+# _ord_init: function to initialize _ord_
+#
+# Arnold Robbins, arnold@gnu.org, Public Domain
+# 16 January, 1992
+# 20 July, 1992, revised
+
+BEGIN { _ord_init() }
+
+function _ord_init( low, high, i, t)
+{
+ low = sprintf("%c", 7) # BEL is ascii 7
+ if (low == "\a") { # regular ascii
+ low = 0
+ high = 127
+ } else if (sprintf("%c", 128 + 7) == "\a") {
+# ascii, mark parity
+ low = 128
+ high = 255
+ } else { # ebcdic(!)
+ low = 0
+ high = 255
+ }
+
+ for (i = low; i <= high; i++) {
+ t = sprintf("%c", i)
+ _ord_[t] = i
+ }
+}
+function ord(str, c)
+{
+# only first character is of interest
+ c = substr(str, 1, 1)
+ return _ord_[c]
+}
+
+function chr(c)
+{
+# force c to be numeric by adding 0
+ return sprintf("%c", c + 0)
+}
+
+# assert --- assert that a condition is true. Otherwise exit.
+
+#
+# Arnold Robbins, arnold@gnu.org, Public Domain
+# May, 1993
+
+function assert(condition, string)
+{
+ if (! condition) {
+ printf("%s:%d: assertion failed: %s\n",
+ FILENAME, FNR, string) > "/dev/stderr"
+ _assert_exit = 1
+ exit 1
+ }
+}
+
+ END {
+ if (_assert_exit)
+ exit 1
+ }
+
27 etc/awkbot.conf
@@ -0,0 +1,27 @@
+
+# IRC Stuff
+<irc>
+ nickname awkbot
+ altnick awkbot_
+ username awkbot
+ realname AWK IRC bot
+# server irc.isprime.com:6667
+ server irc.freenode.net:6667
+# port 6667
+# channel awk perl pike
+# channel c++
+ channel awk
+# channel blacksun
+ debug 1
+ startup PRIVMSG NickServ :identify darwin
+</irc>
+
+# Mysql settings
+# The awk preprocessor uses this
+mysql on
+
+<mysql>
+ username tag
+ password darwin
+ database awkbot
+</mysql>
122 lib/awkbot.awk
@@ -0,0 +1,122 @@
+# awkbot
+# -----------------------------------------------------------------------------
+# "THE BEER-WARE LICENSE" (Revision 43) borrowed from FreeBSD's jail.c:
+# <tag@cpan.org> wrote this file. As long as you retain this notice you
+# can do whatever you want with this stuff. If we meet some day, and you think
+# this stuff is worth it, you can buy me a beer in return. Scott S. McCoy
+# -----------------------------------------------------------------------------
+
+#include <assert.awk>
+#include <config.awk>
+#include <awkbot_db_mysql.awk>
+#include <irc.awk>
+#include <awkdoc.awk>
+#include <join.awk>
+#include <queue.awk>
+
+#define TEST 1
+
+#ifdef TEST
+BEGIN {
+ print "Awkbot is starting up..."
+}
+#else
+BEGIN {
+ print "This program needs to be loaded with awkpp"
+ exit
+}
+#endif
+
+BEGIN {
+# assert(irc, "Awkbot depends on irc.awk")
+# assert(awkbot_config, "Awkbot depends on config.awk")
+
+ VERSION = "awkbot $Revision: 412 $"
+
+ config_load("etc/awkbot.conf")
+
+ assert(config("irc.username"), "username not specified in config")
+ assert(config("irc.nickname"), "nickname not specified in config")
+ assert(config("irc.altnick"), "altnick not specified in config")
+ assert(config("irc.server"), "server not specified in config")
+
+ irc_set("debug", config("irc.debug"))
+
+ irc_set("nickname", config("irc.nickname"))
+ irc_set("username", config("irc.username"))
+ irc_set("realname", config("irc.realname"))
+
+ irc_register("connect")
+ irc_register("privmsg")
+ irc_register("ctcp")
+
+ irc_connect(config("irc.server"))
+}
+
+function irc_handler_connect ( channel,key,msg) {
+ split(config("irc.channel"), channel)
+ for (key in channel) irc_join("#" channel[key])
+
+ msg = config("irc.startup")
+
+ if (msg) irc_sockwrite(msg "\r\n")
+}
+
+function irc_handler_ctcp (nick, host, recipient, action, argument) {
+ # Don't respond to channel ctcps
+ if (recipient !~ /\#/) {
+ if (tolower(action) == "version") {
+ irc_ctcp_reply(nick, action, VERSION)
+ }
+
+ else if (tolower(action) == "ping") {
+ irc_ctcp_reply(nick, action, argument)
+ }
+ }
+}
+
+function irc_handler_privmsg (nick, host, recipient, message, arg \
+ ,direct,target,address,action,t,q,a) {
+
+ if (recipient ~ /^#/) target = recipient
+ else target = nick
+
+ if (substr(arg[1], 0, length(irc["nickname"])) == irc["nickname"]) {
+ direct = 1
+ shift(arg)
+ }
+ else {
+ direct = (target != recipient)
+ }
+
+ if (target == recipient) address = nick ": "
+ else address = ""
+
+ if (direct) {
+ if (arg[1] == "karma") awkbot_karma_get(target,arg[2])
+ else if (arg[1] == "forget") {
+ awkbot_db_forget(join(arg,2,sizeof(arg),SUBSEP))
+ irc_privmsg(target, address "what's a "join(arg,2,sizeof(arg))"?")
+ }
+ else if (arg[2] == "is") {
+ awkbot_db_answer(arg[1], join(arg, 3, sizeof(arg), " "))
+ irc_privmsg(target, address "Okay")
+ }
+ else {
+ q = gensub(/\?$/, "", "g", join(arg, 1, sizeof(arg), SUBSEP))
+ if (a = awkbot_db_question(tolower(q)))
+ irc_privmsg(target, address a)
+ }
+ }
+
+ if (match(arg[1], /^(.*)\+\+$/, t)) awkbot_db_karma_inc(t[1])
+ if (match(arg[1], /^(.*)--$/, t)) awkbot_db_karma_dec(t[1])
+
+ if (arg[1] == "awkdoc")
+ irc_privmsg(target, address awkdoc(arg[2]))
+}
+
+function awkbot_karma_get (reply_to,nickname ,points) {
+ points = awkbot_db_karma(nickname)
+ irc_privmsg(reply_to, sprintf("Karma for %s: %d points", nickname, points))
+}
78 lib/awkbot_db_mysql.awk
@@ -0,0 +1,78 @@
+# -----------------------------------------------------------------------------
+# "THE BEER-WARE LICENSE" (Revision 43) borrowed from FreeBSD's jail.c:
+# <tag@cpan.org> wrote this file. As long as you retain this notice you
+# can do whatever you want with this stuff. If we meet some day, and you think
+# this stuff is worth it, you can buy me a beer in return. Scott S. McCoy
+# -----------------------------------------------------------------------------
+# deps: assert.awk mysql.awk
+
+#include <assert.awk>
+#include <mysql.awk>
+
+BEGIN {
+ # Config wont get parsed until awkbot's BEGIN {} block
+ irc_register("initialize")
+}
+
+function irc_handler_initialize () {
+ mysql_login(config("mysql.username"), config("mysql.password"))
+ mysql_db(config("mysql.database"))
+}
+
+function awkbot_db_karma_inc (nick,amount ,rv,row) {
+ # the "0" is because undefined == 0 is true, we want to see if its actually
+ # exactly zero.
+ if ((amount != "0") && ! amount) amount = 1;
+ rv = mysql_query("select * from karma where nick = " mysql_quote(nick))
+
+ mysql_fetch_assoc(rv, row)
+ mysql_finish(rv)
+ row["karma"] += amount
+
+ mysql_finish(mysql_query("replace into karma (nick,karma) values (" \
+ mysql_quote(nick) ", " row["karma"] ")"))
+}
+
+function awkbot_db_karma_dec (nick,amount,rv,row) {
+ if ((amount != "0") && ! amount) amount = 1;
+ rv = mysql_query("select * from karma where nick = " mysql_quote(nick))
+
+ mysql_fetch_assoc(rv, row)
+ mysql_finish(rv)
+ row["karma"] -= amount
+
+ mysql_finish(mysql_query("replace into karma (nick,karma) values (" \
+ mysql_quote(nick) ", " row["karma"] ")"))
+}
+
+function awkbot_db_karma (nick ,rv,row) {
+ rv = mysql_query("SELECT karma FROM karma WHERE nick = " mysql_quote(nick))
+
+ mysql_fetch_assoc(rv,row)
+ mysql_finish(rv)
+
+ return 0 + row["karma"]
+}
+
+function awkbot_db_question (question ,rv,row) {
+ rv = mysql_query("SELECT answer FROM qna WHERE question = " \
+ mysql_quote(question))
+
+ mysql_fetch_assoc(rv, row)
+ mysql_finish(rv)
+
+ return row["answer"]
+}
+
+function awkbot_db_answer (question,answer) {
+ mysql_finish(mysql_query("INSERT INTO qna (question, answer) " \
+ " VALUES (" mysql_quote(question) "," mysql_quote(answer) ")"))
+
+ return 1
+}
+
+function awkbot_db_forget (question) {
+ mysql_finish(mysql_query("DELETE FROM qna WHERE question = " \
+ mysql_quote(question)))
+ return 1
+}
35 lib/awkdoc.awk
@@ -0,0 +1,35 @@
+
+function awkdoc(Keyword ,result,line,get,Func,manpage) {
+ if (Keyword ~ /^[A-Z]+$/) Func = 0
+ else Func = 1
+
+ manpage = "man awk";
+
+ Keyword = "^ " Keyword (match(Keyword,"/") ? "" :
+ (Func ? "\\(" : " "))
+
+ while (manpage | getline line ) {
+ gsub(/.\010/, "", line)
+ gsub(/[\000-\037]/, "", line)
+
+ if (Func) {
+ if (line ~ Keyword) get++
+ if (length(line) == 0) get = 0
+ }
+
+ else {
+ if (line ~ Keyword) get = 1
+ if ((line ~ /^ [A-Z]+/) && (line !~ Keyword)) get = 0
+ }
+
+ if (get) result = result line
+ }
+
+ close(manpage)
+
+ gsub(/ +/, " ", result)
+ gsub(/- /, "", result)
+
+ return result
+}
+
17 lib/cgi-lib.awk
@@ -0,0 +1,17 @@
+#!/usr/bin/awk -f
+
+BEGIN {
+ if (ENVIRON["REQUEST_METHOD"] == "POST")
+ while ( getline ) _cgilib_in = _cgilib_in $0
+ if (ENVIRON["REQUEST_METHOD"] == "GET")
+ _cgilib_in = ENVIRON["QUERY_STRING"]
+}
+
+function params (Query ,Each,Pairs,i) {
+ split(_cgilib_in, Pairs, /\&/)
+ i = 0
+ while (Pairs[++i]) {
+ split(Pairs[i], Each, /=/)
+ Query[Each[1]] = Each[2]
+ }
+}
64 lib/config.awk
@@ -0,0 +1,64 @@
+# awkbot/config.awk - A library for simple configuration file parsing
+# -----------------------------------------------------------------------------
+# "THE BEER-WARE LICENSE" (Revision 43) borrowed from FreeBSD's jail.c:
+# <tag@cpan.org> wrote this file. As long as you retain this notice you
+# can do whatever you want with this stuff. If we meet some day, and you think
+# this stuff is worth it, you can buy me a beer in return. Scott S. McCoy
+# -----------------------------------------------------------------------------
+# deps: assert.awk
+
+function config_load (filename) {
+ _config["config", "filename"] = filename
+ config_parse(_config, 0, filename)
+}
+
+# Recurse over new levels
+function config_parse (config_data,level,filename ,l,t,current,closing) {
+ if (config_data["debug"])
+ printf "config_parse(ARRAY, %s, %s)\n", level, filename
+
+ while ( getline < filename ) {
+ # Strip coments
+ sub(/#.*$/, "")
+
+ if (config_data["debug"]) {
+ printf "read:%s:%d %s\n", filename, NR, $0
+ print "Current namespace", level
+ }
+
+ if (/<[^/][^>]*>/) {
+ match($0, /<([^/][^>]*)>/, l)
+ if (config_data["debug"]) print "Opening: ", l[1]
+ if (level) config_parse(config_data, level SUBSEP l[1], filename)
+ else config_parse(config_data, l[1], filename)
+ }
+ else if (/<[/][^>]*>/) {
+ match($0, /<[/]([^>]*)>/, l)
+ t = split(l[1], l, SUBSEP)
+ closing = l[t]
+ t = split(level, l, SUBSEP)
+ current = l[t]
+
+ if (config_data["debug"]) print "Open", current, "close", closing
+ assert((current == closing), "Inconsistent open/close tags")
+ return
+ }
+ else {
+ if (match($0, /([^ ][^ ]*)[ ]*(..*)/, l)) {
+ if (config_data["debug"]) print level SUBSEP l[1], "=", l[2]
+ if (level) config_data[level, l[1]] = l[2]
+ else config_data[l[1]] = l[2]
+ }
+ }
+ }
+}
+
+function config (item, value ,element) {
+ element = gensub(/\./, SUBSEP, "g", item)
+
+ if (value) _config[element] = value
+ if (_config["debug"]) print "config():", item, "(" element ")", value
+# We should just treat undefined stuff as undefined *shrug*
+# assert(_config[element], "config(): " element " is of no value")
+ return _config[element]
+}
15 lib/crand.awk
@@ -0,0 +1,15 @@
+# crand.awk - return an integer between 0 and cieling
+# -----------------------------------------------------------------------------
+# "THE BEER-WARE LICENSE" (Revision 43) borrowed from FreeBSD's jail.c:
+# <tag@cpan.org> wrote this file. As long as you retain this notice you
+# can do whatever you want with this stuff. If we meet some day, and you think
+# this stuff is worth it, you can buy me a beer in return. Scott S. McCoy
+# -----------------------------------------------------------------------------
+
+function crand (ceil) {
+ return sprintf("%d", (rand() * ceil))
+}
+
+function rcrand (ceil) {
+ return sprintf("%d", ((rand() * ceil) + 1))
+}
185 lib/irc.awk
@@ -0,0 +1,185 @@
+#!/usr/bin/awk -f
+# vim600:set ts=4 sw=4 expandtab cin nowrap:
+
+# AWK irc library -> irc.pod for details
+# -----------------------------------------------------------------------------
+# "THE BEER-WARE LICENSE" (Revision 43) borrowed from FreeBSD's jail.c
+# <tag@cpan.org> wrote this file. As long as you retain this notice you
+# can do whatever you want with this stuff. If we meet some day, and you think
+# this stuff is worth it, you can buy me a beer in return. Scott S. McCoy
+# -----------------------------------------------------------------------------
+
+# Init
+
+BEGIN {
+ if (!irc["tempfile"]) irc["tempfile"] = irc_allocate_tempfile()
+
+ print "INIT" > irc["tempfile"]
+ close(irc["tempfile"])
+
+ ARGV[ARGC++] = irc["tempfile"]
+}
+
+END {
+ system(sprintf("rm %s", irc["tempfile"]))
+}
+
+
+# -----------------------------------------------------------------------------
+# Event traps
+
+$0 == "INIT" { irc_parse_init() }
+$2 == "001" { irc_parse_connect() }
+$2 == "PRIVMSG" { irc_parse_privmsg() }
+$1 == "ERROR" { irc_parse_error() }
+$2 == "INVITE" { irc_parse_invite() }
+$1 == "PING" { irc_parse_ping() }
+
+# -----------------------------------------------------------------------------
+# Event handlers
+function irc_parse_init() {
+ if (irc["register", "initialize"]) irc_handler_initialize()
+}
+function irc_parse_connect () {
+ if (irc["register", "connect"]) irc_handler_connect()
+}
+
+# :tag!~tag@c-67-183-29-168.client.comcast.net PRIVMSG #awk :OK
+function irc_parse_privmsg ( arg,i,t) {
+ if ($0 ~ /\x01.*\x01\r/) {
+ if (irc["register", "ctcp"]) {
+ match($0, ":([^!]*)!([^ ]*) PRIVMSG ([^ ]*) :([^\r]*)", t)
+ match($0, ":\x01([A-Z][A-Z]*) ?([^\x01]*)\x01", arg)
+ irc_handler_ctcp(t[1], t[2], t[3], arg[1], arg[2])
+ }
+ }
+ else {
+ if (irc["register", "privmsg"]) {
+ match($0, ":([^!]*)!([^ ]*) PRIVMSG ([^ ]*) :([^\r]*)", t)
+ split(t[4], arg)
+ irc_handler_privmsg(t[1], t[2], t[3], t[4], arg)
+ }
+ }
+}
+
+function irc_parse_invite () { return }
+function irc_parse_ping () {
+ if (irc["register", "ping"]) irc_handler_ping($2)
+
+ irc_sockwrite("PONG " $2 "\r\n")
+}
+function irc_parse_error ( message) {
+ if (irc["register", "error"]) irc_handler_error()
+
+ irc_sockclose()
+}
+
+# -----------------------------------------------------------------------------
+# Runtime Control API
+function irc_register (event) { irc["register", event] = 1 }
+function irc_unregister (event) { irc["register", event] = 0 }
+function irc_error (message) { print message; exit(1); }
+
+# -----------------------------------------------------------------------------
+# Connection API
+function irc_privmsg (target, message) {
+ irc_sockwrite(sprintf("PRIVMSG %s :%s\r\n", target, message))
+}
+
+function irc_ctcp (target, type, arg) {
+ irc_sockwrite(sprintf("PRIVMSG %s :\x01%s %s\x01\r\n", target, type, arg))
+}
+
+function irc_ctcp_reply (target, type, arg) {
+ irc_sockwrite(sprintf("NOTICE %s :\x01%s %s\x01\r\n", target, type, arg))
+}
+
+function irc_join (channel) {
+ irc_sockwrite(sprintf("JOIN %s\r\n", channel))
+}
+
+function irc_part (channel, message) {
+ irc_sockwrite(sprintf("PART %s :%s\r\n", channel, message))
+}
+
+function irc_quit (message) {
+ irc_sockwrite(sprintf("QUIT :%s\r\n", message))
+}
+
+function irc_connect (host, port) {
+ irc_sockopen(host, port)
+ irc_sockwrite("NICK " irc["nickname"] "\n")
+ irc_sockwrite("USER " irc["username"] " a a :" irc["realname"] "\r\n")
+}
+
+function irc_set (key, value) { irc[key] = value }
+
+# -----------------------------------------------------------------------------
+# Raw internals
+
+function irc_allocate_tempfile ( mktemp,tempfile) {
+ if (! irc["command", "mktemp"]) mktemp = "mktemp /tmp/irc.awk.XXXXXX"
+ else mktemp = irc["command", "mktemp"]
+
+ mktemp | getline tempfile
+ close(mktemp)
+
+ return tempfile
+}
+
+function irc_sockwrite (data) {
+ if (irc["socket"]) printf data |& irc["socket"]
+ else irc_error("Attempt to write" data " to closed socket")
+
+ if (irc["debug"]) printf "> %s\n", data
+}
+
+function irc_sockopen (host,port ,t) {
+ if (! irc["socket"]) {
+ if (! port) {
+ if (host !~ /:/) {
+ irc_error("irc_sockopen called without port number")
+ }
+
+ split(host,t,/:/)
+ host = t[1]
+ port = t[2]
+ }
+
+ irc["socket"] = "/inet/tcp/0/" host "/" port
+ }
+}
+
+function irc_sockclose () {
+ if (irc["socket"]) {
+ close(irc["socket"])
+ delete irc["socket"]
+ }
+ else irc_error("irc_sockclose called with no open socket")
+}
+
+# -----------------------------------------------------------------------------
+# Main loop
+
+{
+ if (irc["socket"]) {
+ # Get next line from socket and put in file for parsing
+ irc["socket"] |& getline
+
+ # Cycle Tempfile every 1000th line.
+ if (FNR == 1000) {
+ print > irc["tempfile"]
+ ARGV[ARGC++] = FILENAME
+ delete ARGV[ARGC - 2]
+ }
+
+ # Write to tempfile for next iteration
+ else print >> irc["tempfile"]
+ close(irc["tempfile"])
+
+ if (irc["debug"]) print
+ }
+}
+
+END { if (irc["socket"]) close(irc["socket"]) }
+
108 lib/mysql.awk
@@ -0,0 +1,108 @@
+# mysql client library for awk
+# -----------------------------------------------------------------------------
+# "THE BEER-WARE LICENSE" (Revision 43) borrowed from FreeBSD's jail.c:
+# <tag@cpan.org> wrote this file. As long as you retain this notice you
+# can do whatever you want with this stuff. If we meet some day, and you think
+# this stuff is worth it, you can buy me a beer in return. Scott S. McCoy
+# -----------------------------------------------------------------------------
+
+BEGIN {
+ if (!mysql["path"]) {
+ mysql["path"] = "/usr/bin/mysql"
+ }
+ if (mysql["user"]) mysql["user"] = "-u" mysql["user"]
+ if (mysql["pass"]) mysql["pass"] = "-p" mysql["pass"]
+
+ if (!mysql["tempfile_command"]) {
+ mysql["tempfile_command"] = "mktemp /tmp/__mysql.awk.XXXXXX"
+ }
+
+ mysql["resource_id"] = 1
+}
+
+function mysql_db (db) { mysql["database"] = db }
+function mysql_path (path) { mysql["path"] = path }
+
+function mysql_tempfile_command (command) {
+ mysql["tempfile_command"] = command
+}
+
+function mysql_login (username, password, host, args) {
+ mysql["user"] = "-u" username
+ mysql["pass"] = "-p" password
+ if (host) mysql["host"] = "-h" host
+ if (args) mysql["args"] = args
+}
+
+function mysql_query (query ,input,key,i,call,resource) {
+ resource = mysql["resource_id"]++
+ mysql["tempfile_command"] | getline mysql[resource]
+ close(mysql["tempfile_command"])
+
+ call = sprintf("%s %s %s %s %s %s > %s",
+ mysql["path"], mysql["user"], mysql["pass"], mysql["host"],
+ mysql["args"], mysql["database"],
+ mysql[resource])
+
+ print query | call
+
+ close(call)
+
+ if (getline input < mysql[resource]) {
+ for (i = split(input, key, "\t"); i > 0; i--)
+ mysql[resource, i] = key[i]
+ }
+
+ return resource
+}
+
+function mysql_fetch_assoc (resource,row ,input,i,fields) {
+ if (getline input < mysql[resource]) {
+ fields = split(input, row, "\t")
+ for (i = 1; i <= fields; i++)
+ row[mysql[resource, i]] = row[i]
+ }
+
+ return fields
+}
+
+function mysql_fetch_row (resource,row ,input) {
+ if (getline input < mysql[resource])
+ return split(input, row, "\t")
+
+ return 0
+}
+
+function mysql_index (resource, id) {
+ return mysql[resource, id]
+}
+
+function mysql_finish (resource, i) {
+ close(mysql[resource])
+ system(sprintf("rm %s", mysql[resource]))
+
+ delete mysql[resource]
+
+ i = 1
+ while (mysql[resource,i])
+ delete mysql[resource, i++]
+}
+
+function mysql_cleanup ( i) {
+ for (i = 1; i < mysql["resource_id"]; i++)
+ if (mysql[i]) {
+ close(mysql[i])
+ system(sprintf("rm %s", mysql[i]))
+
+ delete mysql[resource]
+
+ i = 1
+ while (mysql[resource,i])
+ delete mysql[resource, i++]
+ }
+}
+
+function mysql_quote (string, result) {
+ result = gensub("([^\\\\])'", "\\1\\\\'", "g", string)
+ return "'" result "'"
+}
66 lib/queue.awk
@@ -0,0 +1,66 @@
+# queue.awk - Utilities to use an array as a queue
+# -----------------------------------------------------------------------------
+# "THE BEER-WARE LICENSE" (Revision 43) borrowed from FreeBSD's jail.c:
+# <tag@cpan.org> wrote this file. As long as you retain this notice you
+# can do whatever you want with this stuff. If we meet some day, and you think
+# this stuff is worth it, you can buy me a beer in return. Scott S. McCoy
+# -----------------------------------------------------------------------------
+
+#include <assert.awk>
+
+function push (array, value,i) {
+ i = sizeof(array) + 1
+ array[i] = value
+ return value
+}
+
+function pop (array ,value,i) {
+ i = sizeof(array)
+
+ if (! i) return
+
+ value = array[i]
+ delete array[i]
+
+ return value
+}
+
+function shift (array ,value,i) {
+ if (! array[1]) return
+
+ value = array[1]
+
+ for (i = 2; array[i]; i++)
+ array[i - 1] = array[i]
+
+ delete array[i - 1]
+ return value
+}
+
+# These are all slow, but this one is exceptionally bad. I have to iterate the
+# entire length of the array twice, once forward to find the numerical end,
+# once back to move the values. To the best of my knowledge, this is the only
+# way we're going to do this
+function unshift (array,value ,i) {
+ for (i = sizeof(array); i > 0; i--) array[i + 1] = array[i]
+
+ # Should be a safe assumption, this obviously has limitations
+ array[1] = value
+}
+
+function sizeof (array ,i) {
+ i = 1
+ while (array[i] || (array[i] == "0")) i++
+ return (i - 1)
+}
+
+function merge (from,to ,lf,lt,i) {
+ lf = sizeof(from);
+ lt = sizeof(to);
+
+ for (i = lt + 1; i < lf + lt; i++)
+ to[i] = from[i - lt]
+}
+
+function splice (result,array,off,len, ins ,i) {
+}
5 start
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+while sleep 1
+ do AWKPATH=`awk 'BEGIN{print ENVIRON["AWKPATH"]}'`:$PWD/lib/ ./bin/awkpp lib/awkbot.awk
+done
94 t/awkbot
@@ -0,0 +1,94 @@
+#!/bin/sh
+
+# if first arg of the script is -n, it doesnt get forked into the background
+
+[ "$1" == "-n" ] && stay=1 && shift
+[ "$1" == "-m" ] && mod=$2 && shift 2
+[ "$1" == "-p" ] && pre=$2 && shift 2
+
+bins=${pre}{g,}awk
+modules="base_modules xmb_features t/*.load $mod" paths="./,t/,lib/,bin/"
+args=
+#args="-f lib/awkdoc.awk -f lib/mysql.awk -f awkbot.awk"
+export start=1
+#export enable_mysql=1 enable_awkdoc=1
+
+function test_var() { echo enable_mysql - $enable_mysql; }
+test_var
+
+# [prefix=str]
+#function show_files() { for file in $@; do for dir in `eval echo {$paths}'; do
+# all=good$(stuff)
+
+function source_files() { for file in $@; do for dir in `eval echo {$paths}`; do
+ export nfile=$dir$file dir
+ [ -f $nfile ] || continue
+ file -b $nfile | grep -q shell && source $nfile && echo sourced $nfile
+
+ echo going for $nfile
+ _x=$(awk -F'[ \t]*:[ \t]*' '/^#*[ \t]*DEP:/ { print $2 } /^[ \t]+#*[ \t]*DEP:/ {
+ #print "1x" $1 "2x" $2 "3x" $3 "4x" $4 >"/dev/stderr";
+ if (ENVIRON[$2]) printf "%s ", $3 }' $nfile) &&
+ export iargs="$iargs $_x"
+ done
+ done
+}
+
+for i in `eval echo $bins`
+do
+ which $i &>/dev/null || continue
+ $i -W version 2>&1 | grep -q "GNU Awk [34].[12]" || continue
+
+ export awk=$i
+ break
+done
+
+if [ -z $awk ]
+then
+ echo No suitable gawk found on the system, GNU Awk 3.1 or later needed
+ exit 1
+fi
+
+test_var
+nofileloop=1
+[[ -z $nofileloop ]] && for file in $modules
+do
+ test_var
+ for dir in `eval echo {$paths}`; do
+ export nfile=$dir$file
+ [ -f $nfile ] && [ ! -z `eval echo -n \$seen_$nfile` ] || continue
+ test_var
+ #[ ! -f "$file" ] && continue ||
+ #[ -f $nfile ] && f=$f\ $nfile #||
+ f=$f\ $nfile
+ eval seen_$nfile=1
+ #[ -f t/$file ] && f=$f\ t/$file #||
+ #[ -f lib/$file ] && f=$f\ lib/$file #||
+ #[ -f bin/$file ] && f=$f\ bin/$file
+ done
+
+ for rfile in $f
+ do
+ [[ -z "$rfile" ]] && break
+ file -b "$rfile" | grep -q shell && source $rfile && echo sourced $rfile
+
+ echo going for $rfile
+
+ done
+done
+
+[ ! -z $nofileloop ] && source_files $modules
+
+[ -z "$iargs" ] &&
+ echo no include arg, probably something failed &&
+ exit 1
+
+echo iargs - "$iargs" # irags
+echo cur - "$@"
+exit 0
+
+[ -z $stay ] &&
+ (exec nohup $pre$awk $iargs "$@" &) ||
+ while sleep 1
+ do echo "[awkbot] [++] `date`" && $awk $args "$@"
+ done
74 t/awkbot.old
@@ -0,0 +1,74 @@
+#!/bin/sh
+
+# if first arg of the script is -n, it doesnt get forked into the background
+
+[ "$1" == "-n" ] && stay=1 && shift
+[ "$1" == "-m" ] && mod=$2 && shift 2
+[ "$1" == "-p" ] && pre=$2 && shift 2
+
+bins=${pre}{g,}awk
+modules="base_modules xmb_features t/*.load $mod" paths="./,t/,lib/,bin/"
+args=
+#args="-f lib/awkdoc.awk -f lib/mysql.awk -f awkbot.awk"
+export start=1
+export enable_mysql=1 enable_awkdoc=1
+
+function test_var() { echo enable_mysql - $enable_mysql; }
+test_var
+
+for i in `eval echo $bins`
+do
+ which $i &>/dev/null || continue
+ $i -W version 2>&1 | grep -q "GNU Awk [34].[12]" || continue
+
+ export awk=$i
+ break
+done
+
+if [ -z $awk ]
+then
+ echo No suitable gawk found on the system, GNU Awk 3.1 or later needed
+ exit 1
+fi
+
+test_var
+for file in $modules
+do
+ test_var
+ for dir in `eval echo {$paths}`; do
+ export nfile=$dir$file dir
+ [ -f $nfile ] && [ ! -z `eval echo -n \$seen_$nfile` ] || continue
+ test_var
+ #[ ! -f "$file" ] && continue ||
+ #[ -f $nfile ] && f=$f\ $nfile #||
+ f=$f\ $nfile
+ eval seen_$nfile=1
+ #[ -f t/$file ] && f=$f\ t/$file #||
+ #[ -f lib/$file ] && f=$f\ lib/$file #||
+ #[ -f bin/$file ] && f=$f\ bin/$file
+ done
+
+ for rfile in $f
+ do
+ [[ -z "$rfile" ]] && break
+ file -b "$rfile" | grep -q shell && source $rfile && echo sourced $rfile
+
+ echo going for $rfile
+ _x=$(awk -F'[ \t]*:[ \t]*' '/^#*[ \t]*DEP:/ { print $2 } /^[ \t]+#*[ \t]*DEP:/ {
+ #print "1x" $1 "2x" $2 "3x" $3 "4x" $4 >"/dev/stderr";
+ if (ENVIRON[$2]) print $3 }' $f) &&
+ export iargs="$iargs $_x"
+ done
+done
+
+[ -z "$iargs" ] &&
+ echo no include arg, probably something failed &&
+ exit 1
+
+exit 0
+
+[ -z $stay ] &&
+ (exec nohup $pre$awk $iargs "$@" &) ||
+ while sleep 1
+ do echo "[awkbot] [++] `date`" && $awk $args "$@"
+ done
94 t/awkbot.old2
@@ -0,0 +1,94 @@
+#!/bin/sh
+
+# if first arg of the script is -n, it doesnt get forked into the background
+
+[ "$1" == "-n" ] && stay=1 && shift
+[ "$1" == "-m" ] && mod=$2 && shift 2
+[ "$1" == "-p" ] && pre=$2 && shift 2
+
+bins=${pre}{g,}awk
+modules="base_modules xmb_features t/*.load $mod" paths="./,t/,lib/,bin/"
+args=
+#args="-f lib/awkdoc.awk -f lib/mysql.awk -f awkbot.awk"
+export start=1
+#export enable_mysql=1 enable_awkdoc=1
+
+function test_var() { echo enable_mysql - $enable_mysql; }
+test_var
+
+# [prefix=str]
+#function show_files() { for file in $@; do for dir in `eval echo {$paths}'; do
+# export
+
+function source_files() { for file in $@; do for dir in `eval echo {$paths}`; do
+ export nfile=$dir$file dir
+ [ -f $nfile ] || continue
+ file -b $nfile | grep -q shell && source $nfile && echo sourced $nfile
+
+ echo going for $nfile
+ _x=$(awk -F'[ \t]*:[ \t]*' '/^#*[ \t]*DEP:/ { print $2 } /^[ \t]+#*[ \t]*DEP:/ {
+ #print "1x" $1 "2x" $2 "3x" $3 "4x" $4 >"/dev/stderr";
+ if (ENVIRON[$2]) printf "%s ", $3 }' $nfile) &&
+ export iargs="$iargs $_x"
+ done
+ done
+}
+
+for i in `eval echo $bins`
+do
+ which $i &>/dev/null || continue
+ $i -W version 2>&1 | grep -q "GNU Awk [34].[12]" || continue
+
+ export awk=$i
+ break
+done
+
+if [ -z $awk ]
+then
+ echo No suitable gawk found on the system, GNU Awk 3.1 or later needed
+ exit 1
+fi
+
+test_var
+nofileloop=1
+[[ -z $nofileloop ]] && for file in $modules
+do
+ test_var
+ for dir in `eval echo {$paths}`; do
+ export nfile=$dir$file
+ [ -f $nfile ] && [ ! -z `eval echo -n \$seen_$nfile` ] || continue
+ test_var
+ #[ ! -f "$file" ] && continue ||
+ #[ -f $nfile ] && f=$f\ $nfile #||
+ f=$f\ $nfile
+ eval seen_$nfile=1
+ #[ -f t/$file ] && f=$f\ t/$file #||
+ #[ -f lib/$file ] && f=$f\ lib/$file #||
+ #[ -f bin/$file ] && f=$f\ bin/$file
+ done
+
+ for rfile in $f
+ do
+ [[ -z "$rfile" ]] && break
+ file -b "$rfile" | grep -q shell && source $rfile && echo sourced $rfile
+
+ echo going for $rfile
+
+ done
+done
+
+[ ! -z $nofileloop ] && source_files $modules
+
+[ -z "$iargs" ] &&
+ echo no include arg, probably something failed &&
+ exit 1
+
+echo iargs - "$iargs" # irags
+echo cur - "$@"
+exit 0
+
+[ -z $stay ] &&
+ (exec nohup $pre$awk $iargs "$@" &) ||
+ while sleep 1
+ do echo "[awkbot] [++] `date`" && $awk $args "$@"
+ done
13 t/base_modules
@@ -0,0 +1,13 @@
+## base modules /<script>?/
+
+## mysql support
+ # DEP: enable_mysql : -f mysql.awk
+export enable_mysql=1
+
+## awkdoc manual pages
+ # DEP: enable_awkdoc : -f awkdoc.awk
+export enable_awkdoc=1
+
+## AwkB0T
+ # DEP: start : -f awkbot.awk
+export start=1
24 t/irc_test.awk
@@ -0,0 +1,24 @@
+
+BEGIN {
+ irc_set("debug", 1)
+
+# irc_register("initialize")
+ irc_register("connect")
+ irc_register("privmsg")
+
+ irc_set("nickname", "awklibirc")
+ irc_set("realname", "Testing irc.awk")
+ irc_set("username", "tag")
+ irc_connect("irc.freenode.net", "6667")
+}
+
+#function irc_handler_initialize () {
+#}
+
+function irc_handler_connect () {
+ irc_join("#awk")
+}
+
+function irc_handler_privmsg (message,arg) {
+ print message
+}
20 t/queue_test.awk
@@ -0,0 +1,20 @@
+# test queue.awk
+#include <queue.awk>
+
+BEGIN {
+ push(queue, 1)
+ push(queue, 2)
+ push(queue, 3)
+
+ assert((sizeof(queue) == 3), "Sizeof queue" sizeof(queue))
+ assert((pop(queue) == 3), "1")
+ assert((pop(queue) == 2), "2")
+
+
+ unshift(queue, 2)
+ unshift(queue, 3)
+
+ assert((shift(queue) == 3), "3")
+ assert((shift(queue) == 2), "4")
+ assert((shift(queue) == 1), "5")
+}
18 t/test_config.awk
@@ -0,0 +1,18 @@
+# deps: assert.awk awkbot_awkbot_config.awk
+
+BEGIN {
+# awkbot_config["debug"] = 1
+ config_load("t/test_config.conf")
+
+ for (key in _config) {
+ print gensub(SUBSEP, ".", "g", key) ":", awkbot_config[key]
+ }
+
+ assert((config("Test") == 1), "Test failed")
+ assert((config("foo.bar") == 2), "Test failed")
+ assert((config("foo.baz") == 3), "Test failed")
+
+ print "OKAY, Passed tests"
+ print "This is 3:", config("foo.baz")
+ exit (0)
+}
7 t/test_config.conf
@@ -0,0 +1,7 @@
+Test 1
+
+<foo>
+ bar 2
+ baz 3
+</foo>
+
34 t/xmb_test_config.awk
@@ -0,0 +1,34 @@
+# deps: assert.awk awkbot_awkbot_config.awk
+
+BEGIN {
+ if (ARGV[1]) conf = ARGV[1]
+ else conf = "t/test_awkbot_config.conf"
+
+ awkbot_config_load(conf)
+
+ assert((awkbot_config("Test") == 1), "Test failed")
+ assert((awkbot_config("foo.bar") == 2), "Test failed")
+ assert((awkbot_config("foo.baz") == 3), "Test failed")
+
+ print "OKAY, Passed tests"
+ print "This is 3:", awkbot_config("foo.baz")
+ exit (0)
+}
+
+# getline
+function gl(file, null ,t) { getline t < file; if (null) $0 = t; return t }
+function fs(f ,ofs, of) { ofs = FS; FS = "[ \t]*=[ \t]*"; of = $f
+ FS = ofs; return of }
+# split
+function sp(str, Arr, prefix ,A, i) { split(str, A); while (A[++i])
+ if (prefix) Arr[prefix, i] = A[i]; else Arr[A[i]] = i # else: just set true
+ return i }
+
+function awkbot_config_load(file) {
+ gl(file)
+
+ if ($1 ~ /=/) {
+ if ($1 ~ /\[\]$/) { # array,
+ if ($1 ~ /\[\w\]$/) { # 2d array
+
+ awkbot[fs(1)] = fs(2)

0 comments on commit ac4b41f

Please sign in to comment.