|
|
1.1 ! root 1: /* ! 2: * expr.c ! 3: * Nroff/Troff. ! 4: * Expression reader. ! 5: */ ! 6: ! 7: #include <ctype.h> ! 8: #include "roff.h" ! 9: ! 10: /* Local variables. */ ! 11: static int experr; /* Got an error */ ! 12: static int expmul; /* Default unit multiplier */ ! 13: static int expdiv; /* Default unit divisor */ ! 14: static char *expp; /* Pointer in expression */ ! 15: ! 16: /* ! 17: * Return the int value of an expression. ! 18: * Given: ! 19: * Name Description Used ! 20: * str string containing an expression ! 21: * mul/div default unit multiplier, divisor if no unit given ! 22: * num initial value if leading sign ! 23: * hvf horizontal/vertical flag if initial '|' ! 24: * def default value if no expression ! 25: * The expression is evaluated from left to right with no priorites ! 26: * except parentheses. ! 27: */ ! 28: int ! 29: number(str, mul, div, num, hvf, def) char *str; long mul, div; int num, hvf, def; ! 30: { ! 31: register int n, c; ! 32: ! 33: expp = str; ! 34: expmul = mul; ! 35: expdiv = div; ! 36: experr = 0; ! 37: while (isascii(*expp) && isspace(*expp)) ! 38: expp++; ! 39: if ((c = *expp) == '\0') ! 40: return def; ! 41: if (index("+-|", *expp)) ! 42: ++expp; ! 43: n = expseq(); ! 44: if (*expp != '\0') ! 45: experr++; ! 46: if (experr) { ! 47: printe("syntax error"); ! 48: return 0; ! 49: } ! 50: switch (c) { ! 51: case '+': ! 52: n = num + n; ! 53: break; ! 54: case '-': ! 55: n = num - n; ! 56: break; ! 57: case '|': ! 58: n -= hvf ? cdivp->d_rpos : nlinsiz; ! 59: break; ! 60: } ! 61: return n; ! 62: } ! 63: ! 64: /* ! 65: * Like number(), but fewer args, for efficiency. ! 66: */ ! 67: int ! 68: numb(str, mul, div) char *str; long mul, div; ! 69: { ! 70: return number(str, mul, div, 0, 0, 0); ! 71: } ! 72: ! 73: /* ! 74: * Compute an expression sequence. ! 75: */ ! 76: expseq() ! 77: { ! 78: register int n1, n2, c; ! 79: ! 80: n1 = expval(); ! 81: if (experr) ! 82: return 0; ! 83: for (;;) { ! 84: while ((c = *expp++)==' ' || c == '\t') ! 85: ; ! 86: switch (c) { ! 87: case '<': ! 88: if (*expp == '=') { ! 89: expp++; ! 90: c = 'l'; ! 91: } ! 92: break; ! 93: case '>': ! 94: if (*expp == '=') { ! 95: expp++; ! 96: c = 'g'; ! 97: } ! 98: break; ! 99: case '=': ! 100: if (*expp == '=') ! 101: expp++; ! 102: break; ! 103: default: ! 104: if ((c != 0) && index("+-/*%&:", c)) ! 105: break; ! 106: --expp; ! 107: return n1; ! 108: } ! 109: n2 = expval(); ! 110: if (experr) ! 111: return 0; ! 112: switch (c) { ! 113: case '+': ! 114: n1 += n2; ! 115: break; ! 116: case '-': ! 117: n1 -= n2; ! 118: break; ! 119: case '*': ! 120: n1 *= n2; ! 121: break; ! 122: case '/': ! 123: if (n2 == 0) { ! 124: printe("attempted zero divide"); ! 125: experr++; ! 126: return 0; ! 127: } ! 128: n1 /= n2; ! 129: break; ! 130: case '%': ! 131: if (n2 == 0) { ! 132: printe("attempted zero modulus"); ! 133: experr++; ! 134: return 0; ! 135: } ! 136: n1 %= n2; ! 137: break; ! 138: case '<': ! 139: n1 = n1 < n2; ! 140: break; ! 141: case '>': ! 142: n1 = n1 > n2; ! 143: break; ! 144: case 'l': ! 145: n1 = n1 <= n2; ! 146: break; ! 147: case 'g': ! 148: n1 = n1 >= n2; ! 149: break; ! 150: case '=': ! 151: n1 = n1 == n2; ! 152: break; ! 153: case '!': ! 154: n1 = n1 != n2; ! 155: break; ! 156: case '&': ! 157: n1 = n1 && n2; ! 158: break; ! 159: case ':': ! 160: n1 = n1 || n2; ! 161: break; ! 162: } ! 163: } ! 164: } ! 165: ! 166: /* ! 167: * Get an operand. ! 168: */ ! 169: expval() ! 170: { ! 171: long mul, div, m, d; ! 172: register int n, c, s; ! 173: ! 174: while (isascii(c = *expp++) && isspace(c)) ! 175: ; ! 176: if (c == '(') { ! 177: n = expseq(); ! 178: if (*expp++ != ')') { ! 179: --expp; ! 180: experr++; ! 181: n = 0; ! 182: } ! 183: return n; ! 184: } ! 185: for (s = 1; c == '-'; c = *expp++) ! 186: s = -s; ! 187: for (m = 0; isascii(c) && isdigit(c); c = *expp++) ! 188: m = m * 10 + c - '0'; ! 189: d = 1; ! 190: if (c == '.') { ! 191: while (isascii(c = *expp++) && isdigit(c)) { ! 192: m = m * 10 + c - '0'; ! 193: d *= 10; ! 194: } ! 195: } ! 196: switch (c) { ! 197: case 'i': ! 198: mul = SMINCH; ! 199: div = SDINCH; ! 200: break; ! 201: case 'c': ! 202: mul = SMCENT; ! 203: div = SDCENT; ! 204: break; ! 205: case 'P': ! 206: mul = SMPICA; ! 207: div = SDPICA; ! 208: break; ! 209: case 'm': ! 210: mul = SMEMSP; ! 211: div = SDEMSP; ! 212: break; ! 213: case 'n': ! 214: mul = SMENSP; ! 215: div = SDENSP; ! 216: break; ! 217: case 'p': ! 218: mul = SMPOIN; ! 219: div = SDPOIN; ! 220: break; ! 221: case 'u': ! 222: mul = SMUNIT; ! 223: div = SDUNIT; ! 224: break; ! 225: case 'v': ! 226: mul = SMVLSP; ! 227: div = SDVLSP; ! 228: break; ! 229: default: ! 230: --expp; ! 231: mul = expmul; ! 232: div = expdiv; ! 233: } ! 234: while (isascii(c = *expp) && isalpha(c)) ! 235: expp++; ! 236: return unit(s*m*mul, d*div); ! 237: } ! 238: ! 239: /* ! 240: * Given a long numerator and denominator, divide the numerator by ! 241: * the denominator and return an int. ! 242: */ ! 243: int ! 244: unit(mul, div) long mul, div; ! 245: { ! 246: return ((div == 1) ? ((int) mul) : ((int) (mul/div))); ! 247: } ! 248: ! 249: /* end of expr.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.