]> Pileus Git - ~andy/rhawk/commitdiff
Add select
authorAndy Spencer <andy753421@gmail.com>
Tue, 24 Jan 2012 09:51:40 +0000 (09:51 +0000)
committerAndy Spencer <andy753421@gmail.com>
Tue, 24 Jan 2012 09:51:40 +0000 (09:51 +0000)
.gitignore
mkfile
select.awk [new file with mode: 0644]
select.c [new file with mode: 0644]
testirc.lib [new file with mode: 0644]

index b72f9be2042aa06db9cb3a6f533f953b5ce29901..5251d1c0b729327dd667aef051a6fb88f12654ab 100644 (file)
@@ -1,2 +1,5 @@
 *~
 *.swp
+*.so
+*.o
+config.h
diff --git a/mkfile b/mkfile
index 4f52cb26d22832df549d10183f350a495e3423c4..138af83407c7495e14045256b834d05fbaa3c30a 100644 (file)
--- a/mkfile
+++ b/mkfile
@@ -1,4 +1,14 @@
-test:Q:
-       awk -f rhawk < testirc.txt
+CFLAGS   = -g -Wall -fPIC --std=c99
+CPPFLAGS = -I/usr/include/awk -I. -DHAVE_CONFIG_H
+
+test:Q: select.so
+       awk -f select.awk
+       #awk -f rhawk < testirc.txt
        #awk -f rhawk < testirc.txt
        #awk -f test.awk test.txt | awk -f rhawk #| grep 'points\|bid\|took'
+
+%.so: %.o
+       gcc $CFLAGS -shared -o $target $prereq $LDFLAGS
+
+%.o: %.c
+       gcc $CPPFLAGS $CFLAGS -c -o $target $prereq
diff --git a/select.awk b/select.awk
new file mode 100644 (file)
index 0000000..5b45a7a
--- /dev/null
@@ -0,0 +1,33 @@
+BEGIN {
+       extension("./select.so", "dlload");
+
+       nc0   = "netcat -l -p 12345"
+       nc1   = "netcat -l -p 54321"
+       stdin = "/dev/stdin"
+
+       while (1) {
+               # Open pipes
+               printf "" |& nc0
+               printf "" |& nc1
+
+               # Wait for input 
+               if (!(fd = select("from", stdin, nc0, nc1))) {
+                       print "timeout"
+                       continue
+               }
+
+               # Read a line
+               if (fd == stdin)
+                       if (!(st = getline line < fd))
+                               exit 0
+               if (fd == nc0 || fd == nc1)
+                       if (!(st = fd |& getline line)) {
+                               print "broken pipe"
+                               close(fd)
+                               continue
+                       }
+
+               # Print output
+               print "line: [" fd "] -> [" line "]"
+       }
+}
diff --git a/select.c b/select.c
new file mode 100644 (file)
index 0000000..d379167
--- /dev/null
+++ b/select.c
@@ -0,0 +1,149 @@
+/*
+ * select.c - Provide select functions for gawk.
+ */
+
+/*
+ * Copyright (C) 2012 Andy Spencer
+ *
+ * GAWK 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GAWK 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#include "awk.h"
+
+int plugin_is_GPL_compatible;
+
+/* Select function:
+ *   select(how, [timeout,] fd, ..)
+ *   type = {to,from,error,any} */
+static NODE *do_select(int nargs)
+{
+       /* Parse arguments */
+       if (do_lint && get_curfunc_arg_count() < 2)
+               lintwarn("select: not enough arguments");
+
+       /* - check how */
+       int read = 0, write = 0, except = 0;
+       NODE *node = get_scalar_argument(0, FALSE);
+       NODE *how  = force_string(node);
+       if (!strcmp("to",    how->stptr)) write  = 1;
+       if (!strcmp("from",  how->stptr)) read   = 1;
+       if (!strcmp("error", how->stptr)) except = 1;
+       if (!strcmp("any",   how->stptr)) read = write = except = 1;
+       if (!read && !write && !except) {
+               printf("select: invalid select type: %.*s\n",
+                               how->stlen, how->stptr);
+               return make_number((AWKNUM) -EINVAL);
+       }
+
+       /* - check timeout */
+       int    first = 1;
+       struct timeval _timeout = {.tv_sec = 1, .tv_usec = 0};
+       struct timeval *timeout = &_timeout;
+       NODE *next = get_scalar_argument(1, FALSE);
+       if (next->type == Node_val && next->flags & NUMBER) {
+               AWKNUM num = force_number(next);
+               if (num < 0) {
+                       timeout  = NULL;
+               } else {
+                       _timeout.tv_sec  = (int)num;
+                       _timeout.tv_usec = (num - (int)num) * 1E6;
+                       printf("timeout -> %lf %ld,%ld\n", num,
+                                       _timeout.tv_sec,
+                                       _timeout.tv_usec);
+               }
+               first = 2;
+       }
+
+       /* Clear fds */
+       int nfds = 0;
+       fd_set readfds, writefds, exceptfds;
+       FD_ZERO(&readfds);
+       FD_ZERO(&writefds);
+       FD_ZERO(&exceptfds);
+
+       /* Set fds */
+       for (int i = first; i < nargs; i++) {
+               NODE *node = get_scalar_argument(i, TRUE);
+               if (node == NULL)
+                       continue;
+               NODE *str  = force_string(node);
+               struct redirect *redir =
+                       getredirect(str->stptr, str->stlen);
+               if (redir == NULL) {
+                       int err = 0;
+                       int type = read && write ? redirect_twoway :
+                                  read          ? redirect_input  :
+                                  write         ? redirect_output : 0 ;
+                       redir = redirect(str, type, &err);
+               }
+               if (redir == NULL) {
+                       lintwarn("select: arg %d is not a redirect", i);
+                       continue;
+               }
+               if ((read  || except) && redir->iop->fd >= 0) {
+                       int fd = redir->iop->fd;
+                       if (read)      FD_SET(fd, &readfds);
+                       if (except)    FD_SET(fd, &exceptfds);
+                       if (fd > nfds) nfds = fd;
+               }
+               if ((write || except) && redir->fp) {
+                       int fd = fileno(redir->fp);
+                       if (write)     FD_SET(fd, &writefds);
+                       if (except)    FD_SET(fd, &exceptfds);
+                       if (fd > nfds) nfds = fd;
+               }
+       }
+
+       /* Select fds */
+       int rval = select(nfds+1, &readfds, &writefds, &exceptfds, timeout);
+       if (rval == 0)
+               return make_number((AWKNUM) 0);
+       if (rval == -1)
+               return make_number((AWKNUM) 0);
+
+       /* Return */
+       for (int i = first; i < nargs; i++) {
+               NODE *node = get_scalar_argument(i, TRUE);
+               if (node == NULL)
+                       continue;
+               NODE *str  = force_string(node);
+               struct redirect *redir =
+                       getredirect(str->stptr, str->stlen);
+               if (redir == NULL)
+                       continue;
+               if ((read  || except) && redir->iop->fd >= 0) {
+                       int fd = redir->iop->fd;
+                       if ((read   && FD_ISSET(fd, &readfds))  ||
+                           (except && FD_ISSET(fd, &writefds)))
+                               return node;
+               }
+               if ((write || except) && redir->fp) {
+                       int fd = fileno(redir->fp);
+                       if ((write  && FD_ISSET(fd, &writefds)) ||
+                           (except && FD_ISSET(fd, &exceptfds)))
+                               return node;
+               }
+       }
+
+       /* Error */
+       return make_number((AWKNUM) 0);
+}
+
+/* Load select function */
+NODE *dlload(NODE *tree, void *dl)
+{
+       make_builtin("select", do_select, 99);
+       return make_number((AWKNUM) 0);
+}
diff --git a/testirc.lib b/testirc.lib
new file mode 100644 (file)
index 0000000..c215010
--- /dev/null
@@ -0,0 +1,10 @@
+:andy753421!~a@c.d TOPIC #sfvlug :San Fernando Valley Linux Users Group | Meeting: Sat January 21, 6:00pm Denny's Van Nuys | Website: www.sfvlug.org & Wiki: http://tinyurl.com/tabrr & Meetup: http://meetup.com/sfvlug | Knowledge is power. http://tinyurl.com/2xr7sd
+:andy753421!~a@c.d PRIVMSG #sfvlug :.poll
+PING :hitchcock.freenode.net
+:hitchcock.freenode.net PONG hitch
+:andy753421!~andy@rhlug/a PRIVMSG #rhnoise :hm...
+:andy753421!~andy@rhlug/a PRIVMSG #rhnoise :gah, bloody oddly formatted commands
+:rhawk!~andy@76-219-180-192.lightspeed.irvnca.sbcglobal.net JOIN #rhnoise
+:hitchcock.freenode.net 332 rhawk #rhnoise :<beausoleil> ooh, an occupy austin mariachi is going on outside
+:andy753421!~andy@rhlug/a KICK #rhnoise beausoleil :beausoleil
+:hitchcock.freenode.net 332 rhawk #rhnoise :<beausoleil> ooh, an occupy austin mariachi is going on outside