Added filter engine, xterm resize.
authorviric@mandarina
Sun, 23 Sep 2007 23:40:36 +0200
changeset 34 7486e269b794
parent 33 010af11f521e
child 35 69dbea6c3882
Added filter engine, xterm resize.
.hgignore
Makefile
filter.c
filter.h
filter.old
filter_string.c
gen_sockets.c
main.c
main.h
simple_math.c
tcp_server.c
test_filter.c
unix_server.c
xterm.c
--- a/.hgignore	Fri Sep 21 16:07:13 2007 +0200
+++ b/.hgignore	Sun Sep 23 23:40:36 2007 +0200
@@ -1,2 +1,2 @@
 .o$
-st
+^tm$
--- a/Makefile	Fri Sep 21 16:07:13 2007 +0200
+++ b/Makefile	Sun Sep 23 23:40:36 2007 +0200
@@ -7,12 +7,17 @@
 	app_term.o \
 	client_term.o \
 	user_term.o \
-	tcp_server.o
+	tcp_server.o \
+	simple_math.o \
+	xterm.o
 
+all: tm test_filter
 
 tm: $(OBJECTS)
 	$(CC) -o $@ -lutil $^
 
+test_filter: test_filter.o filter.o simple_math.o filter_string.o
+
 clean:
 	rm -f $(OBJECTS) stdinmix
 
@@ -29,3 +34,8 @@
 client_term.o: client_term.c main.h
 user_term.o: user_term.c main.h
 tcp_server.o: tcp_server.c main.h handlers.h
+simple_math.o: simple_math.c main.h
+filter.o: filter.c filter.h main.h
+test_filter.o: test_filter.c filter.h
+filter_string.o: filter_string.c filter.h
+xterm.o: xterm.c main.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filter.c	Sun Sep 23 23:40:36 2007 +0200
@@ -0,0 +1,160 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "main.h"
+
+#include "filter.h"
+
+void add_ffilter(struct FilterRules *fr, struct FFilter *ff)
+{
+    fr->nfilters += 1;
+    fr->filters = (struct FFilter **) realloc(fr->filters,
+            sizeof(*fr->filters) * fr->nfilters);
+    if (fr->filters == 0) error("realloc failed.");
+
+    fr->filters[fr->nfilters-1] = ff;
+    ff->matched = 0;
+}
+
+struct FilterRules * new_filter_rules()
+{
+    struct FilterRules *fr;
+    fr = (struct FilterRules *) malloc(sizeof(*fr));
+    if (fr == 0) error("malloc failed.");
+
+    fr->nfilters = 0;
+    fr->filters = 0; /* null for realloc */
+    fr->fbuffer = 0;
+    fr->fbuffer_len = 0;
+    fr->fbuffer_allocated = 0;
+
+    return fr;
+}
+
+/* We want to access index even before the 'buffer' limits.
+ * Those are at fr->fbuffer, and referred as -X indexes. */
+static int get_char(struct FilterRules *fr, const unsigned char *buffer, int pos)
+{
+    if (pos >= 0)
+        return buffer[pos];
+    else
+    {
+        if (-pos > fr->fbuffer_len)
+            return -1;
+        /* pos is negative */
+        return fr->fbuffer[fr->fbuffer_len + pos];
+    }
+}
+
+static int set_char(struct FilterRules *fr, unsigned char *buffer, int pos, int c)
+{
+    if (pos >= 0)
+    {
+        buffer[pos] = c;
+        return buffer[pos];
+    }
+    else
+    {
+        if (-pos > fr->fbuffer_len)
+            return -1;
+        fr->fbuffer[fr->fbuffer_len - pos] = c;
+        return fr->fbuffer[fr->fbuffer_len - pos];
+    }
+}
+
+/* Return 1 if matches */
+static int apply_ffilter(struct FilterRules *fr, struct FFilter *ff,
+        char *obuf, int *olen, const unsigned char *buffer, int pos)
+{
+    int res;
+
+    res = ff->function(ff, buffer[pos]);
+    if (res)
+    {
+        /* String matches */
+        if (ff->callback)
+        {
+            int shift;
+            shift = pos - ff->matched;
+            /* Call callback */
+            ff->callback(fr, ff, obuf, olen, buffer, shift);
+        }
+        return 1;
+    }
+    return 0;
+}
+
+static void reset_matched(struct FilterRules *fr)
+{
+    int i;
+    for (i=0; i < fr->nfilters; ++i)
+    {
+            struct FFilter *ff;
+            ff = fr->filters[i];
+            ff->matched = 0;
+            if (ff->reset)
+                ff->reset(ff);
+    }
+}
+
+void filter_stream(struct FilterRules *fr, char *obuf, int *olen, const char *buffer, int len)
+{
+    int i;
+
+    int ipos;
+    int max_matched;
+
+    *olen = 0;
+    ipos = - fr->fbuffer_len;
+    max_matched = fr->fbuffer_len;
+    for(i=0; i< len; ++i)
+    { /* each char */
+        int j;
+        int old_max_matched = max_matched;
+        int found = 0;
+        max_matched = 0;
+        /*printf("Try '%c'...\n", buffer[i]);*/
+        for (j=0; j < fr->nfilters; ++j)
+        {
+            struct FFilter *ff;
+            ff = fr->filters[j];
+            found = apply_ffilter(fr, ff, obuf, olen, buffer, i);
+            max_matched = max(max_matched, ff->matched);
+            if (found)
+                break;
+        }
+        /* Some chars may not be needed for the filters
+         * already. */
+        /*printf("ipos: %i\n", ipos);*/
+        if (found)
+        {
+            /*printf("[match!]\n");*/
+            reset_matched(fr);
+            /* The longest string will be matched, sure. Right?*/
+            ipos += max_matched;
+            max_matched = 0;
+        }
+        else
+        {
+            int freed = old_max_matched + 1 /* new char */ - max_matched;
+            for(j=0; j < freed; ++j)
+            {
+                obuf[(*olen)++] = get_char(fr, buffer, ipos++);
+            }
+        }
+    }
+    if (max_matched > fr->fbuffer_allocated)
+    {
+        fr->fbuffer = realloc(fr->fbuffer, max_matched);
+        if (fr->fbuffer == 0) error("Cannot allocate fbuffer");
+    }
+    memcpy(fr->fbuffer, buffer + len - max_matched, max_matched);
+    fr->fbuffer_len = max_matched;
+}
+
+void filter_flush(struct FilterRules *fr, char *obuf, int *olen)
+{
+    memcpy(obuf, fr->fbuffer, fr->fbuffer_len);
+    *olen = fr->fbuffer_len;
+    fr->fbuffer_len = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filter.h	Sun Sep 23 23:40:36 2007 +0200
@@ -0,0 +1,35 @@
+struct FilterRules;
+struct FFilter;
+
+typedef void (*Fcallback)(struct FilterRules *fr, const struct FFilter *ff,
+        char *obuf, int *olen, const char *ibuf, int pos);
+
+/* TRUE if match */
+typedef int (*Ffunction)(struct FFilter *ff, unsigned char c);
+
+typedef void (*Freset)(struct FFilter *ff);
+
+struct FFilter {
+    /* Static */
+    Ffunction function;
+    Freset reset;
+    Fcallback callback;
+
+    int matched;
+};
+
+struct FilterRules {
+    int nfilters;
+    struct FFilter **filters;
+    unsigned char *fbuffer;
+    int fbuffer_len;
+    int fbuffer_allocated;
+};
+
+void add_ffilter(struct FilterRules *fr, struct FFilter *ff);
+struct FilterRules * new_filter_rules();
+void filter_stream(struct FilterRules *fr, char *obuf, int *olen, const char *buffer, int len);
+void filter_flush(struct FilterRules *fr, char *obuf, int *olen);
+
+/* filter_string.c */
+struct FFilter *new_fstring(char *p);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filter.old	Sun Sep 23 23:40:36 2007 +0200
@@ -0,0 +1,190 @@
+#include <stdlib.h>
+#include <string.h>
+#include "main.h"
+
+#include "filter.h"
+
+static struct FString new_fstring()
+{
+    fs->p = p;
+    fs->len = len;
+    fs->actual_pos = 0;
+    fs->next_try = (int *) malloc(
+            sizeof(*fs->next_try) * len);
+}
+
+static void prepare_next_try(char *str, int len, int *next_try)
+{
+    int s; /* skip */
+
+    /* at x = next_try[s], it means how many x characters
+     * have we matched, if we have matched (s+1)? */
+    next_try[0] = 0; /* not used */
+    for (s = 2; s <= len; ++s)
+    {
+        int i;
+        /* compare [0..s-1] to [len - s, len-1] */
+        /* strlen(cmp) = s */
+        /* String compare, exit when not equal, offset in 'i' */
+        for(i=0; i < s; ++i)
+            if (str[len-s-i] != str[i])
+                break;
+        next_try[s-1] = i;
+    }
+}
+
+void add_fstring(struct FilterRules *fr, char *p, int len, Fcallback cb)
+{
+    struct FString *fs;
+    fr->nstrings += 1;
+    fr->strings = (struct FString **) realloc(fr->strings,
+            sizeof(*fr->strings) * fr->nstrings);
+    if (fr->strings == 0) error("realloc failed.");
+
+    /* Fill the last created space */
+    fs = (struct FString *) malloc(sizeof(*fs));
+    fr->strings[fr->nstrings-1] = fs;
+    if (fs == 0) error("malloc failed.");
+
+    new_fstring(fs, p, len);
+
+    /* Prepare the next_try array */
+    prepare_next_try(p, len, fs->next_try);
+
+    fs->callback = cb;
+
+    /* We will keep the fbuffers allocated for the longest
+     * string possible */
+    if (len > fr->fbuffer_allocated)
+    {
+        fr->fbuffer_allocated = len;
+        fr->fbuffer = realloc(fr->fbuffer, len);
+    }
+}
+
+struct FilterRules * new_filter_rules()
+{
+    struct FilterRules *fr;
+    fr = (struct FilterRules *) malloc(sizeof(*fr));
+    if (fr == 0) error("malloc failed.");
+
+    fr->nstrings = 0;
+    fr->strings = 0; /* null for realloc */
+    fr->fbuffer = 0;
+    fr->fbuffer_len = 0;
+    fr->fbuffer_allocated = 0;
+
+    return fr;
+}
+
+/* We want to access index even before the 'buffer' limits.
+ * Those are at fr->fbuffer, and referred as -X indexes. */
+static int get_char(struct FilterRules *fr, const unsigned char *buffer, int pos)
+{
+    if (pos >= 0)
+        return buffer[pos];
+    else
+    {
+        if (-pos > fr->fbuffer_len)
+            return -1;
+        return fr->fbuffer[fr->fbuffer_len - pos];
+    }
+}
+
+static int set_char(struct FilterRules *fr, unsigned char *buffer, int pos, int c)
+{
+    if (pos >= 0)
+    {
+        buffer[pos] = c;
+        return buffer[pos];
+    }
+    else
+    {
+        if (-pos > fr->fbuffer_len)
+            return -1;
+        fr->fbuffer[fr->fbuffer_len - pos] = c;
+        return fr->fbuffer[fr->fbuffer_len - pos];
+    }
+}
+
+/* Return 1 if matches */
+static int filter_string(struct FilterRules *fr, struct FString *fs,
+        char *obuf, int *olen, const unsigned char *buffer, int pos)
+{
+    while (fs->actual_pos > 0 && fs->p[fs->actual_pos] != buffer[pos])
+    {
+        /* next_try maps 1..len to 0..len-1 */
+        fs->actual_pos = fs->next_try[fs->actual_pos-1];
+    }
+    if (fs->p[fs->actual_pos] == buffer[pos])
+        fs->actual_pos += 1;
+    if (fs->actual_pos == fs->len)
+    {
+        /* String matches */
+        int shift;
+        shift = pos - fs->len;
+        /* Call callback */
+        fs->callback(fr, fs, obuf, olen, buffer, shift);
+        return 1;
+    }
+    return 0;
+}
+
+static void reset_actual_pos(struct FilterRules *fr)
+{
+    int i;
+    for (i=0; i < fr->nstrings; ++i)
+    {
+            struct FString *fs;
+            fs = fr->strings[i];
+            fs->actual_pos = 0;
+    }
+}
+
+void filter_stream(struct FilterRules *fr, char *obuf, int *olen, const char *buffer, int len)
+{
+    int i;
+
+    int ipos;
+
+    *olen = 0;
+    ipos = - fr->fbuffer_len;
+    for(i=0; i< len; ++i)
+    { /* each char */
+        int j;
+        int old_maxlen = fr->maxlen_found;
+        int found;
+        fr->maxlen_found = 0;
+        for (j=0; j < fr->nstrings; ++j)
+        {
+            struct FString *fs;
+            fs = fr->strings[j];
+            found = filter_string(fr, fs, obuf, olen, buffer, i);
+            if (found)
+                break;
+            fr->maxlen_found = max(fr->maxlen_found, fs->actual_pos);
+        }
+        /* Some chars may not be needed for the filters
+         * already. */
+        if (found)
+        {
+            reset_actual_pos(fr);
+        }
+        else
+        {
+            for(j=0; j < old_maxlen + 1 - fr->maxlen_found; ++j)
+            {
+                obuf[(*olen)++] = get_char(fr, buffer, ipos++);
+            }
+        }
+    }
+    memcpy(fr->fbuffer, buffer + len - fr->maxlen_found, fr->maxlen_found);
+    fr->fbuffer_len = fr->maxlen_found;
+}
+
+void filter_flush(struct FilterRules *fr, char *obuf, int *olen)
+{
+    memcpy(obuf, fr->fbuffer, fr->fbuffer_len);
+    *olen = fr->fbuffer_len;
+    fr->fbuffer_len = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filter_string.c	Sun Sep 23 23:40:36 2007 +0200
@@ -0,0 +1,45 @@
+#include <stdlib.h>
+#include <string.h>
+#include "filter.h"
+
+struct FString
+{
+    struct FFilter base;
+    unsigned char *p;
+    int len;
+};
+
+static void fstring_reset(struct FFilter *ff)
+{
+    ff->matched = 0;
+}
+
+static int fstring_function(struct FFilter *ff, unsigned char c)
+{
+    struct FString *fs = (struct FString *) ff;
+
+    if (fs->p[fs->base.matched] == c)
+        fs->base.matched++;
+    else
+        /* A SAC */
+        fs->base.matched = 0;
+
+    if (fs->base.matched == fs->len)
+        return 1;
+    return 0;
+}
+
+struct FFilter *new_fstring(char *p)
+{
+    struct FString *fs;
+    fs = (struct FString *) malloc(sizeof(*fs));
+
+    fs->p = strdup(p);
+    fs->len = strlen(p);
+    fs->base.matched = 0;
+    fs->base.function = fstring_function;
+    fs->base.reset = fstring_reset;
+    fs->base.callback = 0;
+
+    return (struct FFilter *) fs;
+}
--- a/gen_sockets.c	Fri Sep 21 16:07:13 2007 +0200
+++ b/gen_sockets.c	Sun Sep 23 23:40:36 2007 +0200
@@ -4,14 +4,18 @@
 #include "main.h"
 
 char *stream_buffer = 0;
+char *ostream_buffer = 0;
 int stream_buffer_size;
+int ostream_buffer_size;
 
-void init_stream_buffer()
+void init_stream_buffers()
 {
     if (stream_buffer == 0)
     {
         assert(command_line.buffer_size > 0);
         stream_buffer_size = command_line.buffer_size;
+        ostream_buffer_size = command_line.buffer_size;
         stream_buffer = (char *) malloc(stream_buffer_size);
+        ostream_buffer = (char *) malloc(ostream_buffer_size);
     }
 }
--- a/main.c	Fri Sep 21 16:07:13 2007 +0200
+++ b/main.c	Sun Sep 23 23:40:36 2007 +0200
@@ -27,13 +27,6 @@
 
 static const char version[] = "0.1";
 
-int max(int a, int b)
-{
-    if (a > b)
-        return a;
-    return b;
-}
-
 static int showhelp(const char *pname)
 {
     printf("tm v%s - terminal mixer,  Copyright (C) 2007  "
@@ -170,7 +163,7 @@
 
     default_command_line();
     parse_opts(argc, argv);
-    init_stream_buffer();
+    init_stream_buffers();
 
     if (command_line.is_server)
         res = server();
--- a/main.h	Fri Sep 21 16:07:13 2007 +0200
+++ b/main.h	Sun Sep 23 23:40:36 2007 +0200
@@ -49,7 +49,9 @@
 /* gen_sockets.c */
 extern char *stream_buffer;
 extern int stream_buffer_size;
-void init_stream_buffer();
+extern char *ostream_buffer;
+extern int ostream_buffer_size;
+void init_stream_buffers();
 
 /* server.c */
 int server();
@@ -63,3 +65,6 @@
 /* server_term.c */
 void prepare_user_terminal();
 void restore_user_terminal();
+
+/* xterm.h */
+char * get_xterm_resize_string();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple_math.c	Sun Sep 23 23:40:36 2007 +0200
@@ -0,0 +1,8 @@
+#include "main.h"
+
+int max(int a, int b)
+{
+    if (a > b)
+        return a;
+    return b;
+}
--- a/tcp_server.c	Fri Sep 21 16:07:13 2007 +0200
+++ b/tcp_server.c	Sun Sep 23 23:40:36 2007 +0200
@@ -3,6 +3,7 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <netinet/in.h>
+#include <string.h>
 #include <sys/socket.h>
 #include <sys/select.h>
 
@@ -158,6 +159,13 @@
         {
             conn_sockets[connected_sockets++] =
                 accept_connection(listen_socket);
+            if (command_line.s_param.run_in_subterminal)
+            {
+                char *xterm_str;
+                xterm_str = get_xterm_resize_string();
+                send(conn_sockets[connected_sockets-1],
+                        xterm_str, strlen(xterm_str), 0);
+            }
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test_filter.c	Sun Sep 23 23:40:36 2007 +0200
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <string.h>
+
+#include "filter.h"
+
+char base[] = "El val dilluns vaig provar el tatami d'en valeri\n";
+
+int main()
+{
+    int i;
+    char obuf[sizeof base];
+    struct FilterRules *fr;
+    struct FFilter *ff;
+    fr = new_filter_rules();
+
+    ff = new_fstring("val");
+    add_ffilter(fr, ff);
+    ff = new_fstring("tatami");
+    add_ffilter(fr, ff);
+
+    for(i=1; i < sizeof(base)-1; ++i)
+    {
+        int olen;
+        printf("test %i:\n", i);
+        if (i == 17)
+            olen=0;
+        filter_stream(fr, obuf, &olen, base, i);
+        filter_stream(fr, obuf + olen, &olen, base + i, sizeof(base) - i);
+        filter_flush(fr, obuf + olen, &olen);
+        printf("%s", obuf);
+    }
+
+    {
+        int olen = 0;
+        printf("test po litere:\n");
+        for(i=0; i < sizeof(base); ++i)
+        {
+            int tlen;
+            filter_stream(fr, obuf + olen, &tlen, base + i, 1);
+            olen += tlen;
+        }
+        filter_flush(fr, obuf + olen, &olen);
+        printf("%s", obuf);
+    }
+
+    return 0;
+}
--- a/unix_server.c	Fri Sep 21 16:07:13 2007 +0200
+++ b/unix_server.c	Sun Sep 23 23:40:36 2007 +0200
@@ -191,6 +191,13 @@
         {
             conn_sockets[connected_sockets++] =
                 accept_connection(listen_socket);
+            if (command_line.s_param.run_in_subterminal)
+            {
+                char *xterm_str;
+                xterm_str = get_xterm_resize_string();
+                send(conn_sockets[connected_sockets-1],
+                        xterm_str, strlen(xterm_str), 0);
+            }
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xterm.c	Sun Sep 23 23:40:36 2007 +0200
@@ -0,0 +1,23 @@
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include "main.h"
+
+static char xterm_resize_string[100];
+
+char * get_xterm_resize_string()
+{
+    struct winsize win;
+    int rows, cols;
+
+    /* Get rows and cols from our connection to the terminal: fd 1 */
+    ioctl(1, TIOCGWINSZ, (char *)&win);
+    rows = win.ws_row;
+    cols = win.ws_col;
+
+    /* Prepare the xterm resize string */
+    snprintf(xterm_resize_string, 100, "\033[8;%i;%it", rows, cols);
+
+    return xterm_resize_string;
+}