#include #include #include "quirc.h" #include "hash.h" #include "config.h" #include "format.h" #include "echo.h" #include "channel.h" #include #ifdef USING_STD_STRING using std::string; #endif #define NUMBER '0':\ case '1':\ case '2':\ case '3':\ case '4':\ case '5':\ case '6':\ case '7':\ case '8':\ case '9' char *fparse_result; static char buflow[20]; static char bufhigh[20]; static char *buflowp; static char *bufhighp; int append(char *low, char *high, string &assemble, int argc, const char * const * argv) { int start=atoi(low); int end=atoi(high); int n; char *dst; int flags; for(n=start;n<=end;n++) { if(n>=argc) return 1; dst=(char *)malloc(Tcl_ScanElement(argv[n],&flags)); if(!dst) return 1; flags|=TCL_DONT_USE_BRACES; Tcl_ConvertElement(argv[n], dst, flags); if(strcmp(dst,"{}")) { assemble+=dst; } free(dst); if(n!=end) assemble+="\\ "; } strcpy(buflow,"0"); sprintf(bufhigh,"%d",argc-1); bufhighp=bufhigh; buflowp=buflow; return 0; } char *fparsev(const char *type, int server, int argc, const char * const * argv) { // %X- %-X %X-Y %- %% // Replaces arguments with an escaped version of a space seperated arg list. // Argument is then evaluated within a set. // Return 0 if there is an error (ie. no arg for format number) // Set buflow to 0, bufhigh to argc-1 // N is number, D is default. // State 0: // Got nothing // %, go to state 1. // D, insert letter. // State 1: // Got % // %, simply insert a %, go back to state 0. // N, could be %X- %X %X-Y, set buflow to it, go to state 2. // -, could be %-X %-, go to state 3. // D, insert %, backup, go to state 0. // State 2: // Got %N // N, append to buflow, loop. // -, go to state 3 // D, insert argument buflow, backup, go to state 0. // State 3: // Got %- or %N- // N, set bufhigh to it, go to state 4. // D, insert buflow to bufhigh, backup, go to state 0. // State 4: // Got %-N or %N-N // N, append to bufhigh, loop. // D, insert buflow to bufhigh, backup, go to state 0. // Post loop processing is identical to default without backup or state 0 // stuff. string assemble; char *format; int n; int state=0; if(fparse_result) { free(fparse_result); fparse_result=0; } format=hash_get(&formats,type); if(!format) return 0; strcpy(buflow,"0"); sprintf(bufhigh,"%d",argc-1); bufhighp=bufhigh; buflowp=buflow; for(n=0;n<(signed)strlen(format);n++) { switch(state) { case 0: switch(format[n]) { case '%': state=1; break; default: assemble+=format[n]; } break; case 1: switch(format[n]) { case '%': assemble+='%'; state=0; break; case NUMBER: *(buflowp++)=format[n]; *buflowp=0; state=2; break; case '-': state=3; break; default: assemble+='%'; n--; state=0; } break; case 2: switch(format[n]) { case NUMBER: *(buflowp++)=format[n]; *buflowp=0; break; case '-': state=3; break; default: if(append(buflow,buflow,assemble,argc,argv)) return 0; n--; state=0; } break; case 3: switch(format[n]) { case NUMBER: *(bufhighp++)=format[n]; *bufhighp=0; break; default: if(append(buflow,bufhigh,assemble,argc,argv)) return 0; n--; state=0; } break; } } switch(state) { case 1: assemble+='%'; break; case 2: if(append(buflow,buflow,assemble,argc,argv)) return 0; break; case 3: if(append(buflow,bufhigh,assemble,argc,argv)) return 0; break; } if(server==-1) { return (fparse_result=strdup(TT_StrF(TT_ARGS,"set ::internal::junk \"%s\"",assemble.c_str()))); } else { return (fparse_result=strdup(TT_StrF(TT_ARGS,"namespace eval ::%d \"set ::internal::junk \\\"%q\\\"\"",server,assemble.c_str()))); } } char *fparse(char *type, int server, int arguments, ...) { char *args[100]; // Make this dynamic. int argpos=0; int n; va_list ap; // Error kludge if(arguments>100) { fprintf(stderr,"fparse argument limit hit. Contact author.\n"); exit(1); } va_start(ap,arguments); for(n=0;nserver) { free(newloc); TT_Eval(TT_ARGS,"error {fdisplay: Invalid server index.}"); return 0; } } if(!strncmp(newloc,"onchannel ",10)) { if((arg=atoi(newloc+10))>=argc) { free(newloc); TT_Eval(TT_ARGS,"error {fdisplay: No argument present for location format argument number.}"); return 0; } if(server==-1) { free(newloc); TT_Eval(TT_ARGS,"error {fdisplay: Cannot run server specific format globally.}"); return 0; } *newloc=0; strcpy(channel.name,argv[arg]); if((channelp=windowp->server->chanlist.find(channel))) { if(channelp->ison) { free(newloc); if(!(newloc=strdup(channelp->pathname))) { TT_Eval(TT_ARGS,"error {fdisplay: Out of memory.}"); return 0; } } } } if(!strncmp(newloc,"channelorstatus ",16)) { if((arg=atoi(newloc+16))>=argc) { free(newloc); TT_Eval(TT_ARGS,"error {fdisplay: No argument present for location format argument number.}"); return 0; } if(server==-1) { free(newloc); TT_Eval(TT_ARGS,"error {fdisplay: Cannot run server specific format globally.}"); return 0; } free(newloc); strcpy(channel.name,argv[arg]); if((channelp=windowp->server->chanlist.find(channel))) { if(!(newloc=strdup(channelp->pathname))) { TT_Eval(TT_ARGS,"error {fdisplay: Out of memory.}"); return 0; } } else { if(!(newloc=strdup(windowp->server->pathname))) { TT_Eval(TT_ARGS,"error {fdisplay: Out of memory.}"); return 0; } } } if(!strncmp(newloc,"chat ",5)) { if((arg=atoi(newloc+5))>=argc) { free(newloc); TT_Eval(TT_ARGS,"error {fdisplay: No argument present for location format argument number.}"); return 0; } if(server==-1) { free(newloc); TT_Eval(TT_ARGS,"error {fdisplay: Cannot run server specific format globally.}"); return 0; } free(newloc); windows.init_trav(); while((windowp2=windows.trav())) { if(windowp2->server==windowp->server&&windowp2->dcc) { if((!strcasecmp(windowp2->dcc->getnick(),argv[arg]))||(!strcasecmp(windowp2->name,argv[arg]))) { if(!(newloc=strdup(windowp2->pathname))) { TT_Eval(TT_ARGS,"error {fdisplay: Out of memory.}"); return 0; } } } } } if(!strncmp(newloc,"pathname ",9)) { if((arg=atoi(newloc+9))>=argc) { free(newloc); TT_Eval(TT_ARGS,"error {fdisplay: No argument present for location format argument number.}"); return 0; } free(newloc); if(!(newloc=strdup(argv[arg]))) { TT_Eval(TT_ARGS,"error {fdisplay: Out of memory.}"); return 0; } } return newloc; } void fdisplayv(const char *type, int server, int argc, const char * const * argv) { char *result; char *newloc; int listc; char **listv; int n; if(!(newloc = fgetpathnames(type,server,argc,argv))) return; if(!(result=fparsev(type,server,argc,argv))) { free(newloc); TT_Eval(TT_ARGS,"error {fparse: Error parsing format (No argument present for format argument number?).}"); return; } if(Tcl_SplitList(TT_Interp,newloc,&listc,(const char ***)&listv)==TCL_ERROR) { free(newloc); TT_Eval(TT_ARGS,"error {fdisplay: Given pathname argument is not a proper TCL list.}"); return; } for(n=0;n100) { fprintf(stderr,"fparse argument limit hit. Contact author.\n"); exit(1); } va_start(ap,arguments); for(n=0;n