1: /* 2: * Focal, 1981. 3: * A number of small routines that 4: * don't go anywhere else. 5: */ 6: #include "focal.h" 7: 8: /* 9: * Put out the text line 10: * pointed to by `lp' to the FILE 11: * pointed to by `fp'. 12: * Used any time a source line is 13: * printed. 14: */ 15: void putline(lp, fp) 16: register struct line *lp; 17: FILE *fp; 18: { 19: fprintf(fp, "%02d.%02d %s\n", lp->l_gno, lp->l_lno, lp->l_text); 20: } 21: 22: /* 23: * Get a line number. 24: * The `c' argument is the first 25: * character, and is assumed to be ok. 26: * The line number, along with its general 27: * shape, is packed into the structure 28: * pointed to by `lnop'. 29: */ 30: void getlno(lnop, c) 31: register struct lno *lnop; 32: register c; 33: { 34: register int gn, ln; 35: static char badlno[] = "Bad line or group number"; 36: 37: if (c < 0) 38: c = getnb(); 39: if (c=='\0' || c==';') { 40: --ctp; 41: lnop->ln_type = LN_NONE; 42: return; 43: } 44: if (c=='A' || c=='a') { 45: while (isalpha(*ctp)) 46: ++ctp; 47: lnop->ln_type = LN_ALL; 48: return; 49: } 50: if (!isdigit(c)) 51: diag(badlno); 52: if ((gn = getnum(c))<1 || gn>99) 53: diag(badlno); 54: if (*ctp != '.') { 55: lnop->ln_gno = gn; 56: lnop->ln_lno = 0; 57: lnop->ln_type = LN_GRP; 58: return; 59: } 60: ++ctp; 61: if ((ln=getnum(*ctp++)) == 0) { 62: lnop->ln_gno = gn; 63: lnop->ln_lno = 0; 64: lnop->ln_type = LN_GRP; 65: return; 66: } 67: if (ln<1 | ln>99) 68: diag(badlno); 69: lnop->ln_gno = gn; 70: lnop->ln_lno = ln; 71: lnop->ln_type = LN_LINE; 72: } 73: 74: /* 75: * Get a number. The argument 76: * `c' is the first character of the 77: * number, and is assumed to be valid. 78: * Return the number read. 79: */ 80: int getnum(c) 81: register c; 82: { 83: register int n; 84: 85: n = 0; 86: while (isdigit(c)) { 87: n = 10*n + c - '0'; 88: c = *ctp++; 89: } 90: --ctp; 91: return (n); 92: } 93: 94: /* 95: * Allocate a new line, with a 96: * data array large enough to hold the 97: * string pointed to by `cp'. 98: * The line and group number fields are 99: * not filled in. 100: * Return a pointer to the line. 101: */ 102: struct line * 103: alocline(cp) 104: register char *cp; 105: { 106: register struct line *lp = NULL; 107: 108: lp = (struct line *) malloc(sizeof(*lp)+strlen(cp)+1); 109: if (lp == NULL) 110: diag("Out of memory"); 111: return (lp); 112: } 113: 114: /* 115: * Print a diagnostic. The `s' 116: * argument is an error message. The 117: * offending line is displayed, with a flag 118: * at the point where the scan failed. 119: * This routine does not return; it just 120: * does a non local goto back to the command 121: * dispatcher. 122: */ 123: void diag(s) 124: const char *s; 125: { 126: register struct line *lp; 127: register char *cp; 128: 129: printf("%s!\n", s); 130: if ((lp=clp) != NULL) { 131: putline(lp, stdout); 132: printf(" "); 133: cp = lp->l_text; 134: } else { 135: printf("*%s\n ", cbuf); 136: cp = cbuf; 137: } 138: while (cp < ctp) { 139: putchar(' '); 140: ++cp; 141: } 142: printf("^\n"); 143: while (controlv != NULL) 144: popdo(); 145: longjmp(env, 0); 146: } 147: 148: /* 149: * Get the next non blank 150: * character from the current source line. 151: * Return it. 152: */ 153: int getnb() 154: { 155: register int c; 156: 157: while ((c = *ctp++)==' ' || c=='\t') 158: ; 159: return (c); 160: } 161: /* 162: * drand48 163: * 164: * return pseudo-random number in interval [0.0, 1.0) 165: * 166: */ 167: double drand48() 168: { 169: return (double) (rand() / 32768.0); 170: }