diff --git a/Makefile b/Makefile index 29f92d42b153b1beac5d007ed92746a0d7f6f1b4..d33ab82b01038995fffeb2c3ab4f7fad7bfcea5f 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,8 @@ osd-alsa: osd-alsa.o util.o client.o osdd: display.o osdd: osdd-file.o osdd-to-string.o osdd: osdd-mqtt.o osdd-to-string.o -lpaho-mqtt3a -lpaho-mqtt3c +osdd: osdd-exec.o osdd-to-string.o +osdd: osdd-system.o osdd-to-string.o osdd: LDLIBS+=$(shell pkg-config --libs xft) -lXext -lX11 diff --git a/osdd-exec.c b/osdd-exec.c new file mode 100644 index 0000000000000000000000000000000000000000..c793701aeef1500f329f0947b69374a182815e09 --- /dev/null +++ b/osdd-exec.c @@ -0,0 +1,106 @@ +/* + * On-screen Display + * + * (c) 2020--2021 Jiri Kalvoda <jirikalvoda@kam.mff.cuni.cz> + */ + +#include "osdd-exec.h" +#include "util.h" +#include "osdd-to-string.h" + +#include <stdio.h> +#include <string.h> +#include <getopt.h> +#include <stdlib.h> +#include <unistd.h> + + + +// ************************* STATE STRUCT ********** + +struct exec_state +{ + //struct osd_to_string_state to_string; + bool do_not_insert_msg_to_que; + bool no_fork; + bool arg_by_line; + VECTOR(char *) prefix; + struct osd_to_string_state to_string; +}; + +// ************************* MAIN FUNCTIONS ******* + +static +void exec_write(struct exec_state *state, VECTOR(VECTOR(char)) in) +{ + if(!in) return; + if(fork()==0) + { + VECTOR(char *) a = VCLONE(state->prefix); + for(int i=0;i<VSIZE(in); i++) VPB(a,in[i]); + VPB(a, 0); + execvp(a[0], a); + } + for(int i=0;i<VSIZE(in); i++) VFREE(in[i]); + VFREE(in); +} + +INIT_FUNC_USING_TO_STRINGS_VECTOR(exec) + +// ************************* NEW ****************** + +static +void exec_new_help(FILE * f) +{ + fprintf(f,"\ +Module EXEC help:\n\ +\t-opt [ARG0] [ARG1] ...\n\ +On each message execute\n\ +ARG0 ARG1 ... [TIME if -t is set] LINE0 LINE1 ...\n\ +" OSDD_TO_STRINGS_VECTOR_HELP "\ +\n\ +"); +} + +static +struct osd_abstract exec_new(int argc, char ** argv, Display * nope) +{ + (void)nope; + argc++;argv--; + struct osd_abstract r; + static const char short_opts[] = "+" OSDD_TO_STRINGS_VECTOR_SHORTOP; + static const struct option long_opts[] = { + OSDD_TO_STRINGS_VECTOR_LONGOP + { NULL, 0, NULL, 0 }, + }; + memset(&r,0,sizeof(r)); + struct exec_state *state = xmalloc(sizeof(*state)); + memset(state,0,sizeof(state)[0]); + + osd_to_string_state_init(&state->to_string); + + int opt; + optind = 0; + while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) >= 0) + { + if(!osd_to_strings_vector_parse_arg(&state->to_string,opt)) + switch (opt) + { + default: + fprintf(stderr,"Option %c not exist\n\n",opt); + exec_new_help(stderr); + exit(0); + } + } + for(int ind = optind; ind < argc; ind++) + { + VPB(state->prefix, argv[ind]); + } + + INIT_FUNC_TO_ABSTRACT(r, exec) + return r; +} + +// ************************* CREATOR **************************** + +CREATE_STANDARD_CREATOR(exec , "EXEC") diff --git a/osdd-exec.h b/osdd-exec.h new file mode 100644 index 0000000000000000000000000000000000000000..558dd90ff2e31cc9f7b0954dc8136bc16ba5cf72 --- /dev/null +++ b/osdd-exec.h @@ -0,0 +1,9 @@ +/* + * On-screen Display + * + * (c) 2020--2021 Jiri Kalvoda <jirikalvoda@kam.mff.cuni.cz> + */ + +#include "osdd-set.h" + +struct osd_creator_abstract exec_creator_new(void); diff --git a/osdd-set.h b/osdd-set.h index 8460c5dd5f5546222d2868141711530653d57dac..e77cbc490d19c190dddee9f5a99554329bedc0b1 100644 --- a/osdd-set.h +++ b/osdd-set.h @@ -103,4 +103,27 @@ void msg_active_outputs(struct osd_set *set, struct msg *msg, char * name, bool struct msg* osd_set_new_msg(struct osd_set * set); void msg_free(struct msg * msg); + +#define CREATE_STANDARD_CREATOR(NAME, SNAME) \ +struct osd_creator_abstract NAME ## _creator_new(void) \ +{ \ + struct osd_creator_abstract r; \ + memset(&r, 0, sizeof(r)); \ + r.name = SNAME; \ + r.help = NAME ## _new_help; \ + r.new.add_one_osd = NAME ## _new; \ + return r; \ +} + +#define INIT_FUNC_TO_ABSTRACT(r, NAME) \ +{ \ + r.context = state; \ + bool (*arrive)(struct NAME ## _state*, struct osd_line*, int) = NAME ## _arrive; \ + r.arrive = (bool (*)(void*, struct osd_line*, int)) arrive; \ + void (*show)(struct NAME ## _state*, struct osd_line*, int) = NAME ## _show; \ + r.show = (void (*)(void*, struct osd_line*, int)) show; \ + void (*clear)(struct NAME ## _state*) = NAME ## _clear; \ + r.clear = (void (*)(void*)) clear; \ +} + #endif diff --git a/osdd-system.c b/osdd-system.c new file mode 100644 index 0000000000000000000000000000000000000000..784d65da6c9337c845d63e3341ef18ab976db7ac --- /dev/null +++ b/osdd-system.c @@ -0,0 +1,119 @@ +/* + * On-screen Display + * + * (c) 2020--2021 Jiri Kalvoda <jirikalvoda@kam.mff.cuni.cz> + */ + +#include "osdd-system.h" +#include "util.h" +#include "osdd-to-string.h" + +#include <stdio.h> +#include <string.h> +#include <getopt.h> +#include <stdlib.h> +#include <unistd.h> + + + +// ************************* STATE STRUCT ********** + +struct system_state +{ + struct osd_to_string_state to_string; + bool no_fork; + char * prefix; +}; + +// ************************* MAIN FUNCTIONS ******* + +static +void system_write(struct system_state *state, VECTOR(char) in) +{ + if(!in) return; + if(state->no_fork || fork()==0) + { + if(state->prefix) + { + VECTOR(char) out = 0; + vprint(&out,"%s%s",state->prefix,in); + system(out); + VFREE(out); + } + else + system(in); + if(!state->no_fork) _exit(0); + } + VFREE(in); +} + +INIT_FUNC_USING_TO_STRING(system) + + +// ************************* NEW ****************** + +static +void system_new_help(FILE * f) +{ + fprintf(f,"\ +Module EXEC help:\n\ +\t-opt [PREFIX]\n\ +concatenatin of PREFIX and message will be executed by system(3)\n\ +-F, --no-fork\t\tDo not fork before call system\n\ +" OSDD_TO_STRING_HELP "\ +\n\ +"); +} + +static +struct osd_abstract system_new(int argc, char ** argv, Display * nope) +{ + (void)nope; + argc++;argv--; + struct osd_abstract r; + static const char short_opts[] = "+F" OSDD_TO_STRING_SHORTOP; + static const struct option long_opts[] = { + { "no-fork", no_argument, NULL, 'F' }, + OSDD_TO_STRING_LONGOP + { NULL, 0, NULL, 0 }, + }; + memset(&r,0,sizeof(r)); + struct system_state *state = xmalloc(sizeof(*state)); + memset(state,0,sizeof(state)[0]); + + osd_to_string_state_init(&state->to_string); + + int opt; + optind = 0; + while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) >= 0) + { + if(!osd_to_string_parse_arg(&state->to_string,opt)) + switch (opt) + { + case 'F': + state->no_fork = 1; + break; + default: + fprintf(stderr,"Option %c not exist\n\n",opt); + system_new_help(stderr); + exit(0); + } + } + int ind = optind; + if(ind < argc) + state->prefix = argv[ind++]; + if(ind != argc) + { + fprintf(stderr,"Too many arguments\n\n"); + system_new_help(stderr); + exit(0); + + } + + INIT_FUNC_TO_ABSTRACT(r, system) + return r; +} + +// ************************* CREATOR **************************** + +CREATE_STANDARD_CREATOR(system,"SYSTEM") diff --git a/osdd-system.h b/osdd-system.h new file mode 100644 index 0000000000000000000000000000000000000000..141196a367bd913e6852052f674849725486382c --- /dev/null +++ b/osdd-system.h @@ -0,0 +1,9 @@ +/* + * On-screen Display + * + * (c) 2020--2021 Jiri Kalvoda <jirikalvoda@kam.mff.cuni.cz> + */ + +#include "osdd-set.h" + +struct osd_creator_abstract system_creator_new(void); diff --git a/osdd-to-string.c b/osdd-to-string.c index f7f28d5ed5296d219a54198e33a56fe0b4b2083b..63c993f19f372e125dcb0f26a0bc2908c5df1afa 100644 --- a/osdd-to-string.c +++ b/osdd-to-string.c @@ -18,7 +18,6 @@ #include <X11/extensions/render.h> #include <X11/Xft/Xft.h> -static char * expand_backslash(char * in) { char * out = xmalloc(strlen(in)+1); @@ -89,6 +88,29 @@ colorToRGB(char * name, int *r, int *g, int *b) bool osd_to_string_parse_arg(struct osd_to_string_state *state, char arg) +{ + if(osd_to_strings_vector_parse_arg(state, arg)) return 1; + switch(arg) + { + case 'l': + free(state->line_separator); + state->line_separator = expand_backslash(optarg); + break; + case 'm': + free(state->msq_separator); + state->msq_separator = expand_backslash(optarg); + break; + case 'T': + free(state->time_separator); + state->time_separator = expand_backslash(optarg); + break; + default: + return 0; + } + return 1; +} + +bool osd_to_strings_vector_parse_arg(struct osd_to_string_state *state, char arg) { switch(arg) { @@ -104,14 +126,6 @@ bool osd_to_string_parse_arg(struct osd_to_string_state *state, char arg) exit(0); } break; - case 'l': - free(state->line_separator); - state->line_separator = expand_backslash(optarg); - break; - case 'm': - free(state->msq_separator); - state->msq_separator = expand_backslash(optarg); - break; case 'r': state->replace_no_text = 1; break; @@ -124,10 +138,6 @@ bool osd_to_string_parse_arg(struct osd_to_string_state *state, char arg) exit(0); } break; - case 'T': - free(state->time_separator); - state->time_separator = expand_backslash(optarg); - break; case 'e': if(state->end_of_mes_by) free(state->end_of_mes_by); state->end_of_mes_by = expand_backslash(optarg); @@ -149,29 +159,32 @@ bool osd_to_string_parse_arg(struct osd_to_string_state *state, char arg) } static -void osd_to_string_time(struct osd_to_string_state *state, VECTOR(char) * out) +VECTOR(char) osd_to_string_time(struct osd_to_string_state *state) { + VECTOR(char) out=0; switch(state->time_mode) { case FILE_TIME_NO: break; case FILE_TIME_UNIX: - vprint(out,"%lld%s",(long long)time(0),state->time_separator); + vprint(&out,"%lld",(long long)time(0)); break; case FILE_TIME_ISO: { time_t t = time(NULL); struct tm tm = *localtime(&t); - vprint(out,"%04d-%02d-%02d %02d:%02d:%02d%s", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,state->time_separator); + vprint(&out,"%04d-%02d-%02d %02d:%02d:%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); } break; } + return out; } -VECTOR(char) osd_to_string(struct osd_to_string_state *state, struct osd_line * lines, int num_lines) +VECTOR(VECTOR(char)) osd_to_strings_vector(struct osd_to_string_state *state, struct osd_line * lines, int num_lines) { - VECTOR(char) out = NULL; - osd_to_string_time(state, &out); + VECTOR(VECTOR(char)) out = NULL; + VECTOR(char) t = osd_to_string_time(state); + if(t) VPB(out,t); for(int i=0;i<num_lines;i++) { struct osd_line * line = lines+i; @@ -218,15 +231,35 @@ VECTOR(char) osd_to_string(struct osd_to_string_state *state, struct osd_line * case FILE_COLOR_NO: break; } - vprint(&out,"%s%s%s%s", color, text, end_color,state->line_separator); + VECTOR(char) l=0; + vprint(&l,"%s%s%s", color, text, end_color); + VPB(out,l); VFREE(text); } + return out; +} + +VECTOR(char) osd_to_string(struct osd_to_string_state *state, struct osd_line * lines, int num_lines) +{ + VECTOR(char) out = NULL; + VRESERVE(out,256); + VECTOR(VECTOR(char)) in = osd_to_strings_vector(state, lines, num_lines); + for(int i=0; i<VSIZE(in); i++) + { + if(i==0 && state->time_mode != FILE_TIME_NO) + vprint(&out,"%s%s",in[i],state->time_separator); + else + vprint(&out,"%s%s",in[i],state->line_separator); + } vprint(&out,"%s",state->msq_separator); + for(int i=0; i<VSIZE(in); i++) + VFREE(in[i]); + VFREE(in); return out; } -VECTOR(char) osd_to_string_arrivee_msq(struct osd_to_string_state *state, struct osd_line * lines, int num_lines) +VECTOR(char) osd_to_string_arrive_msq(struct osd_to_string_state *state, struct osd_line * lines, int num_lines) { if(!state->on_arrive) return 0; return osd_to_string(state, lines, num_lines); @@ -236,7 +269,6 @@ VECTOR(char) osd_to_string_show_msg(struct osd_to_string_state *state, struct os { if(state->on_arrive) return 0; return osd_to_string(state, lines, num_lines); - } VECTOR(char) osd_to_string_clear_msg(struct osd_to_string_state *state) @@ -245,11 +277,43 @@ VECTOR(char) osd_to_string_clear_msg(struct osd_to_string_state *state) if(!state->end_of_mes_by) return 0; VECTOR(char) out=0; if(state->end_of_mes_time) - osd_to_string_time(state, &out); + { + VECTOR(char) t = osd_to_string_time(state); + vprint(&out,"%s",t); + VFREE(t); + } vprint(&out,"%s",state->end_of_mes_by); return out; } +VECTOR(VECTOR(char)) osd_to_strings_vector_arrive_msq(struct osd_to_string_state *state, struct osd_line * lines, int num_lines) +{ + if(!state->on_arrive) return 0; + return osd_to_strings_vector(state, lines, num_lines); +} + +VECTOR(VECTOR(char)) osd_to_strings_vector_show_msg(struct osd_to_string_state *state, struct osd_line * lines, int num_lines) +{ + if(state->on_arrive) return 0; + return osd_to_strings_vector(state, lines, num_lines); + +} + +VECTOR(VECTOR(char)) osd_to_strings_vector_clear_msg(struct osd_to_string_state *state) +{ + if(state->on_arrive) return 0; + if(!state->end_of_mes_by) return 0; + VECTOR(VECTOR(char)) out=0; + if(state->end_of_mes_time) + { + VECTOR(char) t = osd_to_string_time(state); + VPB(out,t); + } + VADDSIZE(out,1); + vprint(&VLAST(out),"%s",state->end_of_mes_by); + return out; +} + void osd_to_string_state_init(struct osd_to_string_state * state) { state->line_separator = expand_backslash("\\n"); diff --git a/osdd-to-string.h b/osdd-to-string.h index c4adfebc35c6687f0f9bb645bc62b7a3f23b30fd..0d38778c152f430d4c96cc3eca2e174487f567f2 100644 --- a/osdd-to-string.h +++ b/osdd-to-string.h @@ -8,19 +8,35 @@ #include "util.h" #define OSDD_TO_STRING_LONGOP \ - { "color", required_argument, NULL, 'c' },\ { "line-separator", required_argument, NULL, 'l' },\ { "msq-separator", required_argument, NULL, 'm' },\ + { "time-separator", required_argument, NULL, 'T' },\ + OSDD_TO_STRINGS_VECTOR_LONGOP + +#define OSDD_TO_STRINGS_VECTOR_LONGOP \ + { "color", required_argument, NULL, 'c' },\ { "replace", no_argument, NULL, 'r' },\ { "time", required_argument, NULL, 't' },\ - { "time-separator", required_argument, NULL, 'T' },\ { "end", required_argument, NULL, 'e' },\ { "end-time", no_argument, NULL, 'E' },\ { "on-arrive", required_argument, NULL, 'a' },\ { "on-arrive-do-not-que", required_argument, NULL, 'A' },\ #define OSDD_TO_STRING_SHORTOP \ - "c:l:m:rt:T:e:EaA" + "l:m:T:" OSDD_TO_STRINGS_VECTOR_SHORTOP + +#define OSDD_TO_STRINGS_VECTOR_SHORTOP \ + "c:rt:T:e:EaA" + +#define OSDD_TO_STRINGS_VECTOR_HELP \ +"-c, --color=<{}>\tSet how to print color of messages {no, rgbDEC, rgbHEX, rgbHEXHASHTAG, term, original}\n" \ +"-r, --replace\t\tReplace not alphabet and number in output to '?'\n"\ +"-t, --time=<{}>\t\tSet how to print actual time {no, unix, iso}\n"\ +"-e, --end-<s>\t\tPrint <s> on end of showing message\n"\ +"-E, --end-time\t\tPrint actual time on end messages (format from -t -T)\n"\ +"-a, --on-arrive\t\tPrint message just when arrive (not compatible with -e -E)\n"\ +"-A, --on-arrive\t\tPrint message just when arrive and do not insert it to message queue\n"\ +"\t\t\t\t(not compatible with -e -E)\n" #define OSDD_TO_STRING_HELP \ "-c, --color=<{}>\tSet how to print color of messages {no, rgbDEC, rgbHEX, rgbHEXHASHTAG, term, original}\n" \ @@ -30,7 +46,7 @@ "-t, --time=<{}>\t\tSet how to print actual time {no, unix, iso}\n"\ "-T, --time-separator=<s>Separator of time and message text\n"\ "-e, --end-<s>\t\tPrint <s> on end of showing message\n"\ -"-E, --end-time\t\tWrite actual time to end messages (format from -t -T)\n"\ +"-E, --end-time\t\tPrint actual time on end messages (format from -t -T)\n"\ "-a, --on-arrive\t\tPrint message just when arrive (not compatible with -e -E)\n"\ "-A, --on-arrive\t\tPrint message just when arrive and do not insert it to message queue\n"\ "\t\t\t\t(not compatible with -e -E)\n" @@ -61,11 +77,59 @@ struct osd_to_string_state bool do_not_insert_msg_to_que; }; +char * expand_backslash(char * in); + +VECTOR(VECTOR(char)) osd_to_strings_vector(struct osd_to_string_state *state, struct osd_line * lines, int num_lines); VECTOR(char) osd_to_string(struct osd_to_string_state *state, struct osd_line * lines, int num_lines); -VECTOR(char) osd_to_string_arrivee_msq(struct osd_to_string_state *state, struct osd_line * lines, int num_lines); +VECTOR(char) osd_to_string_arrive_msq(struct osd_to_string_state *state, struct osd_line * lines, int num_lines); VECTOR(char) osd_to_string_show_msg(struct osd_to_string_state *state, struct osd_line * lines, int num_lines); VECTOR(char) osd_to_string_clear_msg(struct osd_to_string_state *state); +VECTOR(VECTOR(char)) osd_to_strings_vector_arrive_msq(struct osd_to_string_state *state, struct osd_line * lines, int num_lines); +VECTOR(VECTOR(char)) osd_to_strings_vector_show_msg(struct osd_to_string_state *state, struct osd_line * lines, int num_lines); +VECTOR(VECTOR(char)) osd_to_strings_vector_clear_msg(struct osd_to_string_state *state); + bool osd_to_string_parse_arg(struct osd_to_string_state *state, char arg); +bool osd_to_strings_vector_parse_arg(struct osd_to_string_state *state, char arg); void osd_to_string_state_init(struct osd_to_string_state * state); + +#define INIT_FUNC_USING_TO_STRING(NAME) \ +static \ +bool NAME ## _arrive(struct NAME ## _state *state, struct osd_line * lines, int num_lines) \ +{ \ + NAME ## _write(state,osd_to_string_arrive_msq(&state->to_string, lines, num_lines)); \ + return state->to_string.do_not_insert_msg_to_que; \ +} \ + \ +static \ +void NAME ## _show(struct NAME ## _state *state, struct osd_line * lines, int num_lines) \ +{ \ + NAME ## _write(state,osd_to_string_show_msg(&state->to_string, lines, num_lines)); \ +} \ + \ +static \ +void NAME ## _clear(struct NAME ## _state *state) \ +{ \ + NAME ## _write(state,osd_to_string_clear_msg(&state->to_string)); \ +} + +#define INIT_FUNC_USING_TO_STRINGS_VECTOR(NAME) \ +static \ +bool NAME ## _arrive(struct NAME ## _state *state, struct osd_line * lines, int num_lines) \ +{ \ + NAME ## _write(state,osd_to_strings_vector_arrive_msq(&state->to_string, lines, num_lines)); \ + return state->to_string.do_not_insert_msg_to_que; \ +} \ + \ +static \ +void NAME ## _show(struct NAME ## _state *state, struct osd_line * lines, int num_lines) \ +{ \ + NAME ## _write(state,osd_to_strings_vector_show_msg(&state->to_string, lines, num_lines)); \ +} \ + \ +static \ +void NAME ## _clear(struct NAME ## _state *state) \ +{ \ + NAME ## _write(state,osd_to_strings_vector_clear_msg(&state->to_string)); \ +} diff --git a/osdd.c b/osdd.c index b37d0bc603003db70e2c9ffb1fc02a945fbd62ad..0ffa5f49c2899bd13390e5bd965df9becce8bf02 100644 --- a/osdd.c +++ b/osdd.c @@ -14,6 +14,8 @@ #include <locale.h> #include <X11/Xlib.h> #include <X11/Xatom.h> +#include <signal.h> +#include <sys/wait.h> //#undef DEBUG #include "util.h" @@ -22,6 +24,8 @@ #include "display.h" #include "osdd-file.h" #include "osdd-mqtt.h" +#include "osdd-exec.h" +#include "osdd-system.h" static struct osd_set osd; @@ -410,6 +414,14 @@ do_test(void) /*** Main loop ***/ +static +void sigchld(int a) +{ + (void)a; + int s; + wait(&s); +} + int main(int argc, char **argv) { @@ -417,7 +429,10 @@ main(int argc, char **argv) VPB(creator,display_by_outputs_creator_new()); VPB(creator,file_creator_new()); VPB(creator,mqtt_creator_new()); + VPB(creator,exec_creator_new()); + VPB(creator,system_creator_new()); + signal(SIGCHLD, sigchld); setlocale(LC_CTYPE, ""); XInitThreads(); diff --git a/util.c b/util.c index c1044135bd1db829f7e07ef67916a83e8a68d7d9..327f714abe88c2b9d727833b7714d490043366f5 100644 --- a/util.c +++ b/util.c @@ -27,6 +27,10 @@ die(char *fmt, ...) void * xmalloc(int size) { + /*if(size > 10000) + { + fprintf(stderr,"Try alocate %d bytes of memory :-(",size); + }*/ void *p = malloc(size); if (!p) die("Failed to allocate %d bytes of memory", size); @@ -36,6 +40,10 @@ xmalloc(int size) void * xrealloc(void *ptr, int size) { + /*if(size > 10000) + { + fprintf(stderr,"Try alocate %d bytes of memory :-(",size); + }*/ void *p = realloc(ptr, size); if (!p) die("Failed to re-allocate %d bytes of memory", size); @@ -129,12 +137,22 @@ int vmax(void * v) void vfree(void ** v) { - if(!v) return; + if(!*v) return; struct v *this = (struct v*)*v - 1; free(this); *v = 0; } +void * vclone(void * v) +{ + if(!v) return 0; + struct v *this = (struct v*)v - 1; + int l = sizeof(struct v) + this->max; + struct v *new = xmalloc(l); + memcpy(new,this,l); + return new->data; +} + int FORMAT_CHECK(printf,2,3) vprint(VECTOR(char) *out , char *fmt, ...) diff --git a/util.h b/util.h index 40f0edb6ab9ff8365d3f0eec9983d266e616a484..d03b7a15cf2bad74eda25d19bbf15acdd79387b0 100644 --- a/util.h +++ b/util.h @@ -42,16 +42,18 @@ void vreserve(void ** v, int s); int vsize(void * v); int vmax(void * v); void vfree(void ** v); +void * vclone(void * v); // Macros for multiple size by size of element -#define VSETSIZE(v,s) {vsetsize((void **)&(v),sizeof(*(v))*(s));} -#define VADDSIZE(v,s) {vaddsize((void **)&(v),sizeof(*(v))*(s));} -#define VRESERVE(v,s) {vreserve((void **)&(v),sizeof(*(v))*(s));} +#define VSETSIZE(v,s) {vsetsize((void **)&(v),(int)sizeof(*(v))*(s));} +#define VADDSIZE(v,s) {vaddsize((void **)&(v),(int)sizeof(*(v))*(s));} +#define VRESERVE(v,s) {vreserve((void **)&(v),(int)sizeof(*(v))*(s));} #define VSIZE(v) (vsize(v)/(int)sizeof(*(v))) #define VMAX(v) (vmax(v)/(int)sizeof(*(v))) #define VLAST(v) ((v)[VSIZE(v)-1]) #define VPB(v,a) {VADDSIZE(v,1);VLAST(v)=a;} #define VFREE(v) vfree((void **)&(v)) +#define VCLONE(v) ((typeof(v)) vclone((void *)(v))) #define VECTOR(a) a *