Update spp to reduce global symbols

This commit is contained in:
pancake 2017-04-20 14:12:36 +02:00
parent babfae501c
commit f52b27e2ec
6 changed files with 97 additions and 138 deletions

View File

@ -4,48 +4,43 @@ static char *pkgname = NULL;
static char *version = NULL; static char *version = NULL;
static char **slurp_ptr = NULL; static char **slurp_ptr = NULL;
static int slurp_args(char *buf) static int slurp_args(char *buf) {
{
if (slurp_ptr) { if (slurp_ptr) {
*slurp_ptr = strdup(buf); *slurp_ptr = strdup (buf);
slurp_ptr = NULL; slurp_ptr = NULL;
return 1; return 1;
} }
return 0; return 0;
} }
TAG_CALLBACK(acr_default) static TAG_CALLBACK(acr_default) {
{
//printf("acr keyword(%s)\n", buf); //printf("acr keyword(%s)\n", buf);
if (slurp_args(buf)) {
if (slurp_args(buf))
return 0; return 0;
}
if (!strcmp(buf, "PKGNAME")) { if (!strcmp(buf, "PKGNAME")) {
slurp_ptr = &pkgname; slurp_ptr = &pkgname;
} else } else if (!strcmp(buf, "VERSION")) {
if (!strcmp(buf, "VERSION")) {
slurp_ptr = &version; slurp_ptr = &version;
} }
return 0; return 0;
} }
TAG_CALLBACK(acr_eof) static TAG_CALLBACK(acr_eof) {
{ printf ("Report:\n pkgname: %s\n version: %s\n", pkgname, version);
printf("Report:\n pkgname: %s\n version: %s\n", pkgname, version);
return 0; return 0;
} }
struct Tag acr_tags[] = { DLL_LOCAL struct Tag acr_tags[] = {
{ NULL, acr_default }, { NULL, acr_default },
{ NULL } { NULL }
}; };
struct Arg acr_args[] = { DLL_LOCAL struct Arg acr_args[] = {
{ NULL } { NULL }
}; };
struct Proc acr_proc = { DLL_LOCAL struct Proc acr_proc = {
.name = "acr", .name = "acr",
.tags = (struct Tag **)acr_tags, .tags = (struct Tag **)acr_tags,
.args = (struct Arg **)acr_args, .args = (struct Arg **)acr_args,

View File

@ -1,13 +1,11 @@
/* CPP */ /* CPP */
TAG_CALLBACK(cpp_default) static TAG_CALLBACK(cpp_default) {
{
do_printf (out, "DEFAULT: (%s)\n", buf); do_printf (out, "DEFAULT: (%s)\n", buf);
return 0; return 0;
} }
TAG_CALLBACK(cpp_error) static TAG_CALLBACK(cpp_error) {
{
do_printf (out,"\n"); do_printf (out,"\n");
if (echo[ifl] && buf != NULL) { if (echo[ifl] && buf != NULL) {
do_printf (out, "ERROR: %s (line=%d)\n", buf, lineno); do_printf (out, "ERROR: %s (line=%d)\n", buf, lineno);
@ -16,8 +14,7 @@ TAG_CALLBACK(cpp_error)
return 0; return 0;
} }
TAG_CALLBACK(cpp_warning) static TAG_CALLBACK(cpp_warning) {
{
do_printf (out,"\n"); do_printf (out,"\n");
if (echo[ifl] && buf != NULL) { if (echo[ifl] && buf != NULL) {
do_printf (out, "WARNING: line %d: %s\n", lineno, buf); do_printf (out, "WARNING: line %d: %s\n", lineno, buf);
@ -25,8 +22,7 @@ TAG_CALLBACK(cpp_warning)
return 0; return 0;
} }
TAG_CALLBACK(cpp_if) static TAG_CALLBACK(cpp_if) {
{
char *var = getenv (buf + ((*buf == '!') ? 1 : 0)); char *var = getenv (buf + ((*buf == '!') ? 1 : 0));
if (var && *var=='1') if (var && *var=='1')
echo[ifl + 1] = 1; echo[ifl + 1] = 1;
@ -35,21 +31,18 @@ TAG_CALLBACK(cpp_if)
return 1; return 1;
} }
TAG_CALLBACK(cpp_ifdef) static TAG_CALLBACK(cpp_ifdef) {
{
char *var = getenv (buf); char *var = getenv (buf);
echo[ifl + 1] = var? 1: 0; echo[ifl + 1] = var? 1: 0;
return 1; return 1;
} }
TAG_CALLBACK(cpp_else) static TAG_CALLBACK(cpp_else) {
{
echo[ifl] = echo[ifl]? 0: 1; echo[ifl] = echo[ifl]? 0: 1;
return 0; return 0;
} }
TAG_CALLBACK(cpp_ifndef) static TAG_CALLBACK(cpp_ifndef) {
{
cpp_ifdef (buf, out); cpp_ifdef (buf, out);
cpp_else (buf, out); cpp_else (buf, out);
return 1; return 1;
@ -63,8 +56,7 @@ static struct cpp_macro_t {
static int cpp_macros_n = 0; static int cpp_macros_n = 0;
static void cpp_macro_add(char *name, char *args, char *body) static void cpp_macro_add(char *name, char *args, char *body) {
{
char *ptr; char *ptr;
cpp_macros[cpp_macros_n].args = strdup(args); cpp_macros[cpp_macros_n].args = strdup(args);
cpp_macros[cpp_macros_n].body = strdup(body); cpp_macros[cpp_macros_n].body = strdup(body);
@ -76,8 +68,7 @@ static void cpp_macro_add(char *name, char *args, char *body)
cpp_macros_n++; cpp_macros_n++;
} }
PUT_CALLBACK(cpp_fputs) static PUT_CALLBACK(cpp_fputs) {
{
int i; int i;
for (i = 0; i < cpp_macros_n; i++) { for (i = 0; i < cpp_macros_n; i++) {
if (strstr(buf, cpp_macros[i].name)) { if (strstr(buf, cpp_macros[i].name)) {
@ -89,9 +80,8 @@ PUT_CALLBACK(cpp_fputs)
return 0; return 0;
} }
TAG_CALLBACK(cpp_define) static TAG_CALLBACK(cpp_define) {
{ char *eq = strchr (buf, ' ');
char *eq = strchr(buf, ' ');
if (eq) { if (eq) {
char *ptr = eq + 1; char *ptr = eq + 1;
char *macro = strchr(buf, '('); char *macro = strchr(buf, '(');
@ -116,20 +106,18 @@ TAG_CALLBACK(cpp_define)
return 0; return 0;
} }
TAG_CALLBACK(cpp_endif) static TAG_CALLBACK(cpp_endif) {
{
return -1; return -1;
} }
TAG_CALLBACK(cpp_include) static TAG_CALLBACK(cpp_include) {
{
if (echo[ifl]) { if (echo[ifl]) {
spp_file (buf, out); spp_file (buf, out);
} }
return 0; return 0;
} }
struct Tag cpp_tags[] = { DLL_LOCAL struct Tag cpp_tags[] = {
{ "ifdef", cpp_ifdef }, { "ifdef", cpp_ifdef },
{ "ifndef", cpp_ifndef }, { "ifndef", cpp_ifndef },
{ "endif", cpp_endif }, { "endif", cpp_endif },
@ -145,14 +133,12 @@ struct Tag cpp_tags[] = {
/* arguments */ /* arguments */
ARG_CALLBACK(cpp_arg_i) static ARG_CALLBACK(cpp_arg_i) {
{
printf("INCLUDEDIR(%s)\n", arg); printf("INCLUDEDIR(%s)\n", arg);
return 0; return 0;
} }
ARG_CALLBACK(cpp_arg_d) static ARG_CALLBACK(cpp_arg_d) {
{
// TODO: handle r_sys_setenv==-1 // TODO: handle r_sys_setenv==-1
char *eq = strchr(arg, '='); char *eq = strchr(arg, '=');
if (eq) { if (eq) {
@ -162,13 +148,13 @@ ARG_CALLBACK(cpp_arg_d)
return 0; return 0;
} }
struct Arg cpp_args[] = { static struct Arg cpp_args[] = {
{ "-I", "add include directory", 1, cpp_arg_i }, { "-I", "add include directory", 1, cpp_arg_i },
{ "-D", "define value of variable", 1, cpp_arg_d }, { "-D", "define value of variable", 1, cpp_arg_d },
{ NULL } { NULL }
}; };
struct Proc cpp_proc = { DLL_LOCAL struct Proc cpp_proc = {
.name = "cpp", .name = "cpp",
.tags = (struct Tag **)cpp_tags, .tags = (struct Tag **)cpp_tags,
.args = (struct Arg **)cpp_args, .args = (struct Arg **)cpp_args,

View File

@ -1,20 +1,17 @@
/* CPP */ /* CPP */
TAG_CALLBACK(pod_default) static TAG_CALLBACK(pod_default) {
{
do_printf (out, "DEFAULT: (%s)\n", buf); do_printf (out, "DEFAULT: (%s)\n", buf);
return 0; return 0;
} }
TAG_CALLBACK(pod_cut) static TAG_CALLBACK(pod_cut) {
{
do_printf (out, "\n"); do_printf (out, "\n");
echo[ifl] = 0; echo[ifl] = 0;
return 0; return 0;
} }
TAG_CALLBACK(pod_head1) static TAG_CALLBACK(pod_head1) {
{
echo[ifl] = 1; echo[ifl] = 1;
do_printf (out, "\n"); do_printf (out, "\n");
if (!buf) { if (!buf) {
@ -29,18 +26,18 @@ TAG_CALLBACK(pod_head1)
return 0; return 0;
} }
struct Tag pod_tags[] = { static struct Tag pod_tags[] = {
{ "head1", pod_head1 }, { "head1", pod_head1 },
{ "cut", pod_cut }, { "cut", pod_cut },
{ NULL, pod_default }, { NULL, pod_default },
{ NULL } { NULL }
}; };
struct Arg pod_args[] = { static struct Arg pod_args[] = {
{ NULL } { NULL }
}; };
struct Proc pod_proc = { DLL_LOCAL struct Proc pod_proc = {
.name = "pod", .name = "pod",
.tags = (struct Tag **)pod_tags, .tags = (struct Tag **)pod_tags,
.args = (struct Arg **)pod_args, .args = (struct Arg **)pod_args,

View File

@ -7,8 +7,7 @@ static char *eof = NULL;
static char *input = NULL; static char *input = NULL;
#endif #endif
TAG_CALLBACK(sh_default) static TAG_CALLBACK(sh_default) {
{
//if (out != stdout) { //if (out != stdout) {
// pipe stdout to out fd // pipe stdout to out fd
//} //}
@ -32,24 +31,21 @@ TAG_CALLBACK(sh_default)
static int sh_pipe_enabled = 0; static int sh_pipe_enabled = 0;
static char *sh_pipe_cmd = NULL; static char *sh_pipe_cmd = NULL;
TAG_CALLBACK(sh_pipe) static TAG_CALLBACK(sh_pipe) {
{
sh_pipe_enabled = 1; sh_pipe_enabled = 1;
free (sh_pipe_cmd); free (sh_pipe_cmd);
sh_pipe_cmd = strdup (buf); sh_pipe_cmd = strdup (buf);
return 0; return 0;
} }
TAG_CALLBACK(sh_endpipe) static TAG_CALLBACK(sh_endpipe) {
{
sh_pipe_enabled = 0; sh_pipe_enabled = 0;
free (sh_pipe_cmd); free (sh_pipe_cmd);
sh_pipe_cmd = NULL; sh_pipe_cmd = NULL;
return 0; return 0;
} }
PUT_CALLBACK(sh_fputs) static PUT_CALLBACK(sh_fputs) {
{
if (sh_pipe_enabled) { if (sh_pipe_enabled) {
char str[1024]; // XXX char str[1024]; // XXX
sprintf (str, "echo '%s' | %s", buf, sh_pipe_cmd); // XXX sprintf (str, "echo '%s' | %s", buf, sh_pipe_cmd); // XXX
@ -60,18 +56,18 @@ PUT_CALLBACK(sh_fputs)
return 0; return 0;
} }
struct Tag sh_tags[] = { static struct Tag sh_tags[] = {
{ "pipe", sh_pipe }, { "pipe", sh_pipe },
{ "endpipe", sh_endpipe }, { "endpipe", sh_endpipe },
{ NULL, sh_default }, { NULL, sh_default },
{ NULL } { NULL }
}; };
struct Arg sh_args[] = { static struct Arg sh_args[] = {
{ NULL } { NULL }
}; };
struct Proc sh_proc = { DLL_LOCAL struct Proc sh_proc = {
.name = "sh", .name = "sh",
.tags = (struct Tag **)sh_tags, .tags = (struct Tag **)sh_tags,
.args = (struct Arg **)sh_args, .args = (struct Arg **)sh_args,

View File

@ -31,8 +31,7 @@ static char *cmd_to_str(const char *cmd) {
return out; return out;
} }
TAG_CALLBACK(spp_set) static TAG_CALLBACK(spp_set) {
{
char *eq, *val = ""; char *eq, *val = "";
if (!echo[ifl]) { if (!echo[ifl]) {
return 0; return 0;
@ -50,13 +49,13 @@ TAG_CALLBACK(spp_set)
*eq = '\0'; *eq = '\0';
val = eq + 1; val = eq + 1;
} }
if (spp_var_set (buf, val) == -1) if (spp_var_set (buf, val) == -1) {
fprintf (stderr, "Invalid variable name '%s' at line %d\n", buf, lineno); fprintf (stderr, "Invalid variable name '%s' at line %d\n", buf, lineno);
}
return 0; return 0;
} }
TAG_CALLBACK(spp_get) static TAG_CALLBACK(spp_get) {
{
char *var; char *var;
if (!echo[ifl]) { if (!echo[ifl]) {
return 0; return 0;
@ -68,12 +67,12 @@ TAG_CALLBACK(spp_get)
return 0; return 0;
} }
TAG_CALLBACK(spp_getrandom) static TAG_CALLBACK(spp_getrandom) {
{
int max; int max;
if (!echo[ifl]) { if (!echo[ifl]) {
return 0; return 0;
} }
// XXX srsly? this is pretty bad random
srandom (getpid ()); // TODO: change this to be portable srandom (getpid ()); // TODO: change this to be portable
max = atoi (buf); max = atoi (buf);
if (max > 0) { if (max > 0) {
@ -83,8 +82,7 @@ TAG_CALLBACK(spp_getrandom)
return 0; return 0;
} }
TAG_CALLBACK(spp_add) static TAG_CALLBACK(spp_add) {
{
char res[32]; char res[32];
char *var, *eq = strchr (buf, ' '); char *var, *eq = strchr (buf, ' ');
int ret = 0; int ret = 0;
@ -106,8 +104,7 @@ TAG_CALLBACK(spp_add)
return 0; return 0;
} }
TAG_CALLBACK(spp_sub) static TAG_CALLBACK(spp_sub) {
{
char *eq = strchr(buf, ' '); char *eq = strchr(buf, ' ');
char *var; char *var;
int ret = 0; int ret = 0;
@ -127,8 +124,7 @@ TAG_CALLBACK(spp_sub)
} }
// XXX This method needs some love // XXX This method needs some love
TAG_CALLBACK(spp_trace) static TAG_CALLBACK(spp_trace) {
{
char b[1024]; char b[1024];
if (!echo[ifl]) return 0; if (!echo[ifl]) return 0;
snprintf(b, 1023, "echo '%s' >&2 ", buf); snprintf(b, 1023, "echo '%s' >&2 ", buf);
@ -137,16 +133,14 @@ TAG_CALLBACK(spp_trace)
} }
/* TODO: deprecate */ /* TODO: deprecate */
TAG_CALLBACK(spp_echo) static TAG_CALLBACK(spp_echo) {
{
if (!echo[ifl]) return 0; if (!echo[ifl]) return 0;
do_printf (out, "%s", buf); do_printf (out, "%s", buf);
// TODO: add variable replacement here?? not necessary, done by {{get}} // TODO: add variable replacement here?? not necessary, done by {{get}}
return 0; return 0;
} }
TAG_CALLBACK(spp_error) static TAG_CALLBACK(spp_error) {
{
if (!echo[ifl]) { if (!echo[ifl]) {
return 0; return 0;
} }
@ -154,8 +148,7 @@ TAG_CALLBACK(spp_error)
return -1; return -1;
} }
TAG_CALLBACK(spp_warning) static TAG_CALLBACK(spp_warning) {
{
if (!echo[ifl]) { if (!echo[ifl]) {
return 0; return 0;
} }
@ -163,18 +156,17 @@ TAG_CALLBACK(spp_warning)
return 0; return 0;
} }
TAG_CALLBACK(spp_system) static TAG_CALLBACK(spp_system) {
{ if (!echo[ifl]) {
char *str; return 0;
if (!echo[ifl]) return 0; }
str = cmd_to_str(buf); char *str = cmd_to_str (buf);
do_printf (out, "%s", str); do_printf (out, "%s", str);
free(str); free(str);
return 0; return 0;
} }
TAG_CALLBACK(spp_include) static TAG_CALLBACK(spp_include) {
{
char *incdir; char *incdir;
if (!echo[ifl]) { if (!echo[ifl]) {
return 0; return 0;
@ -196,16 +188,14 @@ TAG_CALLBACK(spp_include)
return 0; return 0;
} }
TAG_CALLBACK(spp_if) static TAG_CALLBACK(spp_if) {
{
char *var = spp_var_get(buf); char *var = spp_var_get(buf);
echo[ifl + 1] = (var && *var != '0' && *var != '\0') ? 1 : 0; echo[ifl + 1] = (var && *var != '0' && *var != '\0') ? 1 : 0;
return 1; return 1;
} }
/* {{ ifeq $path / }} */ /* {{ ifeq $path / }} */
TAG_CALLBACK(spp_ifeq) static TAG_CALLBACK(spp_ifeq) {
{
char *value = buf; char *value = buf;
char *eq = strchr(buf, ' '); char *eq = strchr(buf, ' ');
if (eq) { if (eq) {
@ -225,8 +215,7 @@ TAG_CALLBACK(spp_ifeq)
return 1; return 1;
} }
TAG_CALLBACK(spp_hex) static TAG_CALLBACK(spp_hex) {
{
int i; int i;
for(i = 0; buf[i]; i++) { for(i = 0; buf[i]; i++) {
if (buf[i] >= '0' && buf[i] <= '9') { if (buf[i] >= '0' && buf[i] <= '9') {
@ -243,8 +232,7 @@ TAG_CALLBACK(spp_hex)
return 0; return 0;
} }
TAG_CALLBACK(spp_grepline) static TAG_CALLBACK(spp_grepline) {
{
FILE *fd; FILE *fd;
char b[1024]; char b[1024];
char *ptr; char *ptr;
@ -268,23 +256,22 @@ TAG_CALLBACK(spp_grepline)
return 0; return 0;
} }
TAG_CALLBACK(spp_else) static TAG_CALLBACK(spp_else) {
{
echo[ifl] = echo[ifl] ? 0 : 1; echo[ifl] = echo[ifl] ? 0 : 1;
return 0; return 0;
} }
TAG_CALLBACK(spp_ifnot) static TAG_CALLBACK(spp_ifnot) {
{
spp_if (buf, out); spp_if (buf, out);
spp_else (buf, out); spp_else (buf, out);
return 1; return 1;
} }
TAG_CALLBACK(spp_ifin) static TAG_CALLBACK(spp_ifin) {
{
char *var, *ptr; char *var, *ptr;
if (!echo[ifl]) return 1; if (!echo[ifl]) {
return 1;
}
ptr = strchr (buf, ' '); ptr = strchr (buf, ' ');
echo[ifl + 1] = 0; echo[ifl + 1] = 0;
if (ptr) { if (ptr) {
@ -297,13 +284,11 @@ TAG_CALLBACK(spp_ifin)
return 1; return 1;
} }
TAG_CALLBACK(spp_endif) static TAG_CALLBACK(spp_endif) {
{
return -1; return -1;
} }
TAG_CALLBACK(spp_default) static TAG_CALLBACK(spp_default) {
{
if (!echo[ifl]) { if (!echo[ifl]) {
return 0; return 0;
} }
@ -315,38 +300,35 @@ TAG_CALLBACK(spp_default)
static FILE *spp_pipe_fd = NULL; static FILE *spp_pipe_fd = NULL;
TAG_CALLBACK(spp_pipe) static TAG_CALLBACK(spp_pipe) {
{
spp_pipe_fd = popen (buf, "w"); spp_pipe_fd = popen (buf, "w");
return 0; return 0;
} }
static char *spp_switch_str = NULL; static char *spp_switch_str = NULL;
TAG_CALLBACK(spp_switch) static TAG_CALLBACK(spp_switch) {
{
char *var = spp_var_get (buf); char *var = spp_var_get (buf);
if (var) if (var) {
spp_switch_str = strdup (var); spp_switch_str = strdup (var);
else spp_switch_str = strdup (""); } else {
spp_switch_str = strdup ("");
}
return 1; return 1;
} }
TAG_CALLBACK(spp_case) static TAG_CALLBACK(spp_case) {
{
echo[ifl] = strcmp (buf, spp_switch_str)?0:1; echo[ifl] = strcmp (buf, spp_switch_str)?0:1;
return 0; return 0;
} }
TAG_CALLBACK(spp_endswitch) static TAG_CALLBACK(spp_endswitch) {
{
free (spp_switch_str); free (spp_switch_str);
spp_switch_str = NULL; spp_switch_str = NULL;
return -1; return -1;
} }
TAG_CALLBACK(spp_endpipe) static TAG_CALLBACK(spp_endpipe) {
{
/* TODO: Get output here */ /* TODO: Get output here */
int ret = 0, len = 0; int ret = 0, len = 0;
int outlen = 4096; int outlen = 4096;
@ -369,8 +351,7 @@ TAG_CALLBACK(spp_endpipe)
return 0; return 0;
} }
PUT_CALLBACK(spp_fputs) static PUT_CALLBACK(spp_fputs) {
{
if (spp_pipe_fd) { if (spp_pipe_fd) {
fprintf (spp_pipe_fd, "%s", buf); fprintf (spp_pipe_fd, "%s", buf);
} else { } else {
@ -379,7 +360,7 @@ PUT_CALLBACK(spp_fputs)
return 0; return 0;
} }
struct Tag spp_tags[] = { static struct Tag spp_tags[] = {
{ "get", spp_get }, { "get", spp_get },
{ "hex", spp_hex }, { "hex", spp_hex },
{ "getrandom", spp_getrandom }, { "getrandom", spp_getrandom },
@ -408,30 +389,30 @@ struct Tag spp_tags[] = {
{ NULL } { NULL }
}; };
ARG_CALLBACK(spp_arg_i) static ARG_CALLBACK(spp_arg_i) {
{
r_sys_setenv ("SPP_INCDIR", arg); r_sys_setenv ("SPP_INCDIR", arg);
return 0; return 0;
} }
ARG_CALLBACK(spp_arg_d) static ARG_CALLBACK(spp_arg_d) {
{
/* TODO: Handle error */ /* TODO: Handle error */
char *eq = strchr (arg, '='); char *eq = strchr (arg, '=');
if (eq) { if (eq) {
*eq = '\0'; *eq = '\0';
spp_var_set (arg, eq+1); spp_var_set (arg, eq+1);
} else spp_var_set (arg, ""); } else {
spp_var_set (arg, "");
}
return 0; return 0;
} }
struct Arg spp_args[] = { static struct Arg spp_args[] = {
{ "-I", "add include directory", 1, spp_arg_i }, { "-I", "add include directory", 1, spp_arg_i },
{ "-D", "define value of variable", 1, spp_arg_d }, { "-D", "define value of variable", 1, spp_arg_d },
{ NULL } { NULL }
}; };
struct Proc spp_proc = { DLL_LOCAL struct Proc spp_proc = {
.name = "spp", .name = "spp",
.tags = (struct Tag **)spp_tags, .tags = (struct Tag **)spp_tags,
.args = (struct Arg **)spp_args, .args = (struct Arg **)spp_args,

View File

@ -28,12 +28,16 @@ extern int ifl;
extern int echo[MAXIFL]; extern int echo[MAXIFL];
extern int lineno; extern int lineno;
#ifndef DLL_LOCAL
#define DLL_LOCAL __attribute__ ((visibility ("hidden")))
#endif
#define GET_ARG(x,y,i) if (y[i][2]) x = y[i] + 2; else x = y[++i] #define GET_ARG(x,y,i) if (y[i][2]) x = y[i] + 2; else x = y[++i]
#define DEFAULT_PROC(x) \ #define DEFAULT_PROC(x) \
struct Tag *tags = (struct Tag *)&x##_tags; \ DLL_LOCAL struct Tag *tags = (struct Tag *)&x##_tags; \
struct Arg *args = (struct Arg *)&x##_args; \ DLL_LOCAL struct Arg *args = (struct Arg *)&x##_args; \
struct Proc *proc = &x##_proc; DLL_LOCAL struct Proc *proc = &x##_proc;
typedef struct { typedef struct {
RStrBuf *cout; RStrBuf *cout;