/* * dialog.c V2.1 (May 1993) * * The main interactive part of MaGIC.c. This module contains * some of the procedures to be executed in response to menu * selections, most of the others being in getjob.c. */ /**************************************************************** * * * MaGIC 2.1 * * * * (C) 1993 Australian National University * * * * All rights reserved * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by the * * Australian National University. The Australian National Uni- * * versity makes no representations about the suitability of * * this software for any purpose. It is supplied "as is" without * * express or implied warranty. If the software is modified in * * a manner creating derivative copyright rights, appropriate * * legends may be placed on the derivative work in addition to * * that set forth above. * * * * Permission to use, copy, modify and distribute this software * * and its documentation for any purpose and without fee is * * hereby granted, provided that both the above copyright notice * * and this permission notice appear in all copies and sup- * * porting documentation, and that the name of the Australian * * National University not be used in advertising or publicity * * pertaining to distribution of the software without specific, * * written prior permission. * * * ****************************************************************/ #include "MaGIC.h" /* * The dialog function gets the job specifications from the * user, setting up theJob accordingly. It returns 1 if * option 'g' is selected from the menu, 0 if 'e' or 'q' is * selected and n > 1 to change (in the parallel case) to n * processes. */ int dialog(boolean batch, char *batchfile) { if ( batch ) return read_job( batchfile ); for(;;) switch( menu() ) { case 'a': add_axioms(); break; case 'b': bad_guy(); break; case 'c': connective(); break; case 'd': deletion(); break; case 'e': case 'q': return 0; case 'f': fragment(); break; case 'g': return 1; case 'h': help(0); paws(); break; case 'i': input_direct(); break; case 'j': jump_condition(); break; case 'k': job_defaults(batch); break; case 'l': logic_choice(); break; case 'm': print_version(); break; case 'n': case '#': return n_of_procs(); case 'o': order_change(); break; case 'p': print_options(); break; case 'r': read_job( 0 ); break; case 's': store_job(); } } /* * Menu first ensures that the fragment is consistent with the * selected logic, axioms and badguy. Then it displays the * currently selected job and the menu. Finally it takes the * next user choice of menu selection and returns the character * code for the next action. */ char menu() { char readin(); set_frag( true ); if ( xdialog ) { printf("J\n"); outjob( stdout ); } else display(); return readin("abcdefghijklmnopqrst#"); } /* * Readin returns the first character from stdin which matches * one in its parameter, converting to lower case as required. * It then discards all characters up to and including the next * line feed. It is used mainly to get menu selections. */ char readin(char *str) { char ch; int i; fflush(stdout); for(;;) { fgets(answer,SLEN,stdin); ch = 0; for ( i = 0; answer[i]; i++ ) { if ( isupper(ch = answer[i]) ) ch = tolower(ch); if ( strchr(str,ch) ) return ch; } } } /* * "Pause". */ void paws() { if ( xdialog ) fflush(stdout); else { printf("\n\n Now type RETURN to continue........."); READLN; } } /* * Job_defaults is the initialisation procedure. It gets the * initial choice of system and sets theJob to its defaults. */ void job_defaults( boolean batch ) { int i, j; zero = 0; for ( i = 0; i < SYMBOLMAX; i++ ) { strcpy( theJob->symtable[i].s, "" ); theJob->symtable[i].last = theJob->symtable[i].next = 0; } for ( i = 0; i < 3; i++ ) for ( j = 0; j < CMAX+8; j++ ) theJob->symbol[i][j] = 0; theJob->symtab = 0; newsymbol( "(", 0, 0 ); newsymbol( ")", 0, 0 ); newsymbol( ".", 0, 0 ); newsymbol( "a", 0, 0 ); newsymbol( "b", 0, 0 ); newsymbol( "t", theJob->symbol[0], 0 ); newsymbol( "f", theJob->symbol[0], 0 ); newsymbol( "T", theJob->symbol[0], 0 ); newsymbol( "F", theJob->symbol[0], 0 ); newsymbol( "~", theJob->symbol[1], 0 ); newsymbol( "!", theJob->symbol[1], 0 ); newsymbol( "?", theJob->symbol[1], 0 ); newsymbol( "o", theJob->symbol[2], 0 ); newsymbol( "&", theJob->symbol[2], 0 ); newsymbol( "v", theJob->symbol[2], 0 ); newsymbol( "->", theJob->symbol[2], 0 ); strcpy( theJob->data_dir, DATA_DIR ); for ( i = 0; i <= CMAX; i++ ) { theJob->dcs[i] = 0; if ( i < CMAX ) { theJob->defcon[i] = 0; theJob->concut[i] = false; } } for ( i = 0; i < TMAX; i++ ) for ( j = 0; j < RTMAX; j++ ) theJob->croot[i][j] = theJob->proot[i][j] = 0; theJob->failure = 0; for ( i = 1; i < AXMAX; i++ ) theJob->axiom[i] = 0; theJob->tty_out = PRETTY; theJob->fil_out = NONE; theJob->outfil_name[0] = '\0'; theJob->maxmat = 0; theJob->maxtime = 0; Sizmax = theJob->sizmax = SZ; theJob->sizmax_ismax = true; wff_initial(); if ( !batch ) { if ( !noclear ) { #ifdef __CYGWIN__ puts("\033[2J"); #else system("clear"); #endif } theJob->logic = FD; if ( !xdialog ) { printf("\n This is MaGIC %s, finding matrices for", VERSION); printf(" your favourite logic.\n"); printf(" Matrices come in all sizes up to %dx%d.\n", SZ,SZ); logic_choice(); } } } /* * Set_frag makes the selected fragment include all the used * connectives and sets Sizmax accordingly. */ void set_frag( boolean set_sizmax ) { int i, j; for ( i = 0; i < AXMAX; i++ ) if ( theJob->axiom[i] ) { if ( strchr(ax_string[i],'~') || strchr(ax_string[i],'f') || strchr(ax_string[i],'?') ) theJob->f_n = 1; if ( strchr(ax_string[i],'t') || strchr(ax_string[i],'f') ) theJob->f_t = 1; if ( strchr(ax_string[i],'&') || strchr(ax_string[i],'v') ) theJob->f_lat = 1; if ( strchr(ax_string[i],'!') || strchr(ax_string[i],'?') ) theJob->f_nec = 1; if ( i == AxK || i == AxK2 || i == AxTF ) theJob->f_T = theJob->f_t = 1; } if ( theJob->f_n && valid[theJob->logic][AxC] ) theJob->f_fus = 1; for ( i = 0; theJob->croot[i][0]; i++ ) { for ( j = 0; theJob->croot[i][j]; j++ ) if ( theJob->croot[i][j] != ABSURD ) check_frag(theJob->croot[i][j]); for ( j = 0; theJob->proot[i][j]; j++ ) if ( theJob->proot[i][j] != TRIVIAL ) check_frag(theJob->proot[i][j]); } if ( theJob->failure ) check_frag(theJob->failure); for ( i = 0; theJob->dcs[i]; i++ ) if ( theJob->defcon[i] != PRIMITIVE ) check_frag(theJob->defcon[i]); if ( theJob->totord ) theJob->f_lat = 1; if ( theJob->f_lat ) theJob->f_t = theJob->f_T = theJob->f_F = 1; if (( theJob->f_F || theJob->f_T ) && theJob->f_n ) theJob->f_F = theJob->f_T = 1; F_N = ((theJob->f_n && valid[theJob->logic][AxFN]) || theJob->axiom[AxFN]); afx = ((valid[theJob->logic][RulPref] && valid[theJob->logic][RulSuff]) || (theJob->axiom[RulPref] && theJob->axiom[RulSuff])); if ( set_sizmax ) { if ( !(theJob->f_lat || theJob->f_n) ) Sizmax = theJob->f_t? S_pot: S_pO; else if ( !theJob->f_lat ) Sizmax = theJob->f_t? S_pont: S_poN; else if ( !theJob->distrib ) Sizmax = theJob->f_n? S_ln: S_lat; else if ( !theJob->totord ) Sizmax = ((theJob->f_n && theJob->logic==S4) || theJob->axiom[AxBA])? S_ba: (theJob->f_n? S_dln: S_dlat); else Sizmax = theJob->f_n? S_Ton: S_to; if ( theJob->sizmax > Sizmax || theJob->sizmax_ismax ) theJob->sizmax = Sizmax; } } /* * This function adds to the fragment any connectives which * occur in the given formula. It attends to the main * connective only, calling itself recursively to deal with * the subformulae. */ void check_frag(int x) { if (!x) return; if (!theJob->form[x].sym->s[1]) { switch(theJob->form[x].sym->s[0]) { case '~': theJob->f_n = 1; break; case 'f': theJob->f_n = 1; case 't': theJob->f_t = 1; break; case 'T': theJob->f_T = 1; break; case 'F': theJob->f_F = 1; break; case 'o': theJob->f_fus = 1; break; case '?': theJob->f_n = 1; case '!': theJob->f_nec = 1; break; case '&': case 'v': theJob->f_lat = 1; } } check_frag(theJob->form[x].lsub); check_frag(theJob->form[x].rsub); } /* * Print_axiom just writes out axiom #x on stream f. */ void print_axiom(FILE *f, AXIOM x) { fprintf(f, "%s", ax_string[x]); } /* * Display shows the current choices and the menu. */ void display() { if ( !noclear ) { #ifdef __CYGWIN__ puts("\033[2J"); #else system("clear"); #endif } disp(stdout); printf(" A)xiom B)adguy C)onnective D)elete\n"); printf(" E)xit F)ragment G)enerate H)elp\n"); printf(" I)O J)ump K)ill L)ogic\n"); printf(" M)aGIC N)o. Procs O)rder P)rint Opts\n"); printf(" Q)uit R)ead S)tore "); } /* * Disp is the function to print an account of the current * contents of theJob. It is to have verbose and terse modes. */ void disp(FILE *f) { AXIOM ax; int i, j; boolean b; #ifdef PARALLEL fprintf(f, "\n Parallel MaGIC running %d out of %d processes\n", gm->nprocs, PARALLEL); #endif if ( theJob->totord && default_orders[theJob->logic] != total_orders ) fprintf(f, "\n Logic:%8cT%s", ' ', logic_name[theJob->logic]); else if ( theJob->distrib && default_orders[theJob->logic] != distributive_lattices ) fprintf(f, "\n Logic:%8cD%s", ' ', logic_name[theJob->logic]); else if ( !theJob->distrib && default_orders[theJob->logic] != lattices ) fprintf(f, "\n Logic:%8cL%s", ' ', logic_name[theJob->logic]); else fprintf(f, "\n Logic:%8c%s", ' ', logic_name[theJob->logic]); b = false; for ( ax = AxNull+1; ax < AXMAX; ax++ ) if ( theJob->axiom[ax] ) { if ( !b ) { b = true; fprintf(f, "\n\n Plus: "); } else fprintf(f, "\n "); print_axiom(f,ax); } for ( i = 0; theJob->croot[i][0]; i++ ) { if ( i ) fprintf(f, "\n "); else fprintf(f, "\n\n Extra: "); for ( j = 0; theJob->proot[i][j]; j++ ) { if ( j ) fprintf(f, ", "); if ( theJob->proot[i][j] != TRIVIAL ) outfml(theJob->proot[i][j], theJob->proot[i][j],f); } if ( theJob->proot[i][0] != TRIVIAL ) fprintf(f, " / "); for ( j = 0; theJob->croot[i][j]; j++ ) { if ( j ) fprintf(f, ", "); if ( theJob->croot[i][j] != ABSURD ) outfml(theJob->croot[i][j], theJob->croot[i][j],f); } } fprintf(f, "\n\n Fragment: ->"); if ( theJob->f_lat ) fprintf(f, ", &, v"); if ( theJob->f_n ) fprintf(f, ", ~"); if ( theJob->f_fus ) fprintf(f, ", o"); if ( theJob->f_nec ) { fprintf(f, ", !"); if ( theJob->f_n ) fprintf(f, ", ?"); } if ( theJob->f_t ) { fprintf(f, ", t"); if ( theJob->f_n ) fprintf(f, ", f"); } if ( theJob->f_T ) fprintf(f, ", T"); if ( theJob->f_F ) fprintf(f, ", F"); for ( i = 0; theJob->defcon[i]; i++ ) { if ( i ) fprintf(f, "\n "); else if ( !theJob->defcon[1] ) fprintf(f, "\n\n Definition: "); else fprintf(f, "\n\n Definitions:"); if ( !theJob->adicity[i] ) fprintf(f, " %s ", theJob->dcs[i]->s); else if ( theJob->adicity[i] == 1 ) { if ( theJob->dcs[i]->s[1] ) fprintf(f, " %s a ", theJob->dcs[i]->s); else fprintf(f, " %sa ", theJob->dcs[i]->s); } else fprintf(f, " a %s b ", theJob->dcs[i]->s); if ( theJob->defcon[i] == PRIMITIVE ) { fprintf(f, "Primitive"); if ( theJob->concut[i] ) fprintf(f, " (cut)"); } else outfml(theJob->defcon[i], theJob->defcon[i],f); } if ( theJob->failure ) { fprintf(f, "\n\n Fail: "); outfml(theJob->failure, theJob->failure, f); } fprintf(f, "\n\n TTY output: %s\n File output: %s", (theJob->tty_out==NONE? "none": (theJob->tty_out==UGLY? "ugly": (theJob->tty_out==PRETTY? "pretty": "summary"))), (theJob->fil_out==NONE? "none": (theJob->fil_out==UGLY? "ugly": (theJob->fil_out==PRETTY? "pretty": "summary")))); if ( theJob->fil_out ) fprintf(f,"\n Output file: \"%s\"", theJob->outfil_name); fprintf(f, "\n\n Search concludes "); if (theJob->maxtime) fprintf(f, "after %d seconds\n or ", theJob->maxtime); if (theJob->maxmat) fprintf(f, "when %d matri%s found\n or ", theJob->maxmat, (theJob->maxmat==1? "x": "ces")); fprintf(f, "when size %d finished.\n\n\n", theJob->sizmax); } /* * The Help facility is extremely primitive. It simply transfers * the contents of a short file to stdout. The parameter codes * the place in the program from which the Help call was made. */ void help(helpcode x) { switch( x ) { case MEN: put_out("MEN"); break; case WFF1: case WFF2: put_out("WFF"); break; case FDL: put_out("FDL"); break; case BTW: put_out("BTW"); break; case LOG: put_out("LOG"); break; case OUT: put_out("OUT"); break; case HELPMAX: break; } } /* * This is essentially a macro for Help (above). * It prepends the data directory name, appends ".show" * and does the file transfer. * * If we are in terse mode, nothing happens because the * front end xmagic has its own Help routine. */ void put_out(char *f_nm) { FILE *f1; char s[100]; if ( !noclear ) { #ifdef __CYGWIN__ puts( "\033[2J" ); strcpy(s,DATA_DIR); strcat(s,f_nm); strcat(s,".show"); if ( (f1 = fopen(s,"r")) == NULL ) { printf("Cannot open %s.",s); } else { while (fgets(s,80,f1) != NULL) { printf("%s",s); } fclose(f1); } #else sprintf(s,"clear; more %s%s.show", DATA_DIR, f_nm); system( s ); #endif } }