static int line=0;
static enum { SORT_NO,SORT_TIMETOT,SORT_STORES } sortby=SORT_TIMETOT;
static unsigned lifetime_days=0;
+static unsigned long lifetime_seq=1;
static void usage(void)
{
static struct action {
struct action *next;
int timetot,stores;
+ unsigned long last_seq;
char what[1];
} *hashtable[HASH_SIZE];
static int hashtable_tot=0;
if (action)
printf("=%03d/%02d:%02d %4d\t%s\n",days,hours,mins,
action->stores,action->what);
- return(origtot);
+ return origtot;
}
#define A (*Ap)
{
struct action **actionp,*action;
+ if (!*what)
+ return;
if (verbose) printf("storeone: %d: %s\n",length,what);
for (actionp=hashtable+(calchash(what)%HASH_SIZE);(action=*actionp);actionp=&action->next)
if (!strcasecmp(action->what,what)) break;
*actionp=action;
hashtable_tot++;
}
+ else {
+ if (action->last_seq==lifetime_seq) {
+ if (verbose) puts("storeone: preventing duplicate");
+ return; /* prevent duplicates like: TV-Music --> TV-Fun-Music-Fun */
+ }
+ }
+ action->last_seq=lifetime_seq;
action->timetot+=length;
action->stores++;
}
struct textlist *cond;
for (cond=conditions;cond;cond=cond->next)
- if (!strcasecmp(text,cond->text)) return(1);
- return(0);
+ if (!strcasecmp(text,cond->text)) return 1;
+ return 0;
}
static void addlist(struct textlist ***tail,const char *text,int line)
{
regmatch_t matches[10];
int i,m;
+int doprep;
static char modbuf1[sizeof(buf)],modbuf2[sizeof(modbuf1)];
char *src=what,*dstbase=modbuf1,*dst=dstbase;
const char *start FAKEUSE,*end FAKEUSE,*patt;
if (verbose) printf("modify: %s\n",what);
modify_load();
- for (m=0,item=modifies;item;m++,item=item->next) {
+ for (m=0,item=modifies;;m++,item=item->next) {
enum { PATT_START,PATT_MID,PATT_END,PATT_TERM } pattpos;
- i=regexec(&modistructs[m].regex,src,LENGTH(matches),matches,0);
- if (i==REG_NOMATCH) continue;
- if (i) {
- fprintf(ERRH1"regexec() failed for \"%s\""ERRNO1,ERRH2,item->text,ERRNO2);
- exit(EXIT_FAILURE);
- }
- if (verbose) printf("matched: %s -> %s\n",item->text,modistructs[m].dst);
- pattpos=PATT_START; patt=NULL;
- while (pattpos!=PATT_TERM) {
- switch (pattpos) {
- case PATT_START:
- start=src;
- end=src+matches->rm_so;
- pattpos=PATT_MID; patt=modistructs[m].dst;
- break;
- case PATT_MID:
- if (!*patt) {
- pattpos=PATT_END; patt=NULL;
- continue;
+ for (doprep=1;doprep>=0;doprep--) {
+ if (doprep) {
+ *dst++='-';
+ for (patt=src;;patt++) {
+ if (*patt=='-' || !*patt) {
+ if (dst[-1]!='-')
+ *dst++='-';
+ if (!*patt)
+ break;
}
- else if (*patt=='@') {
- start=src; end=src+strlen(src);
- }
- else if (*patt>='0' && *patt<='9') {
-regmatch_t *match=matches+(*patt-'0');
- if (match->rm_so==-1
- || match->rm_eo==-1) {
- fprintf(ERRH1"Trying to substitute '%c' but no \"matches\" entry not set for \"%s\""WHERE1,
- ERRH2,*patt,item->text,WHERE2);
- exit(EXIT_FAILURE);
- }
- if (match->rm_so>match->rm_eo) {
- fprintf(ERRH1"Trying to substitute '%c' start>end (%d>%d) for \"%s\""WHERE1,
- ERRH2,*patt,match->rm_so,match->rm_eo,item->text,WHERE2);
- exit(EXIT_FAILURE);
- }
- start=src+match->rm_so; end=src+match->rm_eo;
+ else
+ *dst++=*patt;
+ }
+ }
+ else {
+ i=regexec(&modistructs[m].regex,src,LENGTH(matches),matches,0);
+ if (i==REG_NOMATCH) continue;
+ if (i) {
+ fprintf(ERRH1"regexec() failed for \"%s\""ERRNO1,ERRH2,item->text,ERRNO2);
+ exit(EXIT_FAILURE);
+ }
+ if (verbose) printf("matched: %s -> %s\n",item->text,modistructs[m].dst);
+ pattpos=PATT_START; patt=NULL;
+ while (pattpos!=PATT_TERM) {
+ switch (pattpos) {
+ case PATT_START:
+ start=src;
+ end=src+matches->rm_so;
+ pattpos=PATT_MID; patt=modistructs[m].dst;
+ break;
+ case PATT_MID:
+ if (!*patt) {
+ pattpos=PATT_END; patt=NULL;
+ continue;
+ }
+ else if (*patt=='@') {
+ start=src; end=src+strlen(src);
+ }
+ else if (*patt>='0' && *patt<='9') {
+ regmatch_t *match=matches+(*patt-'0');
+ if (match->rm_so==-1
+ || match->rm_eo==-1) {
+ fprintf(ERRH1"Trying to substitute '%c' but no \"matches\" entry not set for \"%s\""WHERE1,
+ ERRH2,*patt,item->text,WHERE2);
+ exit(EXIT_FAILURE);
+ }
+ if (match->rm_so>match->rm_eo) {
+ fprintf(ERRH1"Trying to substitute '%c' start>end (%d>%d) for \"%s\""WHERE1,
+ ERRH2,*patt,match->rm_so,match->rm_eo,item->text,WHERE2);
+ exit(EXIT_FAILURE);
+ }
+ start=src+match->rm_so; end=src+match->rm_eo;
+ }
+ else {
+ start=patt; end=patt+1;
+ }
+ patt++;
+ break;
+ case PATT_END:
+ start=src+matches->rm_eo;
+ end=src+strlen(src);
+ pattpos=PATT_TERM; /* assumed: patt=NULL; */
+ break;
+ default:
+ assert(0);
}
- else {
- start=patt; end=patt+1;
+ if ((dst-dstbase+(end-start))>=sizeof(modbuf1)-1/* -1 for '-' during prepping */) {
+ fprintf(ERRH1"Maximum buffer size exceeded during substition for \"%s\""WHERE1,
+ ERRH2,item->text,WHERE2);
+ exit(EXIT_FAILURE);
}
- patt++;
- break;
- case PATT_END:
- start=src+matches->rm_eo;
- end=src+strlen(src);
- pattpos=PATT_TERM; /* assumed: patt=NULL; */
- break;
- default:
- assert(0);
+ memcpy(dst,start,end-start);
+ dst+=end-start;
+ }
}
- if ((dst-dstbase+(end-start))>=sizeof(modbuf1)) {
- fprintf(ERRH1"Maximum buffer size exceeded during substition for \"%s\""WHERE1,
- ERRH2,item->text,WHERE2);
- exit(EXIT_FAILURE);
+/* SWAP buffers: */
+ if (dst==dstbase || (dst==dstbase+1 && *dstbase=='-'))
+ return NULL;
+ *dst='\0';
+ if (src==what) {
+ assert(dstbase==modbuf1);
+ src=dstbase;
+ dst=dstbase=modbuf2;
}
- memcpy(dst,start,end-start);
- dst+=end-start;
- }
- if (dst==dstbase) return(NULL);
- *dst='\0';
- if (src==what) {
- assert(dstbase==modbuf1);
- src=dstbase;
- dst=dstbase=modbuf2;
- }
- else {
-char *swap;
- assert((src==modbuf1 && dstbase==modbuf2)
- ||(src==modbuf2 && dstbase==modbuf1));
- swap=src; src=dstbase; dst=dstbase=swap;
- }
+ else {
+ char *swap;
+ assert((src==modbuf1 && dstbase==modbuf2)
+ ||(src==modbuf2 && dstbase==modbuf1));
+ swap=src; src=dstbase; dst=dstbase=swap;
+ }
+ if (!item)
+ return src;
+ } /* for (doprep) */
}
- return src;
+ /* NOTREACHED */
}
static void store(char *what,int length)
else *ce='\0';
}
storeone(what,length);
+ lifetime_seq++;
}
static void hit(time_t t,char *bufaction)
fprintf(ERRH1"fclose(3) \"%s\""ERRNO1,ERRH2,finame,ERRNO2);
dumphashtable();
- return(EXIT_SUCCESS);
+ return EXIT_SUCCESS;
}