/* * cookie - The incredible fortune cookie system output program */ /* Version T1.00 - 01-Dec-86 - tmk - Initial portable version */ /* Version T1.01 - 06-Dec-86 - tmk - Fixup for VAX: Limit printf to 511 bytes, don't look past end of argv area, use curses for video mode out- put. For PC: fix null pointer prob- lem in sleep(), add q to exit from continuous cookie mode, interrogate environment for COOKIE if all else fails to find the file. General: clean up code. */ /* Version T1.02 - 07-Dec-86 - tmk - Fix -f name eating next argument, add video modes for PDP, fix problem on PC and PDP of improper line wrap in ANSI video modes */ /* Version T1.03 - 30-Mar-87 - tmk - Add setting of environment variable LASTCOOKIE on PC versions, -e option to inhibit same */ /* Version T1.04 - 18-Apr-87 - tmk - Set LASTCOOKIE on VAX version, cleanup by lint */ /* Version T1.05 - 17-May-87 - tmk - Clean up debugging information */ /* Version T1.06 - 27-May-87 - tmk - Cleanup, add DECtalk support */ /* Version T1.07 - 05-Jun-87 - tmk - Modify header structure, expand -i text, clean up messages */ /* Version T1.08 - 24-Jun-87 - tmk - Change file format, long swap code */ /* Version T1.09 - 02-Jul-87 - tmk - Add support for Turbo C */ /* Version T1.10 - 04-Jul-87 - tmk - Set LASTCOOKIE on RSTS version */ /* Version T1.11 - 14-Jul-87 - tmk - Change version no. to indicate mods to ASMCLS in PC versions */ /* Version T1.12 - 16-Jul-87 - tmk - Test for keypress during DOALL out- put of cookies on PC version, emit %% before first cookie in DOALL mode, add range (-r) option */ /* Version T1.13 - 15-Aug-87 - tmk - Support DECtalk on RSTS/E KB's via the BUGFIX.C add-on (DECUS C bugs), allow operation on real RT-11, polish DECtalk output routines */ /* Version T1.14 - 15-Nov-87 - tmk - Change random number generator for better values, add option to test generator, proving all cookies will eventually be displayed */ /* Version T1.15 - 27-Nov-87 - tmk - Fixups for MSC 5.0, make help fit on one screen again, add function pro- totypes, speed up -vx opt combo */ #define VERSION "T1.15 27-Nov-87 - tmk" /* * Define module ID for VMS (must go for Turbo C, else bogus error) */ #ifdef vms #module cookie VERSION #endif /* vms */ /* * Convince Turbo C it's running under MS-DOS (it isn't sure) */ #ifdef __TURBOC__ #define MSDOS 1 #endif /* __TURBOC__ */ /* * Grab lots of header files */ #include #include #include #ifndef decus #include #ifndef vms #include #endif /* vms */ #include #endif /* decus */ #ifdef MSDOS #ifndef __TURBOC__ #include #else #include #endif /* __TURBOC__ */ #include #endif /* MSDOS */ #ifdef vms #include #include #endif /* vms */ /* * Have a fight about function declarations, names, and file modes */ #ifdef __TURBOC__ #define cmpi stricmp #else #define cmpi strcmpi #endif /* __TURBOC__ */ #ifdef decus #define R_MODE "rn" #define void #else #define R_MODE "rb" #endif /* decus */ /* * Define some constants */ #define EOS 0 #define TRUE 1 #define FALSE 0 #ifdef decus #define SC_VT52 (64+1) #define EMT 0104000 #define DOCCL EMT+0367 #endif /* decus */ #ifdef vms #define exstat 65535 #else #define exstat 0 #endif /* vms */ /* * Define some externals */ #ifdef decus extern int $$rsts; extern long rand(); extern long seed; extern long time(); #endif /* decus */ /* * Global variables */ int doall = 0; /* Show all cookies */ long first = 0; /* First cookie of range */ long last = 0; /* Last cookie of range */ int video = 0; /* Utilize video mode */ int noenvset = 0; /* Don't set the LASTCOOKIE sym */ #ifdef MSDOS int ansivideo = 0; /* Use ANSI.SYS instead of BIOS */ int comport = 0; /* Comm. port for DECtalk */ #endif /* MSDOS */ #ifdef decus int isvt52 = 0; /* VT-52 vs. VT-100 flag */ #endif /* decus */ int notLong = 0; /* No Lazarus Long cookies */ int continuous = 0; /* Show 'em continuously */ int debug = 0; /* Are we showing debug info? */ int disp_version = 0; /* Display version of coofile */ int no_sleep = 1; /* Don't pause between cookies */ int offensive = 0; /* Don't show offensive cookies */ int long_sleep = 0; /* If sleeping, how long (secs) */ int linecount = 0; /* Number of lines in fortune */ char temp_text[81]; /* Temporary text buffer */ char envstr[32]; /* Holds the LASTCOOKIE string */ static int nvoice; static char voices[] = "pbhfkrudw"; /* Voices for DECtalk */ #ifdef MSDOS char envnam[128]; /* Stores SET COOKIE= string */ #endif /* MSDOS */ unsigned rndflg = 0; /* Randomness test mode flag */ int *rndtab; /* Randomizer test table */ char *namptr; FILE *cookfd = NULL; /* Cookie file */ FILE *extrafd = NULL; /* First output file */ #ifdef decus int talkfn = 0; /* DECtalk output channel */ #else FILE *talkfd = NULL; /* DECtalk output file */ #endif /* decus */ char *cookfile[] = { /* Cookie search list */ "cookie.fil", /* Current directory first */ "c:\\system\\cookie.fil", /* PC-DOS system directory */ "sys$manager:cookie.fil", /* Default cookie directory */ "public:cookie.fil", /* Various */ "pub:cookie.fil", /* public */ "sys$public:cookie.fil", /* directories */ "games:cookie.fil", /* Some */ "game:cookie.fil", /* games */ "sys$games:cookie.fil", /* directories */ NULL, }; char *coobfile[] = { /* Cookie search list */ "cookob.fil", /* Current directory first */ "c:\\system\\cookob.fil", /* PC-DOS system directory */ "sys$manager:cookob.fil", /* Default cookie directory */ "public:cookob.fil", /* Various */ "pub:cookob.fil", /* public */ "sys$public:cookob.fil", /* directories */ "games:cookob.fil", /* Some */ "game:cookob.fil", /* games */ "sys$games:cookob.fil", /* directories */ NULL, }; struct header { #ifdef vms short coover; /* Version of CAM structure */ short spare; /* Spare value (was password) */ long ncookie; /* Number of cookies */ short bcookie; /* Size of largest cookie */ short nindex; /* Dimension of index[] */ short subindex; /* Number of subindex entries */ short sindex; /* Sizeof index for alloc */ #else int coover; /* Version of CAM structure */ int spare; /* Spare value (was password) */ long ncookie; /* Number of cookies */ int bcookie; /* Size of largest cookie */ int nindex; /* Dimension of index[] */ int subindex; /* Number of subindex entries */ int sindex; /* Sizeof index for alloc */ #endif /* vms */ char date[28]; /* Date cookie file built */ } header; #define NCOOKIES (header.ncookie) #define TEXTSIZE 4096 #define INDEXMAX (TEXTSIZE / sizeof(long)) union { char text[TEXTSIZE]; /* Cookies stored here */ long index[INDEXMAX]; /* Cookie sub index entries */ } t; #ifdef MSDOS union REGS inreg,outreg; /* Processor registers */ #endif /* MSDOS */ /* * If only one cookie is needed, topindex[] can be overlayed over t.index[] */ long topindex[INDEXMAX]; /* Top index entries */ /* * For 'modern' compilers (all except decus), supply fucntion prototypes */ #ifndef decus extern int main(int, char **); extern void init(void); extern void setup_cookie(void); extern void rndchk(int, char *); extern int tbldun(int); extern void rerror(int, int, char *); extern void docookie(long); extern int isLong(char *); extern void antiheinlein(long); extern void output(long, char *); extern void speak(char *); extern void spit(int); extern void startoutput(long); extern void endoutput(void); extern void vtcurse(int, int); extern void erpage(void); extern void vtout(int, int, char *); #ifdef MSDOS #ifndef __TURBOC__ extern void sleep(int); #endif /* __TURBOC__ */ extern void kbtest(void); extern void comwait(int); extern int comrdy(int); extern int comsta(int); extern int cominp(int); extern void comout(int ,int); extern void EXEC2E(char *); extern void ASMCLS(void); #endif /* MSDOS */ extern void hswap(void); extern void swaplb(long *); extern long swapl(long); #endif /* decus */ /* * Actual code starts here */ int main(argc, argv) int argc; char *argv[]; { register int howmany; /* How many to do */ register char *ap; long which; long atol(); which = 0; while (argc > 1) { ap = argv[1]; if (isdigit(*ap) || (*ap == '-' && isdigit(ap[1]))) { which = atol(ap); continuous = 0; } else if (*ap != '-') { fprintf(stderr, "?Unknown command \"%s\"\n", ap); fprintf(stderr, " do COOKIE -? for help.\n\n\n"); } else for (ap++; *ap; ap++) { switch (tolower(*ap)) { case 'a': /* Do all cookies */ doall++; break; #ifdef MSDOS case 'b': /* Use ANSI.SYS for video */ ansivideo++; break; #endif /* MSDOS */ case 'c': /* Display continuously */ continuous++; break; case 'd': /* Display seek addresses */ debug++; break; case 'e': /* Don't set LASTCOOKIE var. */ noenvset++; break; case 'f': /* Use different cookie file */ if (isgraph(ap[1]) != 0) { #ifdef MSDOS namptr = &ap[1]; #endif /* MSDOS */ if ((cookfd = fopen(&ap[1], R_MODE)) == NULL) { perror(&ap[1]); exit(exstat); } } else if (argc > 2) { #ifdef MSDOS namptr = argv[2]; #endif /* MSDOS */ if ((cookfd = fopen(argv[2], R_MODE)) == NULL) { perror(argv[2]); exit(exstat); } argv++; argc--; } else { break; } goto next_arg; case 'h': /* No Lazarus Long cookies */ notLong++; break; case 'i': /* Display version of file */ disp_version++; break; case 'o': /* offensive cookie */ offensive++; break; case 'r': /* Show range of cookies */ if ( argc > 2 && isdigit(ap[1]) && isdigit(argv[2][0])) { doall++; first = atol(&ap[1]); last = atol(argv[2]); argv++; /* Skip next argument */ argc--; /* too. */ } else if (argc > 3 && isdigit(argv[2][0]) && isdigit(argv[3][0])) { doall++; first = atol(argv[2]); last = atol(argv[3]); argv += 2; /* Skip next two argument */ argc -= 2; /* too. */ } else { fprintf(stderr, "?Must specify start and end values \ for range.\n"); break; } goto next_arg; case 's': /* Sleep between cookies */ continuous++; no_sleep--; if (isdigit(ap[1])) { long_sleep = atoi(&ap[1]); } else if (argc > 2 && isdigit(argv[2][0])) { long_sleep = atoi(argv[2]); argv++; /* Skip next argument */ argc--; /* too. */ } else { long_sleep = 0; break; } goto next_arg; case 't': /* Output to DECtalk */ if (isgraph(ap[1]) != 0) { #ifdef MSDOS if (cmpi(&ap[1], "COM1") == 0) comport = 1; if (cmpi(&ap[1], "COM2") == 0) comport = 2; #endif /* MSDOS */ #ifndef decus if ((talkfd = fopen(&ap[1], "wn")) == NULL) { #else if ((talkfn = kb_open(&ap[1])) == NULL) { #endif /* decus */ perror(&ap[1]); exit(exstat); } } else if (argc > 2) { #ifdef MSDOS if (cmpi(argv[2], "COM1") == 0) comport = 1; if (cmpi(argv[2], "COM2") == 0) comport = 2; #endif /* MSDOS */ #ifndef decus if ((talkfd = fopen(argv[2], "wn")) == NULL) { #else if ((talkfn = kb_open(argv[2])) == NULL) { #endif /* decus */ perror(argv[2]); exit(exstat); } argv++; argc--; } else { break; } goto next_arg; case 'v': /* Output in video mode */ video = 1; #ifdef decus if ($$rsts) { if (((isvt52 = sctype()) & 64) == 0) { fprintf(stderr, "?Unknown video %d\n", sctype()); video = 0; /* So don't do it */ } else isvt52 = (isvt52 == SC_VT52); } else isvt52 = 0; #endif /* decus */ break; case 'w': /* Write output to file */ if (isgraph(ap[1]) != 0) { if ((extrafd = fopen(&ap[1], "a")) == NULL) { perror(&ap[1]); exit(exstat); } } else if (argc > 2) { if ((extrafd = fopen(argv[2], "a")) == NULL) { perror(argv[2]); exit(exstat); } argv++; argc--; } else { break; } goto next_arg; case 'x': /* exercise rand() function */ rndflg++; break; case '?': /* Display help message */ printf("COOKIE %s",VERSION); printf("\n\nUsage is: COOKIE option option...\n"); printf("Options: n Display cookie N\n"); printf(" -n Display N random cookies\n"); printf(" -a Print all cookies in order\n"); #ifdef MSDOS printf(" -b Use ANSI.SYS instead of BIOS video\n"); #endif /* MSDOS */ printf(" -c Print random cookies continuously\n"); printf(" -d Enable debugging output\n"); #ifdef decus if ($$rsts) #endif /* decus */ printf(" -e Don't set LASTCOOKIE in environment\n"); printf(" -f fn Get cookies from file FN\n"); printf(" -h Suppress Heinlein quotations\n"); printf(" -i Print version ID of cookie file\n"); printf(" -o Print an offensive cookie "); printf("(May be disabled on your system)\n"); printf(" -r m n Print cookies M through N in order\n"); printf(" -s n Sleep N seconds between cookies "); printf("- if N is omitted, delay is\n"); printf(" proportional to the size of the "); printf("cookie\n"); printf(" -t fn Write cookies to DECtalk on file FN "); printf("as well as to terminal\n"); printf(" -v Output cookies in video mode\n"); printf(" -w fn Write cookies to file FN as well as "); printf("to terminal\n"); printf(" -x Run randomness tests on random num"); printf("ber generator (slow)\n"); printf(" -? Print this message\n"); exit(exstat); break; default: fprintf(stderr, "?Unknown option '%c'\n", *ap); fprintf(stderr, " do COOKIE -? for help.\n\n\n"); } } next_arg: argc--; argv++; } init(); /* Setup random number */ setup_cookie(); /* Open file, check versions... */ if (rndflg) { rndflg=(int) NCOOKIES; rndtab=(int *) calloc(rndflg, sizeof(int)); if (rndtab == NULL) { fprintf(stderr,"?Insufficient memory to hold table\n"); exit(exstat); } printf("\nThis may take a while...\n"); rndchk(0, "sequential"); /* Go exercise randomness */ rndchk(1, "iterative"); exit(exstat); /* And exit */ } if (video) { #ifdef vms initscr(); /* Init VMS C CURSES library */ #endif /* vms */ erpage(); } if (doall) { printf("%s", (doall > 1) ? "%%\n" : ""); if ((first == 0) && (last == 0)) { first = 1; last = NCOOKIES; } if (first == 0) first = 1; if (last == 0) last = 1; for (which = first; which < last; which++) { docookie(which); #ifdef MSDOS kbtest(); #endif /* MSDOS */ } } if (continuous) which = -1; if (which > 0) { if (which > NCOOKIES) { sprintf(t.text, "Misfortune: there are only %ld cookies.\n", NCOOKIES); output(which, t.text); } else docookie(which); } else { if ((howmany = -which) == 0) howmany = 1; while (howmany-- > 0) { which = rand() % NCOOKIES; docookie(which + 1); if (continuous) { howmany = 1; #ifdef MSDOS kbtest(); #endif /* MSDOS */ } if (howmany > 0) { if (no_sleep == 0) { sleep((long_sleep > 0) ? long_sleep : (linecount + 1) * 2); } } } } if (extrafd != NULL) fclose(extrafd); #ifndef decus if (talkfd != NULL) fclose(talkfd); #else if (talkfn != 0) kb_close(talkfn); #endif /* decus */ #ifdef decus if (!noenvset && $$rsts) rtemt(DOCCL, &envstr); /* Set LASTCOOKIE on RSTS */ #endif /* decus */ } void init() /* * Initialize random number generator */ { #ifdef decus seed=time(NULL); /* decus - set seed */ #else srand(time(NULL)); /* others - use function */ #endif /* decus */ rand(); /* always toss the first one */ } void setup_cookie() /* * Initialize cookie file, finding it in the search list */ { register char **namep; register int temp, p; char dummy[9]; if (cookfd == NULL) { if (offensive == 0) { for (namep = cookfile; *namep != NULL; namep++) { if ((cookfd = fopen(*namep, R_MODE)) != NULL) break; } } else { for (namep = coobfile; *namep != NULL; namep++) { if ((cookfd = fopen(*namep, R_MODE)) != NULL) break; } } #ifdef MSDOS namptr = *namep; if (cookfd == NULL) { /* Try for environment */ strcpy(envnam, (char *)getenv("COOKIE")); if (envnam[strlen(envnam)-1] != '\\') strcat(envnam, "\\"); if (offensive == 0) strcat(envnam, cookfile[0]); else strcat(envnam, coobfile[0]); if (debug) printf("environment-generated name is %s\n",envnam); cookfd = fopen(envnam, R_MODE); namptr = (char *)envnam; } #endif /* MSDOS */ if (cookfd == NULL) { fprintf(stderr, "?Can't open cookie file\n"); exit(exstat); } } if (debug) printf("before normalize, first=%ld, last=%ld\n",first,last); fread(dummy, 9, 1, cookfd); if (strncmp(dummy, "555-2368", 8) != 0) { fprintf(stderr, "?Bad magic number in cookie file\n"); exit(exstat); } if ((temp = fread(&header, sizeof(header), 1, cookfd)) != 1) rerror(sizeof(header), temp, "Reading header file"); #ifndef decus hswap(); /* Swap from PDP-11 format */ #endif /* decus */ if (header.coover != 102) { fprintf(stderr, "?Unknown revision level %d in cookie file\n", header.coover); exit(exstat); } #ifndef MSDOS namptr = fgetname(cookfd, temp_text); #endif /* MSDOS */ if (first > NCOOKIES) first = NCOOKIES; if (last > NCOOKIES) last = NCOOKIES; if (debug) printf("after normalize, first=%ld, last=%ld\n",first,last); if (disp_version) { #ifndef decus p = sprintf(t.text, "Cookie file %s, built on %s", namptr, header.date); p--; /* Eat newline character */ p += sprintf(t.text+p,", contains %ld cookies. The largest is %d ", header.ncookie, header.bcookie); p += sprintf(t.text+p, "bytes long. %d index levels were used. ", header.nindex+1); p += sprintf(t.text+p, "The revision level is %d.%02d.", header.coover / 100, header.coover % 100); for (p = 64; p < strlen(t.text); p = p+64) { while (t.text[p] != ' ') p++; /* Break into 64-char lines */ t.text[p] = '\n'; } printf("%s\n", t.text); #else printf("Cookie file %s, built on %s", namptr, header.date); printf("contains %ld cookies. The largest is %d ", header.ncookie, header.bcookie); printf("bytes long. %d index\nlevels were used. ", header.nindex+1); printf("The revision level is %d.%02d.\n", header.coover / 100, header.coover % 100); #endif /* decus */ exit(exstat); } if ((temp = fread(topindex, header.sindex, 1, cookfd)) != 1) rerror(header.sindex, temp, "Reading top-level index"); #ifndef decus swaplb(topindex); /* Swap from PDP-11 format */ #endif /* decus */ } void rndchk(pass, type) int pass; /* Pass number (0 or 1) */ char *type; /* Pass type */ /* * Verify random number generator */ { long i, k, m; int j, l; printf("\nBeginning %s test, %ld cookies.\n",type, NCOOKIES); k=0, l=0; /* initialize # of tries */ m=rand(); /* initialize pseudo-seed */ for (i=0; i k) { k=rndtab[i]; /* set new maximum */ l=i; /* and the cookie number */ } } printf(" Naximum hits was %ld, on cookie %d.\n",k, l); } int tbldun(l) int l; /* * Return number of missing cookie elements */ { register int i, j; j=0; for (i=0; i= header.subindex) fprintf(stderr, "Bug: Gone too far, index = %d, max = %d\n", i, header.subindex); index = topindex[i]; if (debug) { printf("requested cookie %ld+1\n",which); printf("fseek to subindex at %ld\n",index); } if (fseek(cookfd, index, 0) != 0) fprintf(stderr, "Can't seek to top-index at %ld\n", index); if ((bytect = fread(t.index, header.sindex, 1, cookfd)) != 1) { fprintf(stderr, "seek to sub-index %d, %ld.\n", i, index); rerror(header.sindex, bytect, "Can't read sub-index"); } #ifndef decus swaplb(t.index); /* Swap from PDP-11 format */ #endif temp = header.nindex; temp = which % temp; i = temp; index = t.index[i]; #ifdef MSDOS rewind(cookfd); /* fseek() bug in Microsoft 4.0 */ #endif /* MSDOS */ if (debug) printf("fseek to cookie at %ld\n",index); if (fseek(cookfd, index, 0) != 0) { fprintf(stderr, "Can't seek to cookie at %ld: ", index); perror("minor index seek"); printf("Requesting cookie %ld, max = %ld\n", which, header.ncookie); return; } if (debug) printf("ftell of cookie is %ld\n",ftell(cookfd)); tp = &t.text[0]; while (fgets(tp, (sizeof(t.text)) - (tp - t.text), cookfd) != NULL && !feof(cookfd) && tp[0] != '%' && tp[1] != '%') { tp += strlen(tp); } *tp = EOS; /* Remove trailing %% */ if (feof(cookfd)) { rerror(tp - t.text, tp - t.text, "Can't read cookie"); } if (notLong && isLong(t.text)) antiheinlein(which + 1); else output(which + 1, t.text); } static char *anti1[] = { "A Heinlein Cookie you do disdain,\n\ I'll say no more to soothe your brain.\n", "I'd rather drink a gallon of overage Rhine wine,\n\ Than read a quote by Robert A. Heinlein.\n", "I'd rather bite boils from an elephant's behind,\n\ Than read more quotes by Robert A. Heinlein.\n", "*I'd rather a tax audit found me wrong,\n", "*I'd rather be dribbled by old King Kong,\n", "*I'd rather find paraquat in my bong,\n", "*I'd rather Chuck Barris used me as the gong,\n", "*I'd rather do updates to Atari Pong,\n", "*I'd rather write a \"User's Guide to Pong\",\n", }; static char *anti2[] = { "Than read another quote by Lazarus Long.\n", "Than have to read more of Lazarus Long.\n", "Than be forced to consider more Lazarus Long.\n", }; int isLong(text) register char *text; /* * Return TRUE if the text contains "Heinlein" or "Lazarus Long" */ { register char c; while ((c = *text++) != EOS) { switch (c) { case 'H': if (strncmp(text, "einlein",7)==0) return (TRUE); break; case 'L': if (strncmp(text, "azarus Long",11)==0) return (TRUE); break; } } return (FALSE); } static char antibuffer[257]; void antiheinlein(which) long which; /* * Output a non-Heinlein cookie */ { register char *tp; tp = anti1[(rand() & 32767) % (sizeof(anti1)) / (sizeof(char *))]; if (*tp == '*') { strcpy(antibuffer, tp + 1); strcat(antibuffer, anti2[(rand() & 32767) % (sizeof(anti2)) / (sizeof(char *))]); } else { strcpy(antibuffer, tp); } output(which, antibuffer); } void output(which, out_text) long which; char *out_text; /* * Output one cookie */ { register char *tp, *te; register char tc; startoutput(which); te = out_text + strlen(out_text); for ( tp = out_text; tp < te; tp += 511) { if (tp+511 < te) { /* More than 511, break up */ tc = *(tp+511); *(tp+511) = '\0'; #ifdef vms if (video) { printw("%s", tp); refresh(); } else printf("%s", tp); #else printf("%s", tp); #endif /* vms */ if (extrafd != NULL) fprintf(extrafd, "%s", tp); *(tp+511) = tc; } else { #ifdef vms if (video) { printw("%s%s\n", tp, (doall > 1) ? "%%" : ""); refresh(); } else printf("%s%s\n", tp, (doall > 1) ? "%%" : ""); #else printf("%s%s\n", tp, (doall > 1) ? "%%" : ""); #endif /* vms */ if (extrafd != NULL) fprintf(extrafd, "%s%s\n", tp, (doall > 1) ? "%%" : ""); } } #ifndef decus if (talkfd != NULL) /* Should we mumble? */ #else if (talkfn != 0) /* Should we mumble? */ #endif /* decus */ speak(out_text); linecount = 1; tp = out_text; while ((tp = strchr(tp, '\n')) != NULL) { linecount++; tp++; } endoutput(); } void speak(out_text) char *out_text; /* * Drive DECtalk */ { register char *tp; register int c; nvoice = (rand() & 32767 % 9); spit('['); /* Voice header */ spit(':'); spit('n'); spit(voices[nvoice]); spit(']'); for (tp = out_text; (c = *tp++) != EOS;) { switch (c) { case '-': /* hy-\nphen => hyphen */ if (*tp == '\n') { tp++; while ((c = *tp) == ' ') tp++; } else spit('-'); break; case '+': /* Errosols, part 1 of 2 */ if ((*tp == '-') && (tp[1] == '-')) { while (*tp != '+') tp++; tp++; c = *tp; } else spit('+'); break; case '|': /* Errosols, part 2 of 2 */ if ((tp[-2] != '\n') && (*tp != '\n')) spit('|'); break; case ',': spit(','); if (!isspace(*tp)) spit(' '); break; case '[': /* [ => ( */ spit('('); break; case ']': spit(')'); /* ] => ) */ break; case '(': /* (c.a. => ( c.a. */ if (isalpha(*tp) && tp[1] == '.') { spit(c); c = ' '; } spit(c); break; case ')': /* (44-22 BC)? => */ if (tp > &out_text[1] /* (44-22 BC) */ && !isalpha(tp[-2]) && *tp == '?') { spit(c); c = ' '; tp++; } spit(c); break; case '.': if (tp > &out_text[3] /* H. L. Menken => */ && isupper(tp[-2]) /* H L Menken */ && isspace(tp[-3]) /* so DECtalk doesn't */ && isspace(*tp)) /* pause. */ continue; if (tp > &out_text[2] /* ...foo => ... foo */ && tp[-2] == '.' && isalpha(*tp)) { spit(c); c = ' '; } spit(c); break; case '?': if (tp > &out_text[2] && isalpha(tp[-2]) && isspace(*tp)) spit(c); break; default: spit(c); if (isdigit(c) && !isdigit(*tp)) { switch (*tp) { case '?': /* 1900?-1980 */ if (tp[1] != '-') break; tp++; /* Skip ? */ case '-': /* 1900-1910 */ spit(','); spit(' '); tp++; if (*tp == '?' && tp[1] == ')') tp += 2; /* 1900-?) */ break; } } } } #ifdef decus spit(($$rsts) ? '\233' : '\33'); #else spit('\33'); #endif /* decus */ spit('P'); spit('0'); spit(';'); spit('1'); spit('1'); spit('z'); #ifdef decus spit(($$rsts) ? '\233' : '\33'); #else spit('\33'); #endif /* decus */ spit('\\'); } void spit(what) /* Emit character to DECtalk */ int what; { #ifdef MSDOS if (comport == 0) /* Messy case */ putc(what, talkfd); /* If not to COMn */ else { if ((comsta(comport-1) & 0x0030) != 0x0030) { fprintf(stderr, "?Error writing device COM%d:\n", comport); exit(exstat); } comout(comport-1, what); /* Otherwise send the byte */ comwait(comport-1); /* And play at flow control */ } #endif /* MSDOS */ #ifdef decus kb_spit(talkfn, what); /* Simple-minded case */ #endif /* decus */ #ifdef vms putc(what, talkfd); /* Simple case */ #endif /* MSDOS */ } void startoutput(which) long which; /* * Initialize output */ { register char *timebuf; long tvec; if (video) { sprintf(temp_text, "%ld", which); time(&tvec); timebuf = ctime(&tvec); erpage(); vtout(1, 27, timebuf); vtout(3, 36, temp_text); vtout(4, 1, "\n"); /* Force new line for some OS's */ } } void endoutput() /* * Clear the rest of the screen */ { if (video) { fflush(stdout); } } void vtcurse(row, col) int row, col; { if (row == 0) return; #ifdef MSDOS if (ansivideo) printf("\033[%d;%dH",row, col); else { inreg.h.ah = 15; /* Get current video page */ int86(0x10, &inreg, &outreg); inreg.h.ah = 2; /* Position cursor on it */ inreg.h.dh = --row; inreg.h.dl = --col; inreg.h.bh = outreg.h.bh; int86(0x10, &inreg, &outreg); } #endif /* MSDOS */ #ifdef decus if (isvt52) printf(($$rsts) ? "\233Y%c%c" : "\033Y%c%c", row + 037, col + 037); else printf(($$rsts) ? "\233[%d;%dH" : "\033[%d;%dH", row, col); #endif /* decus */ #ifdef vms move(row, col); #endif /* vms */ } void erpage() { vtcurse(1, 1); #ifdef MSDOS if (ansivideo) fputs("\033[J", stdout); else ASMCLS(); #endif /* MSDOS */ #ifdef decus if (isvt52) fputs(($$rsts) ? "\233J" : "\033J", stdout); else fputs(($$rsts) ? "\233[J" : "\033[J", stdout); #endif /* decus */ #ifdef vms clear(); #endif /* vms */ } void vtout(row, col, text) int row, col; char *text; { vtcurse(row, col); #ifndef vms fputs(text, stdout); #else printw("%s", text); refresh(); #endif /* vms */ } #ifdef MSDOS #ifndef __TURBOC__ void sleep(howlong) int howlong; { long basetime, curtime; basetime = time(NULL); curtime = time(NULL); while((curtime < basetime + howlong) && !kbhit()) curtime = time(NULL); kbtest(); /* See if key was hit and exit */ } #endif /* __TURBOC__ */ void kbtest() { int quitchr=0; if (kbhit()) { quitchr = getch(); quitchr = tolower(quitchr); if (quitchr == 113) exit(exstat); } } #endif /* MSDOS */ #ifdef MSDOS void comwait(port) int port; /* Desired port (0, 1) */ { int byte; while ( comrdy(port) != 0) { /* If there is a byte waiting */ byte = cominp(port); /* Get it */ if (byte == 0x13) { /* If ^S, await matching ^Q */ while (cominp(port) != 0x11) { } } } return; } int comrdy(port) /* Return input ready status */ int port; { return ((comsta(port) & 0x0100) >> 8); } int comsta(port) /* Return all status */ int port; { inreg.x.dx = port; inreg.h.ah = 3; int86(0x14, &inreg, &outreg); return (outreg.x.ax); } int cominp(port) /* Return character */ int port; { inreg.x.dx = port; inreg.h.ah = 2; int86(0x14, &inreg, &outreg); return (outreg.h.al & 0x7f); } void comout(port,data) /* Send character */ int port, data; { inreg.x.dx = port; inreg.h.ah = 1; inreg.h.al = data; int86(0x14, &inreg, &outreg); } #endif /* MSDOS */ #ifndef decus void hswap() /* * Swap the header.xxx components to/from PDP-11 format */ { header.ncookie = swapl(header.ncookie); } void swaplb(indextable) long indextable[]; /* * Swap an index table to/from universal format */ { register int i; for (i=0; i < header.nindex; i++) indextable[i] = swapl(indextable[i]); } long swapl(l) /* With thanks to Dennis Bednar */ long l; { register char *sp, *dp; long r; sp = (char *) &l; dp = (char *) &r; *dp++ = sp[2]; /* PDP-11 stores bytes 2,3,0,1 */ *dp++ = sp[3]; *dp++ = sp[0]; *dp = sp[1]; return (r); } #endif