1 /*
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Guy Harris.
7 *
8 * %sccs.include.redist.c%
9 */
10
11 #ifndef lint
12 static char copyright[] =
13 "@(#) Copyright (c) 1988, 1993\n\
14 The Regents of the University of California. All rights reserved.\n";
15 #endif /* not lint */
16
17 #ifndef lint
18 static char sccsid[] = "@(#)ching.phx.c 8.1 (Berkeley) 05/31/93";
19 #endif /* not lint */
20
21 /*
22 * phx - Print NROFF/TROFF source of change, given the line values.
23 */
24 #include <stdio.h>
25 #include "ching.h"
26 #include "pathnames.h"
27
28 struct {
29 int lines; /* encoded value of lines */
30 int trinum; /* trigram number */
31 } table[] = {
32 { 777, 0 }, /* 1 */
33 { 887, 1 }, /* 4 */
34 { 878, 2 }, /* 6 */
35 { 788, 3 }, /* 7 */
36 { 888, 4 }, /* 8 */
37 { 778, 5 }, /* 5 */
38 { 787, 6 }, /* 3 */
39 { 877, 7 }, /* 2 */
40 };
41
42 /*
43 * Gives hexagram number from two component trigrams.
44 */
45 int crosstab[8][8] = {
46 1, 34, 5, 26, 11, 9, 14, 43,
47 25, 51, 3, 27, 24, 42, 21, 17,
48 6, 40, 29, 4, 7, 59, 64, 47,
49 33, 62, 39, 52, 15, 53, 56, 31,
50 12, 16, 8, 23, 2, 20, 35, 45,
51 44, 32, 48, 18, 46, 57, 50, 28,
52 13, 55, 63, 22, 36, 37, 30, 49,
53 10, 54, 60, 41, 19, 61, 38, 58,
54 };
55
56 int trigrams[6];
57 int moving[6];
58
59 FILE *chingf; /* stream to read the hexagram file */
60
61 char *gets();
62
main(argc,argv)63 main(argc, argv)
64 int argc;
65 char **argv;
66 {
67 register int hexagram; /* hexagram number */
68 register char *hexptr; /* pointer to string of lines */
69 char hexstr[6+1]; /* buffer for reading lines in */
70 register int i;
71
72 if (argc < 2)
73 hexptr = gets(hexstr);
74 else
75 hexptr = argv[1];
76 if (hexptr == (char *)NULL || strlen(hexptr) != 6) {
77 fprintf(stderr, "What kind of a change is THAT?!?\n");
78 exit(1);
79 }
80 for (i = 0; i < 6; i++) {
81 trigrams[i] = hexptr[i] - '0';
82 if (trigrams[i] == 6 || trigrams[i] == 9)
83 moving[i] = 1;
84 else
85 moving[i] = 0;
86 }
87 if ((chingf = fopen(_PATH_HEX, "r")) == (FILE *)NULL) {
88 fprintf(stderr, "ching: can't read %s\n", _PATH_HEX);
89 exit(2);
90 }
91 phx(doahex(), 0);
92 if (changes())
93 phx(doahex(), 1);
94 }
95
96 /*
97 * Compute the hexagram number, given the trigrams.
98 */
99 int
doahex()100 doahex()
101 {
102 int lower, upper; /* encoded values of lower and upper trigrams */
103 int lnum, unum; /* indices of upper and lower trigrams */
104 register int i;
105
106 lower = codem(0);
107 upper = codem(3);
108 for (i = 0; i < 8; i++) {
109 if (table[i].lines == lower)
110 lnum = table[i].trinum;
111 if (table[i].lines == upper)
112 unum = table[i].trinum;
113 }
114 return(crosstab[lnum][unum]);
115 }
116
117 /*
118 * Encode a trigram as a 3-digit number; the digits, from left to right,
119 * represent the lines. 7 is a solid (yang) line, 8 is a broken (yin) line.
120 */
codem(a)121 codem(a)
122 int a;
123 {
124 register int code, i;
125 int factor[3];
126
127 factor[0] = 1;
128 factor[1] = 10;
129 factor[2] = 100;
130 code = 0;
131
132 for (i = a; i < a + 3; i++) {
133 switch(trigrams[i]) {
134
135 case YYANG:
136 case OYANG:
137 code += factor[i%3]*7;
138 break;
139
140 case OYIN:
141 case YYIN:
142 code += factor[i%3]*8;
143 break;
144 }
145 }
146 return(code);
147 }
148
149 /*
150 * Compute the changes based on moving lines; return 1 if any lines moved,
151 * 0 if no lines moved.
152 */
changes()153 changes()
154 {
155 register int cflag;
156 register int i;
157
158 cflag = 0;
159 for (i = 0; i < 6; i++) {
160 if (trigrams[i] == OYIN) {
161 trigrams[i] = YYANG;
162 cflag++;
163 } else if (trigrams[i] == OYANG) {
164 trigrams[i] = YYIN;
165 cflag++;
166 }
167 }
168 return(cflag);
169 }
170
171 /*
172 * Print the NROFF/TROFF source of a hexagram, given the hexagram number;
173 * if flag is 0, print the entire source; if flag is 1, ignore the meanings
174 * of the lines.
175 */
phx(hexagram,flag)176 phx(hexagram, flag)
177 int hexagram;
178 int flag;
179 {
180 char textln[128+1]; /* buffer for text line */
181 register char *lp; /* pointer into buffer */
182 register int thishex; /* number of hexagram just read */
183 int lineno; /* number of line read in */
184 int allmoving; /* 1 if all lines are moving */
185 register int i;
186
187 /*
188 * Search for the hexagram; it begins with a line of the form
189 * .H <hexagram number> <other data>.
190 */
191 rewind(chingf);
192 for (;;) {
193 if (fgets(textln, sizeof(textln), chingf) == (char *)NULL) {
194 fprintf(stderr, "ching: Hexagram %d missing\n",
195 hexagram);
196 exit(3);
197 }
198 lp = &textln[0];
199 if (*lp++ != '.' || *lp++ != 'H')
200 continue;
201 while (*lp++ == ' ')
202 ;
203 lp--;
204 thishex = atoi(lp);
205 if (thishex < 1 || thishex > 64)
206 continue;
207 if (thishex == hexagram)
208 break;
209 }
210
211 /*
212 * Print up to the line commentary, which ends with a line of the form
213 * .L <position> <value>
214 */
215 fputs(textln, stdout);
216 for (;;) {
217 if (fgets(textln, sizeof(textln), chingf) == (char *)NULL) {
218 fprintf(stderr, "ching: Hexagram %d malformed\n",
219 hexagram);
220 exit(3);
221 }
222 lp = &textln[0];
223 if (*lp++ == '.') {
224 if (*lp++ == 'L')
225 break;
226 }
227 fputs(textln, stdout);
228 }
229
230 /*
231 * Now print the line commentaries, if this is the first hexagram.
232 */
233 if (flag)
234 return;
235
236 /*
237 * If a line is moving, print its commentary.
238 * The text of the commentary ends with a line either of the form
239 * .L <position> <value>
240 * or of the form
241 * .LA <value>
242 * or of the form
243 * .H <hexagram number> <other arguments>
244 */
245 allmoving = 1;
246 for (i = 0; i < 6; i++) {
247 while (*lp++ == ' ')
248 ;
249 lp--;
250 lineno = atoi(lp);
251 if (i + 1 != lineno) {
252 fprintf(stderr, "ching: Hexagram %d malformed\n",
253 hexagram);
254 exit(3);
255 }
256 if (moving[i])
257 fputs(textln, stdout);
258 else
259 allmoving = 0;
260 for (;;) {
261 if (fgets(textln, sizeof(textln), chingf) == (char *)NULL)
262 break;
263 lp = &textln[0];
264 if (*lp++ == '.' && (*lp == 'L' || *lp == 'H')) {
265 lp++;
266 break;
267 }
268 if (moving[i])
269 fputs(textln, stdout);
270 }
271 }
272
273 /*
274 * If all the lines are moving, print the commentary for that; it
275 * ends with a line of the form
276 * .H <hexagram number> <other arguments>
277 */
278 if (*lp == 'A' && allmoving) {
279 fputs(textln, stdout);
280 for (;;) {
281 if (fgets(textln, sizeof(textln), chingf) == (char *)NULL)
282 break;
283 lp = &textln[0];
284 if (*lp++ == '.' || *lp++ == 'H')
285 break;
286 fputs(textln, stdout);
287 }
288 }
289 }
290