1 /* $NetBSD: printching.c,v 1.5 2011/08/31 16:24:55 plunky Exp $ */ 2 3 /* 4 * Copyright (c) 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Guy Harris. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)ching.phx.c 8.1 (Berkeley) 5/31/93 39 */ 40 41 /* 42 * printching - Print NROFF/TROFF source of change, given the line values. 43 */ 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include "ching.h" 48 #include "pathnames.h" 49 50 static int changes(void); 51 static int codem(int a); 52 static int doahex(void); 53 static void phx(int hexagram, int flag); 54 55 static const struct { 56 int lines; /* encoded value of lines */ 57 int trinum; /* trigram number */ 58 } table[] = { 59 { 777, 0 }, /* 1 */ 60 { 887, 1 }, /* 4 */ 61 { 878, 2 }, /* 6 */ 62 { 788, 3 }, /* 7 */ 63 { 888, 4 }, /* 8 */ 64 { 778, 5 }, /* 5 */ 65 { 787, 6 }, /* 3 */ 66 { 877, 7 }, /* 2 */ 67 }; 68 69 /* 70 * Gives hexagram number from two component trigrams. 71 */ 72 static const int crosstab[8][8] = { 73 {1, 34, 5, 26, 11, 9, 14, 43}, 74 {25, 51, 3, 27, 24, 42, 21, 17}, 75 {6, 40, 29, 4, 7, 59, 64, 47}, 76 {33, 62, 39, 52, 15, 53, 56, 31}, 77 {12, 16, 8, 23, 2, 20, 35, 45}, 78 {44, 32, 48, 18, 46, 57, 50, 28}, 79 {13, 55, 63, 22, 36, 37, 30, 49}, 80 {10, 54, 60, 41, 19, 61, 38, 58} 81 }; 82 83 static int trigrams[6]; 84 static int moving[6]; 85 86 static FILE *chingf; /* stream to read the hexagram file */ 87 88 int 89 main(int argc, char **argv) 90 { 91 char *hexptr; /* pointer to string of lines */ 92 char hexstr[6+1]; /* buffer for reading lines in */ 93 int i; 94 95 if (argc < 2) 96 hexptr = fgets(hexstr, 6+1, stdin); 97 else 98 hexptr = argv[1]; 99 if (hexptr == NULL || strlen(hexptr) != 6) { 100 fprintf(stderr, "What kind of a change is THAT?!?\n"); 101 exit(1); 102 } 103 for (i = 0; i < 6; i++) { 104 trigrams[i] = hexptr[i] - '0'; 105 if (trigrams[i] == 6 || trigrams[i] == 9) 106 moving[i] = 1; 107 else 108 moving[i] = 0; 109 } 110 if ((chingf = fopen(_PATH_HEX, "r")) == NULL) { 111 fprintf(stderr, "ching: can't read %s\n", _PATH_HEX); 112 exit(2); 113 } 114 phx(doahex(), 0); 115 if (changes()) 116 phx(doahex(), 1); 117 exit(0); 118 } 119 120 /* 121 * Compute the hexagram number, given the trigrams. 122 */ 123 static int 124 doahex(void) 125 { 126 int lower, upper; /* encoded values of lower and upper trigrams */ 127 int lnum = 0, unum = 0; /* indices of upper and lower trigrams */ 128 int i; 129 130 lower = codem(0); 131 upper = codem(3); 132 for (i = 0; i < 8; i++) { 133 if (table[i].lines == lower) 134 lnum = table[i].trinum; 135 if (table[i].lines == upper) 136 unum = table[i].trinum; 137 } 138 return(crosstab[lnum][unum]); 139 } 140 141 /* 142 * Encode a trigram as a 3-digit number; the digits, from left to right, 143 * represent the lines. 7 is a solid (yang) line, 8 is a broken (yin) line. 144 */ 145 static int 146 codem(int a) 147 { 148 int code, i; 149 int factor[3]; 150 151 factor[0] = 1; 152 factor[1] = 10; 153 factor[2] = 100; 154 code = 0; 155 156 for (i = a; i < a + 3; i++) { 157 switch(trigrams[i]) { 158 159 case YYANG: 160 case OYANG: 161 code += factor[i%3]*7; 162 break; 163 164 case OYIN: 165 case YYIN: 166 code += factor[i%3]*8; 167 break; 168 } 169 } 170 return(code); 171 } 172 173 /* 174 * Compute the changes based on moving lines; return 1 if any lines moved, 175 * 0 if no lines moved. 176 */ 177 static int 178 changes(void) 179 { 180 int cflag; 181 int i; 182 183 cflag = 0; 184 for (i = 0; i < 6; i++) { 185 if (trigrams[i] == OYIN) { 186 trigrams[i] = YYANG; 187 cflag++; 188 } else if (trigrams[i] == OYANG) { 189 trigrams[i] = YYIN; 190 cflag++; 191 } 192 } 193 return(cflag); 194 } 195 196 /* 197 * Print the NROFF/TROFF source of a hexagram, given the hexagram number; 198 * if flag is 0, print the entire source; if flag is 1, ignore the meanings 199 * of the lines. 200 */ 201 static void 202 phx(int hexagram, int flag) 203 { 204 char textln[128+1]; /* buffer for text line */ 205 char *lp; /* pointer into buffer */ 206 int thishex; /* number of hexagram just read */ 207 int lineno; /* number of line read in */ 208 int allmoving; /* 1 if all lines are moving */ 209 int i; 210 211 /* 212 * Search for the hexagram; it begins with a line of the form 213 * .H <hexagram number> <other data>. 214 */ 215 rewind(chingf); 216 for (;;) { 217 if (fgets(textln, sizeof(textln), chingf) == NULL) { 218 fprintf(stderr, "ching: Hexagram %d missing\n", 219 hexagram); 220 exit(3); 221 } 222 lp = &textln[0]; 223 if (*lp++ != '.' || *lp++ != 'H') 224 continue; 225 while (*lp++ == ' ') 226 ; 227 lp--; 228 thishex = atoi(lp); 229 if (thishex < 1 || thishex > 64) 230 continue; 231 if (thishex == hexagram) 232 break; 233 } 234 235 /* 236 * Print up to the line commentary, which ends with a line of the form 237 * .L <position> <value> 238 */ 239 fputs(textln, stdout); 240 for (;;) { 241 if (fgets(textln, sizeof(textln), chingf) == NULL) { 242 fprintf(stderr, "ching: Hexagram %d malformed\n", 243 hexagram); 244 exit(3); 245 } 246 lp = &textln[0]; 247 if (*lp++ == '.') { 248 if (*lp++ == 'L') 249 break; 250 } 251 fputs(textln, stdout); 252 } 253 254 /* 255 * Now print the line commentaries, if this is the first hexagram. 256 */ 257 if (flag) 258 return; 259 260 /* 261 * If a line is moving, print its commentary. 262 * The text of the commentary ends with a line either of the form 263 * .L <position> <value> 264 * or of the form 265 * .LA <value> 266 * or of the form 267 * .H <hexagram number> <other arguments> 268 */ 269 allmoving = 1; 270 for (i = 0; i < 6; i++) { 271 while (*lp++ == ' ') 272 ; 273 lp--; 274 lineno = atoi(lp); 275 if (i + 1 != lineno) { 276 fprintf(stderr, "ching: Hexagram %d malformed\n", 277 hexagram); 278 exit(3); 279 } 280 if (moving[i]) 281 fputs(textln, stdout); 282 else 283 allmoving = 0; 284 for (;;) { 285 if (fgets(textln, sizeof(textln), chingf) == NULL) 286 break; 287 lp = &textln[0]; 288 if (*lp++ == '.' && (*lp == 'L' || *lp == 'H')) { 289 lp++; 290 break; 291 } 292 if (moving[i]) 293 fputs(textln, stdout); 294 } 295 } 296 297 /* 298 * If all the lines are moving, print the commentary for that; it 299 * ends with a line of the form 300 * .H <hexagram number> <other arguments> 301 */ 302 if (*lp == 'A' && allmoving) { 303 fputs(textln, stdout); 304 for (;;) { 305 if (fgets(textln, sizeof(textln), chingf) == NULL) 306 break; 307 lp = &textln[0]; 308 if (*lp++ == '.' || *lp++ == 'H') 309 break; 310 fputs(textln, stdout); 311 } 312 } 313 } 314