|
|
1.1 ! root 1: /* conv - programmer's calculator ! 2: * conv evaluates expressions in c style syntax and reports the results ! 3: * in hexadecimal, decimal, octal, binary, and ascii character constants. ! 4: * If arguments are present, they are each evaluated as independent ! 5: * expressions, otherwise each line of standard input is evaluated. ! 6: * Input numbers follow the style of the old conv, ie ! 7: * #digits - hexadecimal ! 8: * 0xdigits - hexadecimal ! 9: * 0Xdigits - hexadecimal ! 10: * 0digits - octal ! 11: * $digits - binary ! 12: * digits - decimal ! 13: * 'character - ascii character constant ! 14: * The only expressions not allowed are those involving arrays, pointers, ! 15: * structure members, and addresses. All of the integer arithmetic ops ! 16: * are supported including variables, assignment ops, conditional expressions, ! 17: * and the comma operator. ! 18: * In addition, there is an iterative conditional expression ! 19: * <expr1> ?? <expr2> :: <expr3> ! 20: * which evaluates to while (<expr1>) <expr2>; <expr3>, that is evaluating ! 21: * <expr2> as often as <expr1> evaluates to true, then returning the value ! 22: * of <expr3>. ! 23: * Bug: function definition and evaluation should be permitted. ! 24: */ ! 25: %{ ! 26: #include <ctype.h> ! 27: ! 28: #define NNODES 1000 ! 29: ! 30: char *version = "Conv Version 2.00.\n"; ! 31: ! 32: typedef union yynode { ! 33: struct { ! 34: int n_op; ! 35: union yynode *n1_ln; ! 36: union yynode *n1_rn; ! 37: } yyn1; ! 38: struct { ! 39: int n_op; ! 40: long n2_val; ! 41: } yyn2; ! 42: struct { ! 43: char n3_name[]; ! 44: } yyn3; ! 45: } NODE; ! 46: #define n_ln yyn1.n1_ln ! 47: #define n_rn yyn1.n1_rn ! 48: #define n_val yyn2.n2_val ! 49: #define n_name yyn3.n3_name ! 50: ! 51: #define NULL ((NODE *)0) ! 52: NODE *node(); ! 53: NODE *vnode(); ! 54: NODE *nnode(); ! 55: NODE *hash(); ! 56: NODE *dotp; ! 57: long getcc(); ! 58: long getv(); ! 59: ! 60: %} ! 61: ! 62: %union { ! 63: int yy_op; ! 64: long yy_val; ! 65: NODE *yy_nod; ! 66: } ! 67: ! 68: %start list ! 69: ! 70: %token NUMBER NAME CALL LINK ! 71: %token INC DEC INCBEF DECBEF INCAFT DECAFT ! 72: ! 73: %left ',' ! 74: %right '=' ADDEQ SUBEQ MULEQ DIVEQ REMEQ ANDEQ IOREQ EOREQ SHLEQ SHREQ ! 75: %left QUQU COCO ! 76: %left '?' ':' ! 77: %left OR ! 78: %left AND ! 79: %left '|' ! 80: %left '^' ! 81: %left '&' ! 82: %left EQ NE ! 83: %left '<' '>' LE GE ! 84: %left SHL SHR ! 85: %left '+' '-' ! 86: %left '*' '/' '%' ! 87: %right '~' '!' UMINUS ! 88: ! 89: %type <yy_op> '=' ADDEQ SUBEQ MULEQ DIVEQ REMEQ ANDEQ IOREQ EOREQ SHLEQ SHREQ ! 90: %type <yy_op> '?' ':' OR AND '|' '^' '&' ! 91: %type <yy_op> EQ NE '<' '>' LE GE ! 92: %type <yy_op> SHL SHR '+' '-' '*' '/' '%' ! 93: %type <yy_op> '~' '!' UMINUS '(' ')' ',' ! 94: %type <yy_op> INC DEC INCAFT INCBEF DECAFT DECBEF ! 95: %type <yy_nod> NAME ! 96: %type <yy_val> NUMBER ! 97: %type <yy_nod> expr ! 98: ! 99: %% ! 100: ! 101: list: /* empty */ ! 102: | list '\n' ! 103: | list expr '\n' { ! 104: eval($2, dotp->n_ln); ! 105: switch ($2->n_op) { ! 106: case IOREQ: ! 107: case EOREQ: ! 108: case ANDEQ: ! 109: case SHLEQ: ! 110: case SHREQ: ! 111: case REMEQ: ! 112: case DIVEQ: ! 113: case MULEQ: ! 114: case SUBEQ: ! 115: case ADDEQ: ! 116: case '=': ! 117: break; ! 118: default: ! 119: putv(dotp->n_ln); ! 120: } ! 121: nfree($2); ! 122: } ! 123: | list error '\n' { ! 124: yyerrok; ! 125: } ! 126: ; ! 127: ! 128: ! 129: expr: expr ',' expr { ! 130: $$ = node($2, $1, $3); ! 131: } ! 132: | NAME '=' expr { ! 133: $$ = node($2, $1, $3); ! 134: } ! 135: | NAME ADDEQ expr { ! 136: $$ = node($2, $1, $3); ! 137: } ! 138: | NAME SUBEQ expr { ! 139: $$ = node($2, $1, $3); ! 140: } ! 141: | NAME MULEQ expr { ! 142: $$ = node($2, $1, $3); ! 143: } ! 144: | NAME DIVEQ expr { ! 145: $$ = node($2, $1, $3); ! 146: } ! 147: | NAME REMEQ expr { ! 148: $$ = node($2, $1, $3); ! 149: } ! 150: | NAME ANDEQ expr { ! 151: $$ = node($2, $1, $3); ! 152: } ! 153: | NAME IOREQ expr { ! 154: $$ = node($2, $1, $3); ! 155: } ! 156: | NAME EOREQ expr { ! 157: $$ = node($2, $1, $3); ! 158: } ! 159: | NAME SHLEQ expr { ! 160: $$ = node($2, $1, $3); ! 161: } ! 162: | NAME SHREQ expr { ! 163: $$ = node($2, $1, $3); ! 164: } ! 165: | NAME INC { ! 166: $$ = node(INCAFT, $1, NULL); ! 167: } ! 168: | NAME DEC { ! 169: $$ = node(DECAFT, $1, NULL); ! 170: } ! 171: | INC NAME { ! 172: $$ = node(INCBEF, $2, NULL); ! 173: } ! 174: | DEC NAME { ! 175: $$ = node(DECBEF, $2, NULL); ! 176: } ! 177: | expr QUQU expr COCO expr { ! 178: $$ = node($2, $1, node($4, $3, $5)); ! 179: } ! 180: | expr '?' expr ':' expr { ! 181: $$ = node($2, $1, node($4, $3, $5)); ! 182: } ! 183: | expr OR expr { ! 184: $$ = node($2, $1, $3); ! 185: } ! 186: | expr AND expr { ! 187: $$ = node($2, $1, $3); ! 188: } ! 189: | expr '|' expr { ! 190: $$ = node($2, $1, $3); ! 191: } ! 192: | expr '^' expr { ! 193: $$ = node($2, $1, $3); ! 194: } ! 195: | expr '&' expr { ! 196: $$ = node($2, $1, $3); ! 197: } ! 198: | expr EQ expr { ! 199: $$ = node($2, $1, $3); ! 200: } ! 201: | expr NE expr { ! 202: $$ = node($2, $1, $3); ! 203: } ! 204: | expr '<' expr { ! 205: $$ = node($2, $1, $3); ! 206: } ! 207: | expr '>' expr { ! 208: $$ = node($2, $1, $3); ! 209: } ! 210: | expr LE expr { ! 211: $$ = node($2, $1, $3); ! 212: } ! 213: | expr GE expr { ! 214: $$ = node($2, $1, $3); ! 215: } ! 216: | expr SHR expr { ! 217: $$ = node($2, $1, $3); ! 218: } ! 219: | expr SHL expr { ! 220: $$ = node($2, $1, $3); ! 221: } ! 222: | expr '+' expr { ! 223: $$ = node($2, $1, $3); ! 224: } ! 225: | expr '-' expr { ! 226: $$ = node($2, $1, $3); ! 227: } ! 228: | expr '*' expr { ! 229: $$ = node($2, $1, $3); ! 230: } ! 231: | expr '/' expr { ! 232: $$ = node($2, $1, $3); ! 233: } ! 234: | expr '%' expr { ! 235: $$ = node($2, $1, $3); ! 236: } ! 237: | '-' expr %prec UMINUS { ! 238: $$ = node(UMINUS, $2, NULL); ! 239: } ! 240: | '~' expr %prec UMINUS { ! 241: $$ = node($1, $2, NULL); ! 242: } ! 243: | '!' expr %prec UMINUS { ! 244: $$ = node($1, $2, NULL); ! 245: } ! 246: | NAME { ! 247: $$ = $1; ! 248: } ! 249: | NUMBER { ! 250: $$ = vnode($1); ! 251: } ! 252: | '(' expr ')' { ! 253: $$ = node($1, $2, NULL); ! 254: } ! 255: ; ! 256: ! 257: ! 258: %% ! 259: ! 260: yylex() ! 261: { ! 262: register int c; ! 263: char *seq = "="; ! 264: char tmpbuf[64]; ! 265: register char *p; ! 266: ! 267: again: ! 268: while ((c=getc()) == ' ' || c == '\t') ! 269: ; ! 270: ! 271: if (isalnum(c) || c == '#' || c == '$') { ! 272: tmpbuf[0] = c; ! 273: c = getc(); ! 274: for (p = tmpbuf+1; p < &tmpbuf[64] && isalnum(c); c = getc()) ! 275: *p++ = c; ! 276: ungetc(c); ! 277: *p++ = 0; ! 278: c = tmpbuf[0]; ! 279: if (c == '#' || c == '$' || isdigit(c)) { ! 280: yylval.yy_val = getv(tmpbuf); ! 281: return (NUMBER); ! 282: } ! 283: yylval.yy_nod = hash(tmpbuf); ! 284: return (NAME); ! 285: } ! 286: switch (c) { ! 287: ! 288: case '\'': ! 289: yylval.yy_val = getcc(); ! 290: return NUMBER; ! 291: case '\\': if (substr("\n", 1, 0)) ! 292: goto again; ! 293: return yylval.yy_op = c; ! 294: case '+': return substr("=+", ADDEQ, INC, c); ! 295: case '-': return substr("=-", SUBEQ, DEC, c); ! 296: case '*': return substr(seq, MULEQ, c); ! 297: case '/': return substr(seq, DIVEQ, c); ! 298: case '%': return substr(seq, REMEQ, c); ! 299: case '&': return substr("=&", ANDEQ, AND, c); ! 300: case '|': return substr("=|", IOREQ, OR, c); ! 301: case '^': return substr(seq, EOREQ, c); ! 302: case '=': return substr(seq, EQ, c); ! 303: case '!': return substr(seq, NE, c); ! 304: case '<': if ((c = substr("<=", SHL, LE, c)) == SHL) ! 305: return substr(seq, SHLEQ, c); ! 306: return yylval.yy_op = c; ! 307: case '>': if ((c = substr(">=", SHR, GE, c)) == SHR) ! 308: return substr(seq, SHREQ, c); ! 309: return yylval.yy_op = c; ! 310: case '.': ! 311: yylval.yy_nod = dotp; ! 312: return NAME; ! 313: } ! 314: return yylval.yy_op = c; ! 315: } ! 316: ! 317: NODE *reg[32]; ! 318: ! 319: NODE * ! 320: hash(bp) ! 321: char *bp; ! 322: { ! 323: int hash; ! 324: { ! 325: register char *p; ! 326: register c; ! 327: ! 328: hash = 0; ! 329: p = bp; ! 330: while (c = *p++) ! 331: hash += c; ! 332: } ! 333: { ! 334: register NODE *rp, **ep; ! 335: ! 336: bp[sizeof(NODE)] = 0; ! 337: for (ep = ®[hash & 31]; rp = *ep; ep = &rp->n_rn) { ! 338: if (strcmp(bp, rp->n_ln->n_rn->n_name) == 0) ! 339: return (rp->n_ln); ! 340: } ! 341: rp = node(NAME, vnode((long) 0), nnode(bp)); ! 342: *ep = node(LINK, rp, NULL); ! 343: return (rp); ! 344: } ! 345: } ! 346: ! 347: /* ! 348: * Depending on the next character, return one of several tokens. ! 349: */ ! 350: substr(cp, t1) ! 351: register char *cp; ! 352: int t1; ! 353: { ! 354: register int cn; ! 355: register int *tp; ! 356: ! 357: tp = &t1; ! 358: cn = getc(); ! 359: while (*cp) ! 360: if (*cp++ == cn) ! 361: return yylval.yy_op = *tp; ! 362: else ! 363: tp += 1; ! 364: ungetc(cn); ! 365: return yylval.yy_op = *tp; ! 366: } ! 367: ! 368: int peekc; ! 369: char *inputs = 0; ! 370: ! 371: getc() ! 372: { ! 373: register int c; ! 374: ! 375: if (peekc) { ! 376: c = peekc; ! 377: peekc = 0; ! 378: } else if (inputs != 0) { ! 379: if (c = *inputs) ! 380: inputs += 1; ! 381: else ! 382: c = -1; ! 383: } else ! 384: c = getchar(); ! 385: return c; ! 386: } ! 387: ! 388: ungetc(c) ! 389: { ! 390: peekc = c; ! 391: } ! 392: ! 393: main(argc, argv) ! 394: char *argv[]; ! 395: { ! 396: dotp = node(NAME, vnode((long) 0), NULL); ! 397: if (argc > 1) { ! 398: while (--argc > 0) { ! 399: ++argv; ! 400: if (!strcmp(*argv, "-V")) { ! 401: printf(version); ! 402: exit(0); ! 403: } ! 404: inputs = malloc(strlen(*argv)+2); ! 405: strcpy(inputs, *argv); ! 406: strcat(inputs, "\n"); ! 407: yyparse(); ! 408: } ! 409: } else { ! 410: inputs = 0; ! 411: yyparse(); ! 412: } ! 413: return 0; ! 414: } ! 415: yyerror() { puts("Syntax"); } ! 416: ! 417: NODE _nodes_[NNODES]; ! 418: NODE *_np_ = &_nodes_[0]; ! 419: ! 420: NODE * ! 421: alloc() ! 422: { ! 423: register NODE *np; ! 424: ! 425: np = _np_; ! 426: for (;;) { ! 427: if (np->n_op == 0) { ! 428: _np_ = np; ! 429: return (np); ! 430: } ! 431: if (++np >= &_nodes_[NNODES]) ! 432: np = &_nodes_[0]; ! 433: if (np == _np_) ! 434: break; ! 435: } ! 436: puts("No space"); ! 437: exit(1); ! 438: } ! 439: ! 440: nfree(np) ! 441: register NODE *np; ! 442: { ! 443: if (np->n_op != NAME && np->n_op != NUMBER) { ! 444: if (np->n_rn != NULL) ! 445: nfree(np->n_rn); ! 446: nfree(np->n_ln); ! 447: } ! 448: if (np->n_op != NAME) { ! 449: np->n_op = 0; ! 450: if (np < _np_) ! 451: _np_ = np; ! 452: } ! 453: } ! 454: ! 455: NODE * ! 456: node(op, nl, nr) ! 457: NODE *nl, *nr; ! 458: { ! 459: register NODE *np; ! 460: ! 461: np = alloc(); ! 462: np->n_op = op; ! 463: np->n_ln = nl; ! 464: np->n_rn = nr; ! 465: return (np); ! 466: } ! 467: ! 468: NODE * ! 469: vnode(va) ! 470: long va; ! 471: { ! 472: register NODE *np; ! 473: ! 474: np = alloc(); ! 475: np->n_op = NUMBER; ! 476: np->n_val = va; ! 477: return (np); ! 478: } ! 479: ! 480: NODE * ! 481: nnode(cp) ! 482: register char *cp; ! 483: { ! 484: register NODE *np; ! 485: register char *p; ! 486: ! 487: np = alloc(); ! 488: p = np->n_name; ! 489: while (p < np+1) ! 490: *p++ = *cp++; ! 491: return (np); ! 492: } ! 493: ! 494: eval(np, dp) ! 495: register NODE *np, *dp; ! 496: { ! 497: NODE lval, rval, *lptr; ! 498: ! 499: dp->n_op = NUMBER; ! 500: again: ! 501: switch (np->n_op) { ! 502: case '=': ! 503: case ADDEQ: ! 504: case SUBEQ: ! 505: case MULEQ: ! 506: case DIVEQ: ! 507: case REMEQ: ! 508: case SHREQ: ! 509: case SHLEQ: ! 510: case ANDEQ: ! 511: case EOREQ: ! 512: case IOREQ: ! 513: eval(np->n_rn, &rval); ! 514: /* Fall through */ ! 515: case INCBEF: ! 516: case DECBEF: ! 517: case INCAFT: ! 518: case DECAFT: ! 519: lptr = np->n_ln->n_ln; ! 520: break; ! 521: case NAME: ! 522: lptr = np->n_ln; ! 523: break; ! 524: case ',': ! 525: case '|': ! 526: case '^': ! 527: case '&': ! 528: case EQ: ! 529: case NE: ! 530: case '<': ! 531: case '>': ! 532: case LE: ! 533: case GE: ! 534: case SHR: ! 535: case SHL: ! 536: case '+': ! 537: case '-': ! 538: case '*': ! 539: case '/': ! 540: case '%': ! 541: eval(np->n_rn, &rval); ! 542: /* Fall through */ ! 543: case UMINUS: ! 544: case '~': ! 545: case '!': ! 546: case QUQU: ! 547: case '?': ! 548: case OR: ! 549: case AND: ! 550: eval(np->n_ln, &lval); ! 551: break; ! 552: case NUMBER: ! 553: lptr = np; ! 554: break; ! 555: case '(': ! 556: np = np->n_ln; ! 557: goto again; ! 558: default: ! 559: printf("Bad operator: %d\n", np->n_op); ! 560: return; ! 561: } ! 562: switch (np->n_op) { ! 563: case ',': ! 564: np = np->n_rn; ! 565: goto again; ! 566: case '=': ! 567: lptr->n_val = rval.n_val; ! 568: *dp = *lptr; ! 569: break; ! 570: case ADDEQ: ! 571: lptr->n_val += rval.n_val; ! 572: *dp = *lptr; ! 573: break; ! 574: case SUBEQ: ! 575: lptr->n_val -= rval.n_val; ! 576: *dp = *lptr; ! 577: break; ! 578: case MULEQ: ! 579: lptr->n_val *= rval.n_val; ! 580: *dp = *lptr; ! 581: break; ! 582: case DIVEQ: ! 583: lptr->n_val /= rval.n_val; ! 584: *dp = *lptr; ! 585: break; ! 586: case REMEQ: ! 587: lptr->n_val %= rval.n_val; ! 588: *dp = *lptr; ! 589: break; ! 590: case SHREQ: ! 591: lptr->n_val >>= rval.n_val; ! 592: *dp = *lptr; ! 593: break; ! 594: case SHLEQ: ! 595: lptr->n_val <<= rval.n_val; ! 596: *dp = *lptr; ! 597: break; ! 598: case ANDEQ: ! 599: lptr->n_val &= rval.n_val; ! 600: *dp = *lptr; ! 601: break; ! 602: case EOREQ: ! 603: lptr->n_val ^= rval.n_val; ! 604: *dp = *lptr; ! 605: break; ! 606: case IOREQ: ! 607: lptr->n_val |= rval.n_val; ! 608: *dp = *lptr; ! 609: break; ! 610: case INCBEF: ! 611: ++lptr->n_val; ! 612: *dp = *lptr; ! 613: break; ! 614: case DECBEF: ! 615: --lptr->n_val; ! 616: *dp = *lptr; ! 617: break; ! 618: case INCAFT: ! 619: *dp = *lptr; ! 620: lptr->n_val++; ! 621: break; ! 622: case DECAFT: ! 623: *dp = *lptr; ! 624: lptr->n_val++; ! 625: break; ! 626: case NAME: ! 627: *dp = *lptr; ! 628: break; ! 629: case NUMBER: ! 630: *dp = *lptr; ! 631: break; ! 632: case '|': ! 633: dp->n_val = lval.n_val | rval.n_val; ! 634: break; ! 635: case '^': ! 636: dp->n_val = lval.n_val ^ rval.n_val; ! 637: break; ! 638: case '&': ! 639: dp->n_val = lval.n_val & rval.n_val; ! 640: break; ! 641: case EQ: ! 642: dp->n_val = lval.n_val == rval.n_val; ! 643: break; ! 644: case NE: ! 645: dp->n_val = lval.n_val != rval.n_val; ! 646: break; ! 647: case '<': ! 648: dp->n_val = lval.n_val < rval.n_val; ! 649: break; ! 650: case '>': ! 651: dp->n_val = lval.n_val > rval.n_val; ! 652: break; ! 653: case LE: ! 654: dp->n_val = lval.n_val <= rval.n_val; ! 655: break; ! 656: case GE: ! 657: dp->n_val = lval.n_val >= rval.n_val; ! 658: break; ! 659: case SHR: ! 660: dp->n_val = lval.n_val >> rval.n_val; ! 661: break; ! 662: case SHL: ! 663: dp->n_val = lval.n_val << rval.n_val; ! 664: break; ! 665: case '+': ! 666: dp->n_val = lval.n_val + rval.n_val; ! 667: break; ! 668: case '-': ! 669: dp->n_val = lval.n_val - rval.n_val; ! 670: break; ! 671: case '*': ! 672: dp->n_val = lval.n_val * rval.n_val; ! 673: break; ! 674: case '/': ! 675: dp->n_val = lval.n_val / rval.n_val; ! 676: break; ! 677: case '%': ! 678: dp->n_val = lval.n_val % rval.n_val; ! 679: break; ! 680: case UMINUS: ! 681: dp->n_val = - lval.n_val; ! 682: break; ! 683: case '~': ! 684: dp->n_val = ~ lval.n_val; ! 685: break; ! 686: case '!': ! 687: dp->n_val = ! lval.n_val; ! 688: break; ! 689: case QUQU: ! 690: if (lval.n_val) ! 691: eval(np->n_rn->n_ln, &rval); ! 692: else ! 693: np = np->n_rn->n_rn; ! 694: goto again; ! 695: case '?': ! 696: if (lval.n_val) ! 697: np = np->n_rn->n_ln; ! 698: else ! 699: np = np->n_rn->n_rn; ! 700: goto again; ! 701: case OR: ! 702: if (lval.n_val != 0) { ! 703: *dp = lval; ! 704: break; ! 705: } ! 706: np = np->n_rn; ! 707: goto again; ! 708: case AND: ! 709: if (lval.n_val == 0) { ! 710: *dp = lval; ! 711: break; ! 712: } ! 713: np = np->n_rn; ! 714: goto again; ! 715: } ! 716: } ! 717: ! 718: long ! 719: getcc() ! 720: { ! 721: register int c, d; ! 722: c = getc(); ! 723: d = getc(); ! 724: if (d != '\'') ungetc(d); ! 725: return c; ! 726: } ! 727: ! 728: char digits[16] = "0123456789ABCDEF"; ! 729: ! 730: long ! 731: getv(dp) ! 732: register char *dp; ! 733: { ! 734: register int d; ! 735: register long v; ! 736: register int b; ! 737: ! 738: v = 0; ! 739: b = 10; d = *dp++; ! 740: switch (d) { ! 741: case '#': b = 16; d = *dp++; break; ! 742: case '$': b = 2; d = *dp++; break; ! 743: case '0': b = 8; d = *dp++; ! 744: if (d == 'x' || d == 'X') { ! 745: b = 16; d = *dp++; ! 746: } ! 747: break; ! 748: } ! 749: while ((isdigit(d) && (d -= '0') < b) ! 750: || (isupper(d) && (d += 10 - 'A') < b) ! 751: || (islower(d) && (d += 10 - 'a') < b)) { ! 752: v = v * b + d; ! 753: d = *dp++; ! 754: if (d == 0) ! 755: return v; ! 756: } ! 757: printf("Bad digit: 0%o\n", dp[-1]); ! 758: return v; ! 759: } ! 760: ! 761: putv(v) NODE *v; ! 762: { ! 763: long l; ! 764: register c; ! 765: long m; ! 766: ! 767: l = v->n_val; ! 768: /* ! 769: * hex, decimal, octal ! 770: */ ! 771: printf( "#%X %D 0%O $", l, l, l); ! 772: /* ! 773: * binary ! 774: */ ! 775: for (c=32, m=l; m; --c, m<<=1) ! 776: if (m < 0) ! 777: break; ! 778: do { ! 779: printf( m<0? "1": "0"); ! 780: m <<= 1; ! 781: } while (--c); ! 782: /* ! 783: * char ! 784: */ ! 785: printf( " '"); ! 786: if ((c=(char)l) < 0) { ! 787: printf( "~"); ! 788: c &= 0177; ! 789: } ! 790: if (c<' ' || c=='\177') { ! 791: printf( "^"); ! 792: if (c == '\177') ! 793: c = '?'; ! 794: else ! 795: c += '@'; ! 796: } ! 797: printf( "%c'\n", c); ! 798: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.