/* sentence.c by Michael Thorpe 2001-07-20 */ #include #include #include #include #include #include #define LINE_SIZE 4096 #define COMMENT_CHAR '#' #define SENTENCE_CHAR '-' #define ADDCONST_CHAR '=' struct word { struct word *next; char word[1]; }; struct group { struct group *next; char name; int num; struct word *words; }; struct group *groups=0; int numsentences=0; char curgroup='\0'; int numerrs=0; int maxrecurse=10; struct group *findgroup(char c) { struct group *g; for(g=groups;g;g=g->next) if(g->name==c) break; if(0==g) { if(0==(g=(struct group *)malloc(sizeof(struct group)))) { perror("malloc"); exit(-1); } g->next=groups; g->name=c; g->num=0; g->words=0; groups=g; } return(g); } void addline(char *line) { struct group *g; struct word *w; g=findgroup(curgroup); if(0==(w=(struct word *)malloc(sizeof(struct word)+strlen(line)))) { perror("malloc"); exit(-1); } w->next=g->words; strcpy(w->word,line); g->words=w; g->num++; } int readfile(FILE *f) { char line[LINE_SIZE]; int i; while(line==fgets(line,LINE_SIZE,f)) { for(i=0;line[i] && COMMENT_CHAR != line[i] && '\n' != line[i];i++) ; if(line[i]) while(i>0 && isspace(line[i-1])) i--; line[i]='\0'; if(i==0) continue; if(line[0]=='[' && line[1] && line[2]==']' && !line[3]) curgroup=line[1]; else if(curgroup) addline(line); else numerrs++; } return(0); } char *findword(char c) { struct group *g; struct word *w; int i; g=findgroup(c); if(0==g->num) { fprintf(stderr,"error: Couldn't find any appropriate words! (looking for '%c')\n",c); numerrs++; return(0); } w=g->words; i=rand()%g->num; while(i--) w=w->next; return(w->word); } void addconst(char c,char *s) { struct group *g; struct word *w; int i,j; g=findgroup(c); for(i=j=0;s[i];i++) if(s[i]=='%') j++; j+=i; if(0==(w=(struct word *)malloc(sizeof(struct word)+j))) { perror("malloc"); exit(-1); } w->next=g->words; w->word[j]='\0'; while(i>0) { if(s[--i]=='%') w->word[--j]='%'; w->word[--j]=s[i]; } g->words=w; g->num++; } void tackon(char **s,int *sl,char *t,int tl) { char *u; u=(char *)realloc(*s,*sl+tl); if(!u) { perror("malloc"); exit(-1); } *s=u; memcpy(u+*sl,t,tl); *sl+=tl; } char *expandword(char *s) { char c,*e=0,*t; int capitalize=0,i,j,el=0; maxrecurse--; for(i=0;s[i];i++) { if(s[i]=='%' && s[i+1]) { i++; if(s[i]=='%') tackon(&e,&el,"%",1); else if(s[i]==SENTENCE_CHAR) capitalize=1; else { if(s[i]==ADDCONST_CHAR && s[i+1]) { c=s[++i]; i++; } if((t=findword(s[i]))) { if(maxrecurse) t=expandword(t); if(i>1 && s[i-2]==ADDCONST_CHAR) addconst(c,t); j=strlen(t); if(capitalize) { c=toupper(t[0]); tackon(&e,&el,&c,1); t++; j--; } tackon(&e,&el,t,j); if(maxrecurse) { if(capitalize) t--; free(t); } capitalize=0; } } } else { for(j=i;s[j] && s[j] != '%';j++) ; if(capitalize) { capitalize=0; c=toupper(s[i++]); tackon(&e,&el,&c,1); } tackon(&e,&el,s+i,j-i); i=j-1; } } maxrecurse++; tackon(&e,&el,"\0",1); return(e); } int main(int argc,char **argv) { int i=1; FILE *f; char *myenv=0; char *s; myenv=getenv("SENTENCE"); if((argc<2 && !myenv) || (argc==2 && !strcmp(argv[i],"-h"))) { printf("usage: sentence [-h] [-r <#>] [ [..]] (or set $SENTENCE)\n"); return(1); } if(argc>2 && !strcmp(argv[i],"-r") && isdigit(argv[i+1][0])) { maxrecurse=atoi(argv[++i]); i++; } if(argc<2 && myenv && (f=fopen(myenv,"r"))) { readfile(f); fclose(f); } for(;i