18867Smckusick 2*41774Sbostic static char sccsid[] = " quiz.c 4.5 90/05/12 "; 38867Smckusick 48867Smckusick #include <stdio.h> 58867Smckusick #include <signal.h> 6*41774Sbostic #include "pathnames.h" 7*41774Sbostic 88867Smckusick #define NF 10 98867Smckusick #define NL 300 108867Smckusick #define NC 200 118867Smckusick #define SL 100 128867Smckusick #define NA 10 138867Smckusick 148867Smckusick int tflag; 158867Smckusick int xx[NL]; 168867Smckusick char score[NL]; 178867Smckusick int rights; 188867Smckusick int wrongs; 198867Smckusick int guesses; 208867Smckusick FILE *input; 218867Smckusick int nl = 0; 228867Smckusick int na = NA; 238867Smckusick int inc; 248867Smckusick int ptr = 0; 258867Smckusick int nc = 0; 268867Smckusick char line[150]; 278867Smckusick char response[100]; 288867Smckusick char *tmp[NF]; 298867Smckusick int select[NF]; 308867Smckusick 318867Smckusick readline() 328867Smckusick { 3333196Sbostic register int ch; 348867Smckusick char *t; 358867Smckusick loop: 3633196Sbostic for(t=line;(ch=getc(input))!=-1;t++) { 3733196Sbostic *t = ch; 388867Smckusick nc++; 398867Smckusick if(*t==' '&&(t==line||t[-1]==' ')) 408867Smckusick t--; 418867Smckusick if(*t=='\n') { 428867Smckusick if(t[-1]=='\\') /*inexact test*/ 438867Smckusick continue; 448867Smckusick while(t>line&&t[-1]==' ') 458867Smckusick *--t = '\n'; 468867Smckusick *++t = 0; 478867Smckusick return(1); 488867Smckusick } 498867Smckusick if(t-line>=NC) { 508867Smckusick printf("Too hard for me\n"); 518867Smckusick do { 5233196Sbostic if ((ch = getc(input)) == EOF) 538867Smckusick return(0); 5433196Sbostic } while(ch!='\n'); 5533196Sbostic *line = '\n'; 568867Smckusick goto loop; 578867Smckusick } 588867Smckusick } 598867Smckusick return(0); 608867Smckusick } 618867Smckusick 628867Smckusick char *eu; 638867Smckusick char *ev; 648867Smckusick cmp(u,v) 658867Smckusick char *u,*v; 668867Smckusick { 678867Smckusick int x; 688867Smckusick eu = u; 698867Smckusick ev = v; 708867Smckusick x = disj(1); 718867Smckusick if(x!=1) 728867Smckusick return(x); 738867Smckusick return(eat(1,0)); 748867Smckusick } 758867Smckusick 768867Smckusick disj(s) 778867Smckusick { 788867Smckusick int t, x; 798867Smckusick char *u; 808867Smckusick u = eu; 818867Smckusick t = 0; 828867Smckusick for(;;) { 838867Smckusick x = string(s); 848867Smckusick if(x>1) 858867Smckusick return(x); 868867Smckusick switch(*ev) { 878867Smckusick case 0: 888867Smckusick case ']': 898867Smckusick case '}': 908867Smckusick return(t|x&s); 918867Smckusick case '|': 928867Smckusick ev++; 938867Smckusick t |= s; 948867Smckusick s = 0; 958867Smckusick continue; 968867Smckusick } 978867Smckusick if(s) eu = u; 988867Smckusick if(string(0)>1) 998867Smckusick return(2); 1008867Smckusick switch(*ev) { 1018867Smckusick case 0: 1028867Smckusick case ']': 1038867Smckusick return(0); 1048867Smckusick case '}': 1058867Smckusick return(1); 1068867Smckusick case '|': 1078867Smckusick ev++; 1088867Smckusick continue; 1098867Smckusick default: 1108867Smckusick return(2); 1118867Smckusick } 1128867Smckusick } 1138867Smckusick } 1148867Smckusick 1158867Smckusick string(s) 1168867Smckusick { 1178867Smckusick int x; 1188867Smckusick for(;;) { 1198867Smckusick switch(*ev) { 1208867Smckusick case 0: 1218867Smckusick case '|': 1228867Smckusick case ']': 1238867Smckusick case '}': 1248867Smckusick return(1); 1258867Smckusick case '\\': 1268867Smckusick ev++; 1278867Smckusick if(*ev==0) 1288867Smckusick return(2); 1298867Smckusick if(*ev=='\n') { 1308867Smckusick ev++; 1318867Smckusick continue; 1328867Smckusick } 1338867Smckusick default: 1348867Smckusick if(eat(s,*ev)==1) 1358867Smckusick continue; 1368867Smckusick return(0); 1378867Smckusick case '[': 1388867Smckusick ev++; 1398867Smckusick x = disj(s); 1408867Smckusick if(*ev!=']' || x>1) 1418867Smckusick return(2); 1428867Smckusick ev++; 1438867Smckusick if(s==0) 1448867Smckusick continue; 1458867Smckusick if(x==0) 1468867Smckusick return(0); 1478867Smckusick continue; 1488867Smckusick case '{': 1498867Smckusick ev++; 1508867Smckusick x = disj(s); 1518867Smckusick if(*ev!='}'||x>1) 1528867Smckusick return(2); 1538867Smckusick ev++; 1548867Smckusick continue; 1558867Smckusick } 1568867Smckusick } 1578867Smckusick } 1588867Smckusick 1598867Smckusick eat(s,c) 1608867Smckusick char c; 1618867Smckusick { 1628867Smckusick if(*ev!=c) 1638867Smckusick return(2); 1648867Smckusick if(s==0) { 1658867Smckusick ev++; 1668867Smckusick return(1); 1678867Smckusick } 1688867Smckusick if(fold(*eu)!=fold(c)) 1698867Smckusick return(0); 1708867Smckusick eu++; 1718867Smckusick ev++; 1728867Smckusick return(1); 1738867Smckusick } 1748867Smckusick 1758867Smckusick fold(c) 1768867Smckusick char c; 1778867Smckusick { 1788867Smckusick if(c<'A'||c>'Z') 1798867Smckusick return(c); 1808867Smckusick return(c|040); 1818867Smckusick } 1828867Smckusick 1838867Smckusick publish(t) 1848867Smckusick char *t; 1858867Smckusick { 1868867Smckusick ev = t; 1878867Smckusick pub1(1); 1888867Smckusick } 1898867Smckusick 1908867Smckusick pub1(s) 1918867Smckusick { 1928867Smckusick for(;;ev++){ 1938867Smckusick switch(*ev) { 1948867Smckusick case '|': 1958867Smckusick s = 0; 1968867Smckusick ev; 1978867Smckusick continue; 1988867Smckusick case ']': 1998867Smckusick case '}': 2008867Smckusick case 0: 2018867Smckusick return; 2028867Smckusick case '[': 2038867Smckusick case '{': 2048867Smckusick ev++; 2058867Smckusick pub1(s); 2068867Smckusick ev; 2078867Smckusick continue; 2088867Smckusick case '\\': 2098867Smckusick if(*++ev=='\n') 2108867Smckusick continue; 2118867Smckusick default: 2128867Smckusick if(s) 2138867Smckusick putchar(*ev); 2148867Smckusick } 2158867Smckusick } 2168867Smckusick } 2178867Smckusick 2188867Smckusick segment(u,w) 2198867Smckusick char *u, *w[]; 2208867Smckusick { 2218867Smckusick char *s; 2228867Smckusick int i; 2238867Smckusick char *t; 2248867Smckusick s = u; 2258867Smckusick for(i=0;i<NF;i++) { 2268867Smckusick u = s; 2278867Smckusick t = w[i]; 2288867Smckusick while(*s!=':'&&*s!='\n'&&s-u<SL) { 2298867Smckusick if(*s=='\\') { 2308867Smckusick if(s[1] == '\n') { 2318867Smckusick s += 2; 2328867Smckusick continue; 2338867Smckusick } 2348867Smckusick *t++ = *s++; 2358867Smckusick } 2368867Smckusick *t++ = *s++; 2378867Smckusick } 2388867Smckusick 2398867Smckusick while(*s!=':'&&*s!='\n') 2408867Smckusick s++; 2418867Smckusick *t = 0; 2428867Smckusick if(*s++=='\n') { 2438867Smckusick return(i+1); 2448867Smckusick } 2458867Smckusick } 2468867Smckusick printf("Too many facts about one thing\n"); 2478867Smckusick } 2488867Smckusick 2498867Smckusick perm(u,m,v,n,p) 2508867Smckusick int p[]; 2518867Smckusick char *u[], *v[]; 2528867Smckusick { 2538867Smckusick int i, j; 2548867Smckusick int x; 2558867Smckusick for(i=0;i<m;i++) { 2568867Smckusick for(j=0;j<n;j++) { 2578867Smckusick x = cmp(u[i],v[j]); 2588867Smckusick if(x>1) badinfo(); 2598867Smckusick if(x==0) 2608867Smckusick continue; 2618867Smckusick p[i] = j; 2628867Smckusick goto uloop; 2638867Smckusick } 2648867Smckusick return(0); 2658867Smckusick uloop: ; 2668867Smckusick } 2678867Smckusick return(1); 2688867Smckusick } 2698867Smckusick 2708867Smckusick find(u,m) 2718867Smckusick char *u[]; 2728867Smckusick { 2738867Smckusick int n; 2748867Smckusick while(readline()){ 2758867Smckusick n = segment(line,tmp); 2768867Smckusick if(perm(u,m,tmp+1,n-1,select)) 2778867Smckusick return(1); 2788867Smckusick } 2798867Smckusick return(0); 2808867Smckusick } 2818867Smckusick 2828867Smckusick readindex() 2838867Smckusick { 2848867Smckusick xx[0] = nc = 0; 2858867Smckusick while(readline()) { 2868867Smckusick xx[++nl] = nc; 2878867Smckusick if(nl>=NL) { 2888867Smckusick printf("I've forgotten some of it;\n"); 2898867Smckusick printf("I remember %d items.\n", nl); 2908867Smckusick break; 2918867Smckusick } 2928867Smckusick } 2938867Smckusick } 2948867Smckusick 2958867Smckusick talloc() 2968867Smckusick { 2978867Smckusick int i; 29817680Sralph char *malloc(); 29917680Sralph 3008867Smckusick for(i=0;i<NF;i++) 3018867Smckusick tmp[i] = malloc(SL); 3028867Smckusick } 3038867Smckusick 3048867Smckusick main(argc,argv) 3058867Smckusick char *argv[]; 3068867Smckusick { 3078867Smckusick register j; 3088867Smckusick int i; 3098867Smckusick int x; 3108867Smckusick int z; 3118867Smckusick char *info; 3128867Smckusick int tvec[2]; 3138867Smckusick char *t; 3148867Smckusick extern done(); 3158867Smckusick int count; 316*41774Sbostic info = _PATH_INDEX; 3178867Smckusick time(tvec); 3188867Smckusick inc = tvec[1]&077774|01; 3198867Smckusick loop: 3208867Smckusick if(argc>1&&*argv[1]=='-') { 3218867Smckusick switch(argv[1][1]) { 3228867Smckusick case 'i': 3238867Smckusick if(argc>2) 3248867Smckusick info = argv[2]; 3258867Smckusick argc -= 2; 3268867Smckusick argv += 2; 3278867Smckusick goto loop; 3288867Smckusick case 't': 3298867Smckusick tflag = 1; 3308867Smckusick argc--; 3318867Smckusick argv++; 3328867Smckusick goto loop; 3338867Smckusick } 3348867Smckusick } 3358867Smckusick input = fopen(info,"r"); 3368867Smckusick if(input==NULL) { 3378867Smckusick printf("No info\n"); 3388867Smckusick exit(0); 3398867Smckusick } 3408867Smckusick talloc(); 3418867Smckusick if(argc<=2) 3428867Smckusick instruct(info); 3438867Smckusick signal(SIGINT,done); 3448867Smckusick argv[argc] = 0; 3458867Smckusick if(find(&argv[1],argc-1)==0) 3468867Smckusick dunno(); 3478867Smckusick fclose(input); 3488867Smckusick input = fopen(tmp[0],"r"); 3498867Smckusick if(input==NULL) 3508867Smckusick dunno(); 3518867Smckusick readindex(); 3528867Smckusick if(!tflag || na>nl) 3538867Smckusick na = nl; 3548867Smckusick stdout->_flag |= _IONBF; 3558867Smckusick for(;;) { 3568867Smckusick i = next(); 3578867Smckusick fseek(input,xx[i]+0L,0); 3588867Smckusick z = xx[i+1]-xx[i]; 3598867Smckusick for(j=0;j<z;j++) 3608867Smckusick line[j] = getc(input); 3618867Smckusick segment(line,tmp); 3628867Smckusick if(*tmp[select[0]] == '\0' || *tmp[select[1]] == '\0') { 3638867Smckusick score[i] = 1; 3648867Smckusick continue; 3658867Smckusick } 3668867Smckusick publish(tmp[select[0]]); 3678867Smckusick printf("\n"); 3688867Smckusick for(count=0;;count++) { 3698867Smckusick if(query(response)==0) { 3708867Smckusick publish(tmp[select[1]]); 3718867Smckusick printf("\n"); 3728867Smckusick if(count==0) wrongs++; 3738867Smckusick score[i] = tflag?-1:1; 3748867Smckusick break; 3758867Smckusick } 3768867Smckusick x = cmp(response,tmp[select[1]]); 3778867Smckusick if(x>1) badinfo(); 3788867Smckusick if(x==1) { 3798867Smckusick printf("Right!\n"); 3808867Smckusick if(count==0) rights++; 3818867Smckusick if(++score[i]>=1 && na<nl) 3828867Smckusick na++; 3838867Smckusick break; 3848867Smckusick } 3858867Smckusick printf("What?\n"); 3868867Smckusick if(count==0) wrongs++; 3878867Smckusick score[i] = tflag?-1:1; 3888867Smckusick } 3898867Smckusick guesses += count; 3908867Smckusick } 3918867Smckusick } 3928867Smckusick 3938867Smckusick query(r) 3948867Smckusick char *r; 3958867Smckusick { 3968867Smckusick char *t; 3978867Smckusick for(t=r;;t++) { 3988867Smckusick if(read(0,t,1)==0) 3998867Smckusick done(); 4008867Smckusick if(*t==' '&&(t==r||t[-1]==' ')) 4018867Smckusick t--; 4028867Smckusick if(*t=='\n') { 4038867Smckusick while(t>r&&t[-1]==' ') 4048867Smckusick *--t = '\n'; 4058867Smckusick break; 4068867Smckusick } 4078867Smckusick } 4088867Smckusick *t = 0; 4098867Smckusick return(t-r); 4108867Smckusick } 4118867Smckusick 4128867Smckusick next() 4138867Smckusick { 4148867Smckusick int flag; 4158867Smckusick inc = inc*3125&077777; 4168867Smckusick ptr = (inc>>2)%na; 4178867Smckusick flag = 0; 4188867Smckusick while(score[ptr]>0) 4198867Smckusick if(++ptr>=na) { 4208867Smckusick ptr = 0; 4218867Smckusick if(flag) done(); 4228867Smckusick flag = 1; 4238867Smckusick } 4248867Smckusick return(ptr); 4258867Smckusick } 4268867Smckusick 4278867Smckusick done() 4288867Smckusick { 42931539Sbostic if (rights + wrongs) { 43031539Sbostic printf("\nRights %d, wrongs %d, ", rights, wrongs); 43131539Sbostic if (guesses) 43231539Sbostic printf("extra guesses %d, ", guesses); 43331539Sbostic printf("score %d%%\n",100 * rights / (rights + wrongs)); 43431539Sbostic } 4358867Smckusick exit(0); 4368867Smckusick } 4378867Smckusick instruct(info) 4388867Smckusick { 4398867Smckusick char *t; 4408867Smckusick int i, n; 4418867Smckusick printf("Subjects:\n\n"); 4428867Smckusick while(readline()) { 4438867Smckusick printf("-"); 4448867Smckusick n = segment(line,tmp); 4458867Smckusick for(i=1;i<n;i++) { 4468867Smckusick printf(" "); 4478867Smckusick publish(tmp[i]); 4488867Smckusick } 4498867Smckusick printf("\n"); 4508867Smckusick } 4518867Smckusick printf("\n"); 4528867Smckusick input = fopen(info,"r"); 4538867Smckusick if(input==NULL) 4548867Smckusick abort(); 4558867Smckusick readline(); 4568867Smckusick segment(line,tmp); 4578867Smckusick printf("For example,\n"); 4588867Smckusick printf(" quiz "); 4598867Smckusick publish(tmp[1]); 4608867Smckusick printf(" "); 4618867Smckusick publish(tmp[2]); 4628867Smckusick printf("\nasks you a "); 4638867Smckusick publish(tmp[1]); 4648867Smckusick printf(" and you answer the "); 4658867Smckusick publish(tmp[2]); 4668867Smckusick printf("\n quiz "); 4678867Smckusick publish(tmp[2]); 4688867Smckusick printf(" "); 4698867Smckusick publish(tmp[1]); 4708867Smckusick printf("\nworks the other way around\n"); 4718867Smckusick printf("\nType empty line to get correct answer.\n"); 4728867Smckusick exit(0); 4738867Smckusick } 4748867Smckusick 4758867Smckusick badinfo(){ 4768867Smckusick printf("Bad info %s\n",line); 4778867Smckusick } 4788867Smckusick 4798867Smckusick dunno() 4808867Smckusick { 4818867Smckusick printf("I don't know about that\n"); 4828867Smckusick exit(0); 4838867Smckusick } 484