diff --git a/common/utils/T/tracer/Makefile.remote b/common/utils/T/tracer/Makefile.remote index 08b79f2aa1645206977accfaff1920f2ad0b185d..3eadcc27daa5e3d32f192a1ae3d6d649063efe33 100644 --- a/common/utils/T/tracer/Makefile.remote +++ b/common/utils/T/tracer/Makefile.remote @@ -11,17 +11,20 @@ OBJS=remote_old.o plot.o database.o gui.o utils.o $(PROG): gui/gui.a $(OBJS) $(CC) $(CFLAGS) -o $(PROG) $(OBJS) gui/gui.a $(LIBS) -textlog: utils.o remote.o database.o event.o handler.o textlog.o \ - event_selector.o view/view.a gui/gui.a +textlog: utils.o textlog.o database.o event.o handler.o \ + event_selector.o view/view.a gui/gui.a logger/logger.a $(CC) $(CFLAGS) -o textlog $^ $(LIBS) -.PHONY: gui/gui.a view/view.a +.PHONY: gui/gui.a view/view.a logger/logger.a + +gui/gui.a: + cd gui && make view/view.a: cd view && make -gui/gui.a: - cd gui && make +logger/logger.a: + cd logger && make %.o: %.c $(CC) $(CFLAGS) -c -o $@ $< @@ -30,3 +33,4 @@ clean: rm -f *.o $(PROG) core textlog cd gui && make clean cd view && make clean + cd logger && make clean diff --git a/common/utils/T/tracer/logger/Makefile b/common/utils/T/tracer/logger/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1b4c3b1d28fcefc91744d4a73bfd37053fd69659 --- /dev/null +++ b/common/utils/T/tracer/logger/Makefile @@ -0,0 +1,13 @@ +CC=gcc +CFLAGS=-Wall -g -pthread -I.. + +OBJS=textlog.o + +logger.a: $(OBJS) + ar cr logger.a $(OBJS) + +%.o: %.c + $(CC) $(CFLAGS) -o $@ -c $< + +clean: + rm -f *.a *.o diff --git a/common/utils/T/tracer/logger/textlog.c b/common/utils/T/tracer/logger/textlog.c new file mode 100644 index 0000000000000000000000000000000000000000..264068c61798d78fb260615f349f8ad60e387eaa --- /dev/null +++ b/common/utils/T/tracer/logger/textlog.c @@ -0,0 +1,189 @@ +#include "textlog.h" +#include "handler.h" +#include "database.h" +#include "view/view.h" +#include "utils.h" +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +enum format_item_type { + INSTRING, + INT, STRING, BUFFER }; + +struct format_item { + enum format_item_type type; + union { + /* INSTRING */ + char *s; + /* others */ + int event_arg; + }; +}; + +struct textlog { + char *event_name; + char *format; + void *database; + unsigned long handler_id; + /* parsed format string */ + struct format_item *f; + int fsize; + /* list of views */ + view **v; + int vsize; + /* local output buffer */ + OBUF o; +}; + +static void _event(void *p, event e) +{ + struct textlog *l = p; + int i; + + l->o.osize = 0; + + for (i = 0; i < l->fsize; i++) + switch(l->f[i].type) { + case INSTRING: PUTS(&l->o, l->f[i].s); break; + case INT: PUTI(&l->o, e.e[l->f[i].event_arg].i); break; + case STRING: PUTS_CLEAN(&l->o, e.e[l->f[i].event_arg].s); break; + case BUFFER: + PUTS(&l->o, "{buffer size:"); + PUTI(&l->o, e.e[l->f[i].event_arg].bsize); + PUTS(&l->o, "}"); + break; + } + PUTC(&l->o, 0); + + for (i = 0; i < l->vsize; i++) l->v[i]->append(l->v[i], l->o.obuf); +} + +enum chunk_type { C_ERROR, C_STRING, C_ARG_NAME, C_EVENT_NAME }; +struct chunk { + enum chunk_type type; + char *s; + enum format_item_type it; + int event_arg; +}; + +/* TODO: speed it up? */ +static int find_argument(char *name, database_event_format f, + enum format_item_type *it, int *event_arg) +{ + int i; + for (i = 0; i < f.count; i++) if (!strcmp(name, f.name[i])) break; + if (i == f.count) return 0; + *event_arg = i; + if (!strcmp(f.type[i], "int")) *it = INT; + else if (!strcmp(f.type[i], "string")) *it = STRING; + else if (!strcmp(f.type[i], "buffer")) *it = BUFFER; + else return 0; + return 1; +} + +static struct chunk next_chunk(char **s, database_event_format f) +{ + char *cur = *s; + char *name; + enum format_item_type it; + int event_arg; + + /* argument in [ ] */ + if (*cur == '[') { + *cur = 0; + cur++; + name = cur; + /* no \ allowed there */ + while (*cur && *cur != ']' && *cur != '\\') cur++; + if (*cur != ']') goto error; + *cur = 0; + cur++; + *s = cur; + if (find_argument(name, f, &it, &event_arg) == 0) goto error; + return (struct chunk){type:C_ARG_NAME, s:name, it:it, event_arg:event_arg}; + } + + /* { } is name of event (anything in between is smashed) */ + if (*cur == '{') { + *cur = 0; + cur++; + while (*cur && *cur != '}') cur++; + if (*cur != '}') goto error; + *cur = 0; + cur++; + *s = cur; + return (struct chunk){type:C_EVENT_NAME}; + } + + /* anything but [ and { is raw string */ + /* TODO: deal with \ */ + name = cur; + while (*cur && *cur != '[' && *cur != '{') cur++; + *s = cur; + return (struct chunk){type:C_STRING, s:name}; + +error: + return (struct chunk){type:C_ERROR}; +} + +textlog *new_textlog(event_handler *h, void *database, + char *event_name, char *format) +{ + struct textlog *ret; + int event_id; + database_event_format f; + char *cur; + + ret = calloc(1, sizeof(struct textlog)); if (ret == NULL) abort(); + + ret->event_name = strdup(event_name); if (ret->event_name == NULL) abort(); + ret->format = strdup(format); if (ret->format == NULL) abort(); + ret->database = database; + + event_id = event_id_from_name(database, event_name); + + ret->handler_id = register_handler_function(h, event_id, _event, ret); + + f = get_format(database, event_id); + + /* we won't get more than strlen(format) "chunks" */ + ret->f = malloc(sizeof(struct format_item) * strlen(format)); + if (ret->f == NULL) abort(); + + cur = ret->format; + + while (*cur) { + struct chunk c = next_chunk(&cur, f); + switch (c.type) { + case C_ERROR: goto error; + case C_STRING: + ret->f[ret->fsize].type = INSTRING; + ret->f[ret->fsize].s = c.s; + break; + case C_ARG_NAME: + ret->f[ret->fsize].type = c.it; + ret->f[ret->fsize].event_arg = c.event_arg; + break; + case C_EVENT_NAME: + ret->f[ret->fsize].type = INSTRING; + ret->f[ret->fsize].s = ret->event_name; + break; + } + ret->fsize++; + } + + return ret; + +error: + printf("%s:%d: bad format '%s'\n", __FILE__, __LINE__, format); + abort(); +} + +void textlog_add_view(textlog *_l, view *v) +{ + struct textlog *l = _l; + l->vsize++; + l->v = realloc(l->v, l->vsize * sizeof(view *)); if (l->v == NULL) abort(); + l->v[l->vsize-1] = v; +} diff --git a/common/utils/T/tracer/textlog.h b/common/utils/T/tracer/logger/textlog.h similarity index 100% rename from common/utils/T/tracer/textlog.h rename to common/utils/T/tracer/logger/textlog.h diff --git a/common/utils/T/tracer/remote.c b/common/utils/T/tracer/remote.c deleted file mode 100644 index 2ef9e5bc28c518cc63ab1c23f17a56e632fe9be7..0000000000000000000000000000000000000000 --- a/common/utils/T/tracer/remote.c +++ /dev/null @@ -1,220 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <unistd.h> -#include "database.h" -#include "event.h" -#include "handler.h" -#include "textlog.h" -#include "view/view.h" -#include "gui/gui.h" -#include "utils.h" -#include "../T_defs.h" -#include "event_selector.h" - -#define DEFAULT_REMOTE_PORT 2021 - -int get_connection(char *addr, int port) -{ - struct sockaddr_in a; - socklen_t alen; - int s, t; - - printf("waiting for connection on %s:%d\n", addr, port); - - s = socket(AF_INET, SOCK_STREAM, 0); - if (s == -1) { perror("socket"); exit(1); } - t = 1; - if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(int))) - { perror("setsockopt"); exit(1); } - - a.sin_family = AF_INET; - a.sin_port = htons(port); - a.sin_addr.s_addr = inet_addr(addr); - - if (bind(s, (struct sockaddr *)&a, sizeof(a))) { perror("bind"); exit(1); } - if (listen(s, 5)) { perror("bind"); exit(1); } - alen = sizeof(a); - t = accept(s, (struct sockaddr *)&a, &alen); - if (t == -1) { perror("accept"); exit(1); } - close(s); - - printf("connected\n"); - - return t; -} - -void usage(void) -{ - printf( -"options:\n" -" -d <database file> this option is mandatory\n" -" -on <GROUP or ID> turn log ON for given GROUP or ID\n" -" -off <GROUP or ID> turn log OFF for given GROUP or ID\n" -" -ON turn all logs ON\n" -" -OFF turn all logs OFF\n" -" note: you may pass several -on/-off/-ON/-OFF,\n" -" they will be processed in order\n" -" by default, all is off\n" -" -p <port> use given port (default %d)\n" -" -x GUI output\n" -" -debug-gui activate GUI debug logs\n" -" -no-gui disable GUI entirely\n", - DEFAULT_REMOTE_PORT - ); - exit(1); -} - -int fullread(int fd, void *_buf, int count) -{ - char *buf = _buf; - int ret = 0; - int l; - while (count) { - l = read(fd, buf, count); - if (l <= 0) { printf("read socket problem\n"); abort(); } - count -= l; - buf += l; - ret += l; - } - return ret; -} - -event get_event(int s, char *v, void *d) -{ - int type; - int32_t length; - - fullread(s, &length, 4); - fullread(s, &type, sizeof(int)); - length -= sizeof(int); - fullread(s, v, length); - - return new_event(type, length, v, d); -} - -static void *gui_thread(void *_g) -{ - gui *g = _g; - gui_loop(g); - return NULL; -} - -int main(int n, char **v) -{ - extern int volatile gui_logd; - char *database_filename = NULL; - void *database; - int port = DEFAULT_REMOTE_PORT; - char **on_off_name; - int *on_off_action; - int on_off_n = 0; - int *is_on; - int number_of_events; - int s; - int i; - char t; - int l; - event_handler *h; - textlog *textlog; - gui *g; - int gui_mode = 0; - view *out; - int gui_active = 1; - - on_off_name = malloc(n * sizeof(char *)); if (on_off_name == NULL) abort(); - on_off_action = malloc(n * sizeof(int)); if (on_off_action == NULL) abort(); - - for (i = 1; i < n; i++) { - if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage(); - if (!strcmp(v[i], "-d")) - { if (i > n-2) usage(); database_filename = v[++i]; continue; } - if (!strcmp(v[i], "-p")) - { if (i > n-2) usage(); port = atoi(v[++i]); continue; } - if (!strcmp(v[i], "-on")) { if (i > n-2) usage(); - on_off_name[on_off_n]=v[++i]; on_off_action[on_off_n++]=1; continue; } - if (!strcmp(v[i], "-off")) { if (i > n-2) usage(); - on_off_name[on_off_n]=v[++i]; on_off_action[on_off_n++]=0; continue; } - if (!strcmp(v[i], "-ON")) - { on_off_name[on_off_n]=NULL; on_off_action[on_off_n++]=1; continue; } - if (!strcmp(v[i], "-OFF")) - { on_off_name[on_off_n]=NULL; on_off_action[on_off_n++]=0; continue; } - if (!strcmp(v[i], "-x")) { gui_mode = 1; continue; } - if (!strcmp(v[i], "-debug-gui")) { gui_logd = 1; continue; } - if (!strcmp(v[i], "-no-gui")) { gui_active = 0; continue; } - usage(); - } - - if (gui_active == 0) gui_mode = 0; - - if (database_filename == NULL) { - printf("ERROR: provide a database file (-d)\n"); - exit(1); - } - - database = parse_database(database_filename); - - number_of_events = number_of_ids(database); - is_on = calloc(number_of_events, sizeof(int)); - if (is_on == NULL) abort(); - - h = new_handler(database); - - if (gui_active) { - g = gui_init(); - new_thread(gui_thread, g); - } - - if (gui_mode) { - widget *w, *win; -// w = new_textlist(g, 600, 20, 0); - w = new_textlist(g, 800, 50, BACKGROUND_COLOR); - win = new_toplevel_window(g, 800, 50*12, "textlog"); - widget_add_child(g, win, w, -1); - out = new_view_textlist(1000, 10, g, w); - //tout = new_view_textlist(7, 4, g, w); - } else { - out = new_view_stdout(); - } - - for (i = 0; i < number_of_events; i++) { - char *name, *desc; - database_get_generic_description(database, i, &name, &desc); - textlog = new_textlog(h, database, name, desc); -// "ENB_UL_CHANNEL_ESTIMATE", -// "ev: {} eNB_id [eNB_ID] frame [frame] subframe [subframe]"); - textlog_add_view(textlog, out); - free(name); - free(desc); - } - - for (i = 0; i < on_off_n; i++) - on_off(database, on_off_name[i], is_on, on_off_action[i]); - - s = get_connection("0.0.0.0", port); - - /* send the first message - activate selected traces */ - t = 0; - if (write(s, &t, 1) != 1) abort(); - l = 0; - for (i = 0; i < number_of_events; i++) if (is_on[i]) l++; - if (write(s, &l, sizeof(int)) != sizeof(int)) abort(); - for (l = 0; l < number_of_events; l++) - if (is_on[l]) - if (write(s, &l, sizeof(int)) != sizeof(int)) abort(); - - if (gui_active) - setup_event_selector(g, database, s, is_on); - - /* read messages */ - while (1) { - char v[T_BUFFER_MAX]; - event e; - e = get_event(s, v, database); - handle_event(h, e); - } - - return 0; -} diff --git a/common/utils/T/tracer/textlog.c b/common/utils/T/tracer/textlog.c index 264068c61798d78fb260615f349f8ad60e387eaa..f3e6f7178cf9fadd0d45c8b6055e7d4017493924 100644 --- a/common/utils/T/tracer/textlog.c +++ b/common/utils/T/tracer/textlog.c @@ -1,189 +1,220 @@ -#include "textlog.h" -#include "handler.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <unistd.h> #include "database.h" +#include "event.h" +#include "handler.h" +#include "logger/textlog.h" #include "view/view.h" +#include "gui/gui.h" #include "utils.h" -#include <stdlib.h> -#include <string.h> -#include <stdio.h> +#include "../T_defs.h" +#include "event_selector.h" -enum format_item_type { - INSTRING, - INT, STRING, BUFFER }; - -struct format_item { - enum format_item_type type; - union { - /* INSTRING */ - char *s; - /* others */ - int event_arg; - }; -}; - -struct textlog { - char *event_name; - char *format; - void *database; - unsigned long handler_id; - /* parsed format string */ - struct format_item *f; - int fsize; - /* list of views */ - view **v; - int vsize; - /* local output buffer */ - OBUF o; -}; - -static void _event(void *p, event e) +#define DEFAULT_REMOTE_PORT 2021 + +int get_connection(char *addr, int port) { - struct textlog *l = p; - int i; + struct sockaddr_in a; + socklen_t alen; + int s, t; - l->o.osize = 0; - - for (i = 0; i < l->fsize; i++) - switch(l->f[i].type) { - case INSTRING: PUTS(&l->o, l->f[i].s); break; - case INT: PUTI(&l->o, e.e[l->f[i].event_arg].i); break; - case STRING: PUTS_CLEAN(&l->o, e.e[l->f[i].event_arg].s); break; - case BUFFER: - PUTS(&l->o, "{buffer size:"); - PUTI(&l->o, e.e[l->f[i].event_arg].bsize); - PUTS(&l->o, "}"); - break; - } - PUTC(&l->o, 0); + printf("waiting for connection on %s:%d\n", addr, port); + + s = socket(AF_INET, SOCK_STREAM, 0); + if (s == -1) { perror("socket"); exit(1); } + t = 1; + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(int))) + { perror("setsockopt"); exit(1); } + + a.sin_family = AF_INET; + a.sin_port = htons(port); + a.sin_addr.s_addr = inet_addr(addr); + + if (bind(s, (struct sockaddr *)&a, sizeof(a))) { perror("bind"); exit(1); } + if (listen(s, 5)) { perror("bind"); exit(1); } + alen = sizeof(a); + t = accept(s, (struct sockaddr *)&a, &alen); + if (t == -1) { perror("accept"); exit(1); } + close(s); + + printf("connected\n"); - for (i = 0; i < l->vsize; i++) l->v[i]->append(l->v[i], l->o.obuf); + return t; } -enum chunk_type { C_ERROR, C_STRING, C_ARG_NAME, C_EVENT_NAME }; -struct chunk { - enum chunk_type type; - char *s; - enum format_item_type it; - int event_arg; -}; - -/* TODO: speed it up? */ -static int find_argument(char *name, database_event_format f, - enum format_item_type *it, int *event_arg) +void usage(void) { - int i; - for (i = 0; i < f.count; i++) if (!strcmp(name, f.name[i])) break; - if (i == f.count) return 0; - *event_arg = i; - if (!strcmp(f.type[i], "int")) *it = INT; - else if (!strcmp(f.type[i], "string")) *it = STRING; - else if (!strcmp(f.type[i], "buffer")) *it = BUFFER; - else return 0; - return 1; + printf( +"options:\n" +" -d <database file> this option is mandatory\n" +" -on <GROUP or ID> turn log ON for given GROUP or ID\n" +" -off <GROUP or ID> turn log OFF for given GROUP or ID\n" +" -ON turn all logs ON\n" +" -OFF turn all logs OFF\n" +" note: you may pass several -on/-off/-ON/-OFF,\n" +" they will be processed in order\n" +" by default, all is off\n" +" -p <port> use given port (default %d)\n" +" -x GUI output\n" +" -debug-gui activate GUI debug logs\n" +" -no-gui disable GUI entirely\n", + DEFAULT_REMOTE_PORT + ); + exit(1); } -static struct chunk next_chunk(char **s, database_event_format f) +int fullread(int fd, void *_buf, int count) { - char *cur = *s; - char *name; - enum format_item_type it; - int event_arg; - - /* argument in [ ] */ - if (*cur == '[') { - *cur = 0; - cur++; - name = cur; - /* no \ allowed there */ - while (*cur && *cur != ']' && *cur != '\\') cur++; - if (*cur != ']') goto error; - *cur = 0; - cur++; - *s = cur; - if (find_argument(name, f, &it, &event_arg) == 0) goto error; - return (struct chunk){type:C_ARG_NAME, s:name, it:it, event_arg:event_arg}; + char *buf = _buf; + int ret = 0; + int l; + while (count) { + l = read(fd, buf, count); + if (l <= 0) { printf("read socket problem\n"); abort(); } + count -= l; + buf += l; + ret += l; } + return ret; +} - /* { } is name of event (anything in between is smashed) */ - if (*cur == '{') { - *cur = 0; - cur++; - while (*cur && *cur != '}') cur++; - if (*cur != '}') goto error; - *cur = 0; - cur++; - *s = cur; - return (struct chunk){type:C_EVENT_NAME}; - } +event get_event(int s, char *v, void *d) +{ + int type; + int32_t length; - /* anything but [ and { is raw string */ - /* TODO: deal with \ */ - name = cur; - while (*cur && *cur != '[' && *cur != '{') cur++; - *s = cur; - return (struct chunk){type:C_STRING, s:name}; + fullread(s, &length, 4); + fullread(s, &type, sizeof(int)); + length -= sizeof(int); + fullread(s, v, length); -error: - return (struct chunk){type:C_ERROR}; + return new_event(type, length, v, d); } -textlog *new_textlog(event_handler *h, void *database, - char *event_name, char *format) +static void *gui_thread(void *_g) { - struct textlog *ret; - int event_id; - database_event_format f; - char *cur; - - ret = calloc(1, sizeof(struct textlog)); if (ret == NULL) abort(); - - ret->event_name = strdup(event_name); if (ret->event_name == NULL) abort(); - ret->format = strdup(format); if (ret->format == NULL) abort(); - ret->database = database; - - event_id = event_id_from_name(database, event_name); - - ret->handler_id = register_handler_function(h, event_id, _event, ret); - - f = get_format(database, event_id); - - /* we won't get more than strlen(format) "chunks" */ - ret->f = malloc(sizeof(struct format_item) * strlen(format)); - if (ret->f == NULL) abort(); - - cur = ret->format; - - while (*cur) { - struct chunk c = next_chunk(&cur, f); - switch (c.type) { - case C_ERROR: goto error; - case C_STRING: - ret->f[ret->fsize].type = INSTRING; - ret->f[ret->fsize].s = c.s; - break; - case C_ARG_NAME: - ret->f[ret->fsize].type = c.it; - ret->f[ret->fsize].event_arg = c.event_arg; - break; - case C_EVENT_NAME: - ret->f[ret->fsize].type = INSTRING; - ret->f[ret->fsize].s = ret->event_name; - break; - } - ret->fsize++; + gui *g = _g; + gui_loop(g); + return NULL; +} + +int main(int n, char **v) +{ + extern int volatile gui_logd; + char *database_filename = NULL; + void *database; + int port = DEFAULT_REMOTE_PORT; + char **on_off_name; + int *on_off_action; + int on_off_n = 0; + int *is_on; + int number_of_events; + int s; + int i; + char t; + int l; + event_handler *h; + textlog *textlog; + gui *g; + int gui_mode = 0; + view *out; + int gui_active = 1; + + on_off_name = malloc(n * sizeof(char *)); if (on_off_name == NULL) abort(); + on_off_action = malloc(n * sizeof(int)); if (on_off_action == NULL) abort(); + + for (i = 1; i < n; i++) { + if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage(); + if (!strcmp(v[i], "-d")) + { if (i > n-2) usage(); database_filename = v[++i]; continue; } + if (!strcmp(v[i], "-p")) + { if (i > n-2) usage(); port = atoi(v[++i]); continue; } + if (!strcmp(v[i], "-on")) { if (i > n-2) usage(); + on_off_name[on_off_n]=v[++i]; on_off_action[on_off_n++]=1; continue; } + if (!strcmp(v[i], "-off")) { if (i > n-2) usage(); + on_off_name[on_off_n]=v[++i]; on_off_action[on_off_n++]=0; continue; } + if (!strcmp(v[i], "-ON")) + { on_off_name[on_off_n]=NULL; on_off_action[on_off_n++]=1; continue; } + if (!strcmp(v[i], "-OFF")) + { on_off_name[on_off_n]=NULL; on_off_action[on_off_n++]=0; continue; } + if (!strcmp(v[i], "-x")) { gui_mode = 1; continue; } + if (!strcmp(v[i], "-debug-gui")) { gui_logd = 1; continue; } + if (!strcmp(v[i], "-no-gui")) { gui_active = 0; continue; } + usage(); } - return ret; + if (gui_active == 0) gui_mode = 0; -error: - printf("%s:%d: bad format '%s'\n", __FILE__, __LINE__, format); - abort(); -} + if (database_filename == NULL) { + printf("ERROR: provide a database file (-d)\n"); + exit(1); + } -void textlog_add_view(textlog *_l, view *v) -{ - struct textlog *l = _l; - l->vsize++; - l->v = realloc(l->v, l->vsize * sizeof(view *)); if (l->v == NULL) abort(); - l->v[l->vsize-1] = v; + database = parse_database(database_filename); + + number_of_events = number_of_ids(database); + is_on = calloc(number_of_events, sizeof(int)); + if (is_on == NULL) abort(); + + h = new_handler(database); + + if (gui_active) { + g = gui_init(); + new_thread(gui_thread, g); + } + + if (gui_mode) { + widget *w, *win; +// w = new_textlist(g, 600, 20, 0); + w = new_textlist(g, 800, 50, BACKGROUND_COLOR); + win = new_toplevel_window(g, 800, 50*12, "textlog"); + widget_add_child(g, win, w, -1); + out = new_view_textlist(1000, 10, g, w); + //tout = new_view_textlist(7, 4, g, w); + } else { + out = new_view_stdout(); + } + + for (i = 0; i < number_of_events; i++) { + char *name, *desc; + database_get_generic_description(database, i, &name, &desc); + textlog = new_textlog(h, database, name, desc); +// "ENB_UL_CHANNEL_ESTIMATE", +// "ev: {} eNB_id [eNB_ID] frame [frame] subframe [subframe]"); + textlog_add_view(textlog, out); + free(name); + free(desc); + } + + for (i = 0; i < on_off_n; i++) + on_off(database, on_off_name[i], is_on, on_off_action[i]); + + s = get_connection("0.0.0.0", port); + + /* send the first message - activate selected traces */ + t = 0; + if (write(s, &t, 1) != 1) abort(); + l = 0; + for (i = 0; i < number_of_events; i++) if (is_on[i]) l++; + if (write(s, &l, sizeof(int)) != sizeof(int)) abort(); + for (l = 0; l < number_of_events; l++) + if (is_on[l]) + if (write(s, &l, sizeof(int)) != sizeof(int)) abort(); + + if (gui_active) + setup_event_selector(g, database, s, is_on); + + /* read messages */ + while (1) { + char v[T_BUFFER_MAX]; + event e; + e = get_event(s, v, database); + handle_event(h, e); + } + + return 0; }