#include <regex.h>
#define ACTS_MAX 20
-#define HASH_SIZE 211
+#define HASH_SIZE 971
#define CONFIGFILE "/.timeplanrc" /* HOME prepended */
#define DEF_TIMEPLAN "/.timeplan" /* HOME prepended */
#define MARK_DAY "_days"
#define ERRNO2 strerror(errno)
#define FAKEUSE =0
-static const char version[]="This is TimePlan, version 1.0\n";
+static const char version[]="This is TimePlan, version 1.0.1\n";
static const char *pname;
static char *finame;
static FILE *fi;
unsigned r=57;
while (*s) r=r*7+11*toupper(*s++);
+ r=r%HASH_SIZE;
return r;
}
if (!*what)
return;
if (verbose) printf("storeone: %d: %s\n",length,what);
- for (actionp=hashtable+(calchash(what)%HASH_SIZE);(action=*actionp);actionp=&action->next)
+ for (actionp=hashtable+calchash(what);(action=*actionp);actionp=&action->next)
if (!strcasecmp(action->what,what)) break;
if (!action) {
if (!(action=malloc(sizeof(*action)+strlen(what)))) {
{
regmatch_t matches[10];
int i,m;
-int doprep;
+int doprep,willprep;
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;;m++,item=item->next) {
+ for (m=0,item=modifies,willprep=1;;m++,item=item->next) {
enum { PATT_START,PATT_MID,PATT_END,PATT_TERM } pattpos;
- for (doprep=1;doprep>=0;doprep--) {
+ for (doprep=willprep;doprep>=0;doprep--) {
if (doprep) {
*dst++='-';
for (patt=src;;patt++) {
}
}
else {
+ if (!item)
+ return src;
i=regexec(&modistructs[m].regex,src,LENGTH(matches),matches,0);
- if (i==REG_NOMATCH) continue;
+ if (i==REG_NOMATCH) {
+ willprep=0;
+ break;
+ }
if (i) {
fprintf(ERRH1"regexec() failed for \"%s\""ERRNO1,ERRH2,item->text,ERRNO2);
exit(EXIT_FAILURE);
}
+ willprep=1;
if (verbose) printf("matched: %s -> %s\n",item->text,modistructs[m].dst);
pattpos=PATT_START; patt=NULL;
while (pattpos!=PATT_TERM) {
||(src==modbuf2 && dstbase==modbuf1));
swap=src; src=dstbase; dst=dstbase=swap;
}
- if (!item)
- return src;
} /* for (doprep) */
}
/* NOTREACHED */
}
+static struct modifycache {
+ struct modifycache *next;
+ char src[1]; /* dst[1] follows after '\0' */
+ } *mcachetable[HASH_SIZE];
+static unsigned long modifycache_hits;
+
+static char *modify_cached(char *what)
+{
+struct modifycache **mcachep,*mcache;
+char *dst;
+size_t whatl;
+
+ if (!*what)
+ return(NULL);
+ whatl=strlen(what);
+ if (verbose) printf("modify_cached: %s\n",what);
+ for (mcachep=mcachetable+calchash(what);(mcache=*mcachep);mcachep=&mcache->next)
+ if (!strcasecmp(mcache->src,what)) break;
+ if (!mcache) {
+ dst=modify(what);
+ if (!(mcache=malloc(sizeof(*mcache)+whatl+1+(dst?strlen(dst):0)))) {
+ fprintf(ERRH1"malloc() for \"%s\""ERRNO1,ERRH2,what,ERRNO2);
+ exit(EXIT_FAILURE);
+ }
+ mcache->next=NULL;
+ memcpy(mcache->src,what,whatl+1);
+ if (dst)
+ strcpy(mcache->src+whatl+1,dst);
+ else
+ mcache->src[whatl+1]='\0'; /* dst will be empty */
+ *mcachep=mcache;
+ }
+ else {
+ if (verbose) printf("cache hit.\n");
+ /* if (verbose) would be performance hit */
+ modifycache_hits++;
+ }
+ if (!mcache->src[whatl+1])
+ return(NULL);
+ return(mcache->src+whatl+1);
+}
+
+static void modify_cached_stats(void)
+{
+struct modifycache **mcachep,*mcache;
+unsigned long depth,maxdepth=0,entries_total=0;
+#define MODIFYCACHE_CALLS (modifycache_hits+entries_total)
+
+ for (mcachep=mcachetable;mcachep<mcachetable+HASH_SIZE;mcachep++) {
+ for (depth=0,mcache=*mcachep;mcache;mcache=mcache->next)
+ depth++;
+ if (depth>maxdepth)
+ maxdepth=depth;
+ entries_total+=depth;
+ }
+ printf("modify_cached cache stats: hits=%u.%02u%% (%lu/%lu), HASH_SIZE=%d, maxdepth=%lu\n",
+ (unsigned)( 100*modifycache_hits/MODIFYCACHE_CALLS ),
+ (unsigned)((10000*modifycache_hits/MODIFYCACHE_CALLS)%100),
+ modifycache_hits,MODIFYCACHE_CALLS,
+ HASH_SIZE,maxdepth);
+#undef MODIFYCACHE_CALLS
+}
+
static void store(char *what,int length)
{
-char *ce;
+char ce_trash,*ce,*ceo=&ce_trash;
- if (!(what=modify(what))) {
+ if (!(what=modify_cached(what))) {
if (verbose) puts("discarded.");
return;
}
if (verbose) printf("store: %d: %s\n",length,what);
- while ((ce=(tree?strrchr:strchr)(what,'-'))) {
+ while ((ce=(tree?strrchr(what,'-'):strchr(what,'-')))) {
if (!tree) *ce='\0';
storeone(what,length);
- if (!tree) what=ce+1;
- else *ce='\0';
+ if (!tree) { *ce='-'; what=ce+1; }
+ else { *ceo='-'; *(ceo=ce)='\0'; }
}
storeone(what,length);
+ if (tree) *ceo='-';
lifetime_seq++;
}
t=mktime(&tm);
if (t==-1 || tm.tm_wday<0 || tm.tm_wday>6
|| tm.tm_mday<1 || tm.tm_mday>31
- || tm.tm_mon <1 || tm.tm_mon >12
+ || tm.tm_mon <0 || tm.tm_mon >11
|| tm.tm_year<80 || tm.tm_year>150
) {
fprintf(ERRH1"Incorrect timestamp \"%s\""WHERE1,ERRH2,buf,WHERE2);
if (fi!=stdin && fclose(fi))
fprintf(ERRH1"fclose(3) \"%s\""ERRNO1,ERRH2,finame,ERRNO2);
+ if (verbose)
+ modify_cached_stats();
dumphashtable();
return EXIT_SUCCESS;
}