X-Git-Url: https://git.jankratochvil.net/?p=timeplan.git;a=blobdiff_plain;f=timeplan.c;h=61d71f91fc3e64d3897675fb6b41e2071946350d;hp=7818e433278ea7adc771afb2f8eb4a3a2575631c;hb=0aa855d604bdacb2a88b4617e2f331f0f3387be1;hpb=69bfcea33fbdb28417d9eaa6e939aadd796ded23 diff --git a/timeplan.c b/timeplan.c index 7818e43..61d71f9 100644 --- a/timeplan.c +++ b/timeplan.c @@ -35,6 +35,7 @@ static char buf[LINE_MAX]; 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) { @@ -84,6 +85,7 @@ static int calctime(int timetot,int at,int of) static struct action { struct action *next; int timetot,stores; + unsigned long last_seq; char what[1]; } *hashtable[HASH_SIZE]; static int hashtable_tot=0; @@ -138,7 +140,7 @@ dump: if (action) printf("=%03d/%02d:%02d %4d\t%s\n",days,hours,mins, action->stores,action->what); - return(origtot); + return origtot; } #define A (*Ap) @@ -196,6 +198,8 @@ static void storeone(char *what,int length) { 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; @@ -211,6 +215,13 @@ struct action **actionp,*action; *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++; } @@ -227,8 +238,8 @@ static int iscondition(const char *text) 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) @@ -347,6 +358,7 @@ static char *modify(char *what) { 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; @@ -354,83 +366,104 @@ const struct textlist *item; 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) @@ -449,6 +482,7 @@ char *ce; else *ce='\0'; } storeone(what,length); + lifetime_seq++; } static void hit(time_t t,char *bufaction) @@ -635,5 +669,5 @@ const char *days[]={"Ne","Po","Ut","St","Ct","Pa","So"}; fprintf(ERRH1"fclose(3) \"%s\""ERRNO1,ERRH2,finame,ERRNO2); dumphashtable(); - return(EXIT_SUCCESS); + return EXIT_SUCCESS; }