/* Build TLMP protocol analyser component from a proto file. A proto file contains one line per protocol command. The line start with the protocol verb followed by the name of all parameters. Special case: The parameter * means that a variable number of words is accepted. They will be passed to the application as a string (const char *) called extra. The parameter [ means that the following parameters are optional. They will be empty if missing. */ #include #include #include #include #include #include #include using namespace std; struct PROTO{ string command; // Name of the protocol command vector prms; // Name of the parameters unsigned min_prms; // Minimum number of parameters unsigned max_prms; // Maximum number bool any_extra; // There is not max_prm. Anything after min_prm // goes in the extra }; static void printargs (bool first_done, vector &args) { for (unsigned i=0; i argname){ char prev = argend[-1]; if (isalpha(prev) || isdigit(prev) || prev == '_'){ argend--; }else{ break; } } printf ("%s",argend); first_done = true; } } /* Convert the name into a valid C++ name. Change - for _ */ static void buildp_cnvtoc (const char *func, string &funcc) { while (*func != '\0'){ if (*func == '-'){ funcc += '_'; }else{ funcc += *func; } func++; } } int main (int argc, char *argv[]) { glocal int ret = -1; glocal const char *name = NULL; glocal vector args; glocal bool secretmode = false; glocal bool gomode = false; glocal.ret = (argc,argv); setproginfo ("buildp",VERSION,"Build TLMP protocol components"); setarg ('n',"name","Name of the component",glocal.name,true); setarg ('a',"arg","Extra arg passed to the component",glocal.args,false); setarg ('s',"secretmode","Extra processing to validate message signature",glocal.secretmode,false); setarg ('g',"gomode","Send a Go after every command",glocal.gomode,false); glocal vector lines; (argv[0],true); line = str_skip(line); if (line[0] != '\0' && line[0] != '#'){ vector tb; int n = str_splitline (line,' ',tb); if (n > 0){ PROTO p; p.command = tb[0]; p.min_prms = tb.size()-1; p.max_prms = p.min_prms; p.any_extra = false; for (unsigned i=1; i // Print a comment header explaining how the file was produced printf ("// Generated by the ./buildp utility with the following command\n"); printf ("// ./buildp"); if (glocal.gomode) printf (" --gomode"); if (glocal.secretmode) printf (" --secretmode"); for (unsigned i=0; i &tb = p.prms; printf ("\t#define _F_%s_%s(x) void x %s(bool &endserver, bool &endclient, const char *line",glocal.name,funcc,funcc); for (unsigned i=0; i _tb;\n"); printf ("\t\tint _n = str_splitline(_line,' ',_tb);\n"); printf ("\t\tif(_n==0){\n"); printf ("\t\t\t_c.invalid (_endserver,_endclient,_line"); printargs(true,glocal.args); printf (");\n"); if (glocal.secretmode){ printf ("\t\t}else if (fdpass_valid_secret(_secret,_line,_tb,_n)==-1){\n"); printf ("\t\t\t_intruder = time(NULL);\n"); } printf ("\t\t}else{\n"); printf ("\t\t\tconst char *_func = _tb[0].c_str();\n"); for (unsigned i=0; i=%u && _n<=%u){\n",func ,p.min_prms+1,p.max_prms+1); }else if (p.any_extra){ printf ("(strcmp(_func,\"%s\")==0 && _n>=%u){\n",func,p.max_prms+1); } for (unsigned j=p.min_prms; j%u) _extra += \" \";\n",p.min_prms+1); printf ("\t\t\t\t\t_extra += _tb[j];\n"); printf ("\t\t\t\t}\n"); } printf ("\t\t\t\t_c.%s(_endserver,_endclient,_line",funcc); for (unsigned i=1; i<=p.max_prms; i++){ printf (",_tb[%u].c_str()",i); } if (p.any_extra){ printf (",_extra.c_str()"); } printargs (true,glocal.args); printf (");\n"); if (glocal.gomode) printf ("\t\t\t\t_cc->send(\"Ok\\n\");\n"); } printf ("\t\t\t}else{\n"); printf ("\t\t\t\t_c.invalid (_endserver,_endclient,_line"); printargs(true,glocal.args); printf (");\n"); printf ("\t\t\t}\n"); printf ("\t\t}\n"); printf ("\t}\n"); printf ("}\n"); } return 0; return glocal.ret; }