#include <stdarg.h>
#include <sys/types.h>
#include "quirc.h"
#include "hash.h"
#include "config.h"
#include "format.h"
#include "echo.h"
#include "channel.h"
#include <string>
#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;n<arguments;n++) {
args[argpos++]=va_arg(ap,char*);
}
va_end(ap);
return(fparsev(type, server, arguments, args));
}
char *fgetformat(const char *type) {
return hash_get(&formats,type);
}
char *fgetpathnames(const char *type, int server, int argc,
const char * const * argv) {
char *location;
char *newloc;
twindow window;
twindow *windowp;
twindow *windowp2;
tchan channel;
tchan *channelp;
int arg;
// errors should be handled here via bgerror
location=hash_get(&locations,type);
if(!location) {
// Replace this with an fparse'd or M_ error.
TT_Eval(TT_ARGS,"error {fdisplay: No location present for given display type.}");
return 0;
}
if(server==-1) {
if(!(newloc=strdup(TT_StrF(TT_ARGS,"set ::internal::junk \"%s\"",location)))) {
// Replace this with an fparse'd or M_ error.
TT_Eval(TT_ARGS,"error {fdisplay: Out of memory.}");
return 0;
}
windowp=0; /* Avoids a warning message. Make sure server!=-1 or
windowp!=0 before attempting to use the windowp pointer.
It will only be valid when called in a server manner. */
} else {
if(!(newloc=strdup(TT_StrF(TT_ARGS,"namespace eval ::%d \"set ::internal::junk \\\"%q\\\"\"",server,location)))) {
// Replace this with an fparse'd or M_ error.
TT_Eval(TT_ARGS,"error {fdisplay: Out of memory.}");
return 0;
}
if(!strcmp(newloc,"{}")) {
free(newloc);
if(!(newloc=strdup(""))) {
// Replace this with an fparse'd or M_ error.
TT_Eval(TT_ARGS,"error {fdisplay: Out of memory.}");
return 0;
}
}
sprintf(window.pathname,".status%d",server);
if(!(windowp=windows.find(window)) || !windowp->server) {
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;n<listc;n++) {
echo(result,listv[n],atoi(hash_get(&activate,type)));
}
Tcl_Free((char *)listv);
free(newloc);
}
void fdisplay(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;n<arguments;n++) {
args[argpos++]=va_arg(ap,char*);
}
va_end(ap);
fdisplayv(type, server, arguments, args);
}
int fexists(const char *type) {
return (int)*hash_get(&formats,type);
}
syntax highlighted by Code2HTML, v. 0.9.1