135942Sbostic /*
2*60770Sbostic * Copyright (c) 1988, 1993
3*60770Sbostic * The Regents of the University of California. All rights reserved.
435942Sbostic *
535942Sbostic * This code is derived from software contributed to Berkeley by
635942Sbostic * Guy Harris.
735942Sbostic *
842573Sbostic * %sccs.include.redist.c%
935942Sbostic */
1035942Sbostic
1135942Sbostic #ifndef lint
12*60770Sbostic static char copyright[] =
13*60770Sbostic "@(#) Copyright (c) 1988, 1993\n\
14*60770Sbostic The Regents of the University of California. All rights reserved.\n";
1535942Sbostic #endif /* not lint */
1635942Sbostic
1735942Sbostic #ifndef lint
18*60770Sbostic static char sccsid[] = "@(#)ching.phx.c 8.1 (Berkeley) 05/31/93";
1935942Sbostic #endif /* not lint */
2035942Sbostic
2135942Sbostic /*
2235942Sbostic * phx - Print NROFF/TROFF source of change, given the line values.
2335942Sbostic */
2435942Sbostic #include <stdio.h>
2535942Sbostic #include "ching.h"
2641175Sbostic #include "pathnames.h"
2735942Sbostic
2835942Sbostic struct {
2935942Sbostic int lines; /* encoded value of lines */
3035942Sbostic int trinum; /* trigram number */
3135942Sbostic } table[] = {
3235942Sbostic { 777, 0 }, /* 1 */
3335942Sbostic { 887, 1 }, /* 4 */
3435942Sbostic { 878, 2 }, /* 6 */
3535942Sbostic { 788, 3 }, /* 7 */
3635942Sbostic { 888, 4 }, /* 8 */
3735942Sbostic { 778, 5 }, /* 5 */
3835942Sbostic { 787, 6 }, /* 3 */
3935942Sbostic { 877, 7 }, /* 2 */
4035942Sbostic };
4135942Sbostic
4235942Sbostic /*
4335942Sbostic * Gives hexagram number from two component trigrams.
4435942Sbostic */
4535942Sbostic int crosstab[8][8] = {
4635942Sbostic 1, 34, 5, 26, 11, 9, 14, 43,
4735942Sbostic 25, 51, 3, 27, 24, 42, 21, 17,
4835942Sbostic 6, 40, 29, 4, 7, 59, 64, 47,
4935942Sbostic 33, 62, 39, 52, 15, 53, 56, 31,
5035942Sbostic 12, 16, 8, 23, 2, 20, 35, 45,
5135942Sbostic 44, 32, 48, 18, 46, 57, 50, 28,
5235942Sbostic 13, 55, 63, 22, 36, 37, 30, 49,
5335942Sbostic 10, 54, 60, 41, 19, 61, 38, 58,
5435942Sbostic };
5535942Sbostic
5635942Sbostic int trigrams[6];
5735942Sbostic int moving[6];
5835942Sbostic
5935942Sbostic FILE *chingf; /* stream to read the hexagram file */
6035942Sbostic
6135942Sbostic char *gets();
6235942Sbostic
main(argc,argv)6335942Sbostic main(argc, argv)
6435942Sbostic int argc;
6535942Sbostic char **argv;
6635942Sbostic {
6735942Sbostic register int hexagram; /* hexagram number */
6835942Sbostic register char *hexptr; /* pointer to string of lines */
6935942Sbostic char hexstr[6+1]; /* buffer for reading lines in */
7035942Sbostic register int i;
7135942Sbostic
7235942Sbostic if (argc < 2)
7335942Sbostic hexptr = gets(hexstr);
7435942Sbostic else
7535942Sbostic hexptr = argv[1];
7635942Sbostic if (hexptr == (char *)NULL || strlen(hexptr) != 6) {
7735942Sbostic fprintf(stderr, "What kind of a change is THAT?!?\n");
7835942Sbostic exit(1);
7935942Sbostic }
8035942Sbostic for (i = 0; i < 6; i++) {
8135942Sbostic trigrams[i] = hexptr[i] - '0';
8235942Sbostic if (trigrams[i] == 6 || trigrams[i] == 9)
8335942Sbostic moving[i] = 1;
8435942Sbostic else
8535942Sbostic moving[i] = 0;
8635942Sbostic }
8741175Sbostic if ((chingf = fopen(_PATH_HEX, "r")) == (FILE *)NULL) {
8841175Sbostic fprintf(stderr, "ching: can't read %s\n", _PATH_HEX);
8935942Sbostic exit(2);
9035942Sbostic }
9135942Sbostic phx(doahex(), 0);
9235942Sbostic if (changes())
9335942Sbostic phx(doahex(), 1);
9435942Sbostic }
9535942Sbostic
9635942Sbostic /*
9735942Sbostic * Compute the hexagram number, given the trigrams.
9835942Sbostic */
9935942Sbostic int
doahex()10035942Sbostic doahex()
10135942Sbostic {
10235942Sbostic int lower, upper; /* encoded values of lower and upper trigrams */
10335942Sbostic int lnum, unum; /* indices of upper and lower trigrams */
10435942Sbostic register int i;
10535942Sbostic
10635942Sbostic lower = codem(0);
10735942Sbostic upper = codem(3);
10835942Sbostic for (i = 0; i < 8; i++) {
10935942Sbostic if (table[i].lines == lower)
11035942Sbostic lnum = table[i].trinum;
11135942Sbostic if (table[i].lines == upper)
11235942Sbostic unum = table[i].trinum;
11335942Sbostic }
11435942Sbostic return(crosstab[lnum][unum]);
11535942Sbostic }
11635942Sbostic
11735942Sbostic /*
11835942Sbostic * Encode a trigram as a 3-digit number; the digits, from left to right,
11935942Sbostic * represent the lines. 7 is a solid (yang) line, 8 is a broken (yin) line.
12035942Sbostic */
codem(a)12135942Sbostic codem(a)
12235942Sbostic int a;
12335942Sbostic {
12435942Sbostic register int code, i;
12535942Sbostic int factor[3];
12635942Sbostic
12735942Sbostic factor[0] = 1;
12835942Sbostic factor[1] = 10;
12935942Sbostic factor[2] = 100;
13035942Sbostic code = 0;
13135942Sbostic
13235942Sbostic for (i = a; i < a + 3; i++) {
13335942Sbostic switch(trigrams[i]) {
13435942Sbostic
13535942Sbostic case YYANG:
13635942Sbostic case OYANG:
13735942Sbostic code += factor[i%3]*7;
13835942Sbostic break;
13935942Sbostic
14035942Sbostic case OYIN:
14135942Sbostic case YYIN:
14235942Sbostic code += factor[i%3]*8;
14335942Sbostic break;
14435942Sbostic }
14535942Sbostic }
14635942Sbostic return(code);
14735942Sbostic }
14835942Sbostic
14935942Sbostic /*
15035942Sbostic * Compute the changes based on moving lines; return 1 if any lines moved,
15135942Sbostic * 0 if no lines moved.
15235942Sbostic */
changes()15335942Sbostic changes()
15435942Sbostic {
15535942Sbostic register int cflag;
15635942Sbostic register int i;
15735942Sbostic
15835942Sbostic cflag = 0;
15935942Sbostic for (i = 0; i < 6; i++) {
16035942Sbostic if (trigrams[i] == OYIN) {
16135942Sbostic trigrams[i] = YYANG;
16235942Sbostic cflag++;
16335942Sbostic } else if (trigrams[i] == OYANG) {
16435942Sbostic trigrams[i] = YYIN;
16535942Sbostic cflag++;
16635942Sbostic }
16735942Sbostic }
16835942Sbostic return(cflag);
16935942Sbostic }
17035942Sbostic
17135942Sbostic /*
17235942Sbostic * Print the NROFF/TROFF source of a hexagram, given the hexagram number;
17335942Sbostic * if flag is 0, print the entire source; if flag is 1, ignore the meanings
17435942Sbostic * of the lines.
17535942Sbostic */
phx(hexagram,flag)17635942Sbostic phx(hexagram, flag)
17735942Sbostic int hexagram;
17835942Sbostic int flag;
17935942Sbostic {
18035942Sbostic char textln[128+1]; /* buffer for text line */
18135942Sbostic register char *lp; /* pointer into buffer */
18235942Sbostic register int thishex; /* number of hexagram just read */
18335942Sbostic int lineno; /* number of line read in */
18435942Sbostic int allmoving; /* 1 if all lines are moving */
18535942Sbostic register int i;
18635942Sbostic
18735942Sbostic /*
18835942Sbostic * Search for the hexagram; it begins with a line of the form
18935942Sbostic * .H <hexagram number> <other data>.
19035942Sbostic */
19135942Sbostic rewind(chingf);
19235942Sbostic for (;;) {
19335942Sbostic if (fgets(textln, sizeof(textln), chingf) == (char *)NULL) {
19435942Sbostic fprintf(stderr, "ching: Hexagram %d missing\n",
19535942Sbostic hexagram);
19635942Sbostic exit(3);
19735942Sbostic }
19835942Sbostic lp = &textln[0];
19935942Sbostic if (*lp++ != '.' || *lp++ != 'H')
20035942Sbostic continue;
20135942Sbostic while (*lp++ == ' ')
20235942Sbostic ;
20335942Sbostic lp--;
20435942Sbostic thishex = atoi(lp);
20535942Sbostic if (thishex < 1 || thishex > 64)
20635942Sbostic continue;
20735942Sbostic if (thishex == hexagram)
20835942Sbostic break;
20935942Sbostic }
21035942Sbostic
21135942Sbostic /*
21235942Sbostic * Print up to the line commentary, which ends with a line of the form
21335942Sbostic * .L <position> <value>
21435942Sbostic */
21535942Sbostic fputs(textln, stdout);
21635942Sbostic for (;;) {
21735942Sbostic if (fgets(textln, sizeof(textln), chingf) == (char *)NULL) {
21835942Sbostic fprintf(stderr, "ching: Hexagram %d malformed\n",
21935942Sbostic hexagram);
22035942Sbostic exit(3);
22135942Sbostic }
22235942Sbostic lp = &textln[0];
22335942Sbostic if (*lp++ == '.') {
22435942Sbostic if (*lp++ == 'L')
22535942Sbostic break;
22635942Sbostic }
22735942Sbostic fputs(textln, stdout);
22835942Sbostic }
22935942Sbostic
23035942Sbostic /*
23135942Sbostic * Now print the line commentaries, if this is the first hexagram.
23235942Sbostic */
23335942Sbostic if (flag)
23435942Sbostic return;
23535942Sbostic
23635942Sbostic /*
23735942Sbostic * If a line is moving, print its commentary.
23835942Sbostic * The text of the commentary ends with a line either of the form
23935942Sbostic * .L <position> <value>
24035942Sbostic * or of the form
24135942Sbostic * .LA <value>
24235942Sbostic * or of the form
24335942Sbostic * .H <hexagram number> <other arguments>
24435942Sbostic */
24535942Sbostic allmoving = 1;
24635942Sbostic for (i = 0; i < 6; i++) {
24735942Sbostic while (*lp++ == ' ')
24835942Sbostic ;
24935942Sbostic lp--;
25035942Sbostic lineno = atoi(lp);
25135942Sbostic if (i + 1 != lineno) {
25235942Sbostic fprintf(stderr, "ching: Hexagram %d malformed\n",
25335942Sbostic hexagram);
25435942Sbostic exit(3);
25535942Sbostic }
25635942Sbostic if (moving[i])
25735942Sbostic fputs(textln, stdout);
25835942Sbostic else
25935942Sbostic allmoving = 0;
26035942Sbostic for (;;) {
26135942Sbostic if (fgets(textln, sizeof(textln), chingf) == (char *)NULL)
26235942Sbostic break;
26335942Sbostic lp = &textln[0];
26435942Sbostic if (*lp++ == '.' && (*lp == 'L' || *lp == 'H')) {
26535942Sbostic lp++;
26635942Sbostic break;
26735942Sbostic }
26835942Sbostic if (moving[i])
26935942Sbostic fputs(textln, stdout);
27035942Sbostic }
27135942Sbostic }
27235942Sbostic
27335942Sbostic /*
27435942Sbostic * If all the lines are moving, print the commentary for that; it
27535942Sbostic * ends with a line of the form
27635942Sbostic * .H <hexagram number> <other arguments>
27735942Sbostic */
27835942Sbostic if (*lp == 'A' && allmoving) {
27935942Sbostic fputs(textln, stdout);
28035942Sbostic for (;;) {
28135942Sbostic if (fgets(textln, sizeof(textln), chingf) == (char *)NULL)
28235942Sbostic break;
28335942Sbostic lp = &textln[0];
28435942Sbostic if (*lp++ == '.' || *lp++ == 'H')
28535942Sbostic break;
28635942Sbostic fputs(textln, stdout);
28735942Sbostic }
28835942Sbostic }
28935942Sbostic }
290