Annotation of freem/src/fma_globals.c, revision 1.1
1.1 ! snw 1: /*
! 2: * *
! 3: * * *
! 4: * * *
! 5: * ***************
! 6: * * * * *
! 7: * * MUMPS *
! 8: * * * * *
! 9: * ***************
! 10: * * *
! 11: * * *
! 12: * *
! 13: *
! 14: * fma_globals.c
! 15: * fmadm - globals
! 16: *
! 17: *
! 18: * Author: Serena Willis <jpw@coherent-logic.com>
! 19: * Copyright (C) 1998 MUG Deutschland
! 20: * Copyright (C) 2020 Coherent Logic Development LLC
! 21: *
! 22: *
! 23: * This file is part of FreeM.
! 24: *
! 25: * FreeM is free software: you can redistribute it and/or modify
! 26: * it under the terms of the GNU Affero Public License as published by
! 27: * the Free Software Foundation, either version 3 of the License, or
! 28: * (at your option) any later version.
! 29: *
! 30: * FreeM is distributed in the hope that it will be useful,
! 31: * but WITHOUT ANY WARRANTY; without even the implied warranty of
! 32: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 33: * GNU Affero Public License for more details.
! 34: *
! 35: * You should have received a copy of the GNU Affero Public License
! 36: * along with FreeM. If not, see <https://www.gnu.org/licenses/>.
! 37: *
! 38: **/
! 39:
! 40: #include <stdlib.h>
! 41: #include <stdio.h>
! 42: #include <stdlib.h>
! 43: #include <string.h>
! 44: #include <dirent.h>
! 45: #include <time.h>
! 46: #include <unistd.h>
! 47: #include <sys/types.h>
! 48: #include <sys/stat.h>
! 49: #include <fcntl.h>
! 50:
! 51: #include "fmadm.h"
! 52:
! 53: void gl (char *global, short kf, short df, short nr, int chop);
! 54: int gverify (char *gpath);
! 55: static short int g_collate (); /* if 't' follows 's' in MUMPS collating */
! 56: int key_check (char *key);
! 57: void check ();
! 58: void show ();
! 59:
! 60: /* global variables for gverify */
! 61: short filedes; /* file descriptor */
! 62: char block[MAXLEV][BLOCKLEN]; /* block to be read */
! 63: char *blck; /* dto. as pointer */
! 64: unsigned long llink[MAXLEV]; /* left link pointers */
! 65: unsigned long rlink[MAXLEV]; /* right link pointers */
! 66: short offsets[MAXLEV]; /* offsets */
! 67: short type[MAXLEV]; /* block type */
! 68: extern short level; /* current level */
! 69: unsigned long no_of_blks; /* number of blocks */
! 70: unsigned long freeblks; /* free blocks list */
! 71: char key[256]; /* current key in pointer block scan */
! 72: short exstat = 0; /* exit status */
! 73: void showpath (); /* display path of pointers */
! 74: /* end of global variables for gverify */
! 75:
! 76:
! 77: int fma_globals_list (int optc, char **opts)
! 78: {
! 79: DIR *dir;
! 80: struct dirent *ent;
! 81:
! 82: char filename[STRLEN];
! 83:
! 84: int ct = 0;
! 85:
! 86: printf ("\nFreeM Global Listing\n");
! 87: printf ("--------------------\n\n");
! 88:
! 89: printf ("Namespace: %s\n", fma_namespace);
! 90: printf ("Global Path: %s\n\n", fma_global_path);
! 91:
! 92: if ((dir = opendir (fma_global_path)) == NULL) {
! 93: fprintf (stderr, "fmadm: could not open global directory %s\n", fma_global_path);
! 94: return 1;
! 95: }
! 96:
! 97: while ((ent = readdir (dir)) != NULL) {
! 98:
! 99: strncpy (filename, ent->d_name, STRLEN - 1);
! 100:
! 101: if (filename[0] == '^' && filename[1] != '$') {
! 102: printf (" %s\n", filename);
! 103: ct++;
! 104: }
! 105:
! 106: }
! 107:
! 108: printf ("\n\n - %d globals found\n\n", ct);
! 109: closedir (dir);
! 110:
! 111: return 0;
! 112: }
! 113:
! 114: int fma_globals_examine (int optc, char **opts)
! 115: {
! 116:
! 117: DIR *dir;
! 118: struct dirent *ent;
! 119:
! 120: char gpath[STRLEN];
! 121: int i;
! 122: int ct = 0;
! 123:
! 124: if ((dir = opendir (fma_global_path)) == NULL) {
! 125: fprintf (stderr, "fmadm: could not open global directory %s\n", fma_global_path);
! 126: return 1;
! 127: }
! 128:
! 129: printf ("\nFreeM Global Examine\n");
! 130: printf ("--------------------\n\n");
! 131:
! 132: printf ("Namespace: %s\n", fma_namespace);
! 133: printf ("Global Path: %s\n", fma_global_path);
! 134: printf ("Globals Selected: ");
! 135:
! 136:
! 137: if (optc > 1) {
! 138:
! 139: for (i = fma_base_opt; i <= optc; i++) {
! 140: printf ("%s ", opts[i]);
! 141: }
! 142:
! 143: printf ("\n\n");
! 144:
! 145: }
! 146: else {
! 147: printf ("[ENTIRE NAMESPACE]\n\n");
! 148: }
! 149:
! 150:
! 151: if (optc > 1) {
! 152:
! 153: for (i = fma_base_opt; i < optc; i++) {
! 154:
! 155: snprintf (gpath, STRLEN - 1, "%s/%s", fma_global_path, opts[i]);
! 156: gl (gpath, FALSE, FALSE, FALSE, strlen (fma_global_path));
! 157:
! 158: ct++;
! 159:
! 160: }
! 161:
! 162: }
! 163: else {
! 164:
! 165: while ((ent = readdir (dir)) != NULL) {
! 166:
! 167: strncpy (gpath, ent->d_name, STRLEN - 1);
! 168:
! 169: if (gpath[0] == '^' && gpath[1] != '$') {
! 170:
! 171: snprintf (gpath, STRLEN - 1, "%s/%s", fma_global_path, ent->d_name);
! 172:
! 173: gl (gpath, FALSE, FALSE, FALSE, strlen (fma_global_path));
! 174:
! 175: ct++;
! 176:
! 177: }
! 178:
! 179: }
! 180:
! 181: }
! 182:
! 183: printf ("\n\n");
! 184: printf (" - %d globals examined\n\n", ct);
! 185:
! 186: return 0;
! 187:
! 188: }
! 189:
! 190: int fma_globals_remove (int optc, char **opts)
! 191: {
! 192:
! 193: char gpath[STRLEN];
! 194: int i;
! 195: int ct = 0;
! 196: int er = 0;
! 197: int tot = 0;
! 198:
! 199: printf ("\nFreeM Global Removal\n");
! 200: printf ("--------------------\n\n");
! 201:
! 202: printf ("Namespace: %s\n", fma_namespace);
! 203: printf ("Global Path: %s\n\n", fma_global_path);
! 204:
! 205: for (i = fma_base_opt; i < optc; i++) {
! 206: printf ("%-10s\t", opts[i]);
! 207:
! 208: snprintf (gpath, STRLEN - 1, "%s/%s", fma_global_path, opts[i]);
! 209:
! 210: if (unlink (gpath) == -1) {
! 211: printf ("[FAIL]\n");
! 212: er++;
! 213: }
! 214: else {
! 215: printf ("[OK]\n");
! 216: ct++;
! 217: }
! 218:
! 219: tot++;
! 220:
! 221: }
! 222:
! 223: printf ("\nRemoved %d globals [%d errors/%d attempted]\n\n", ct, er, tot);
! 224:
! 225: return 0;
! 226:
! 227: }
! 228:
! 229: int fma_globals_verify (int optc, char **opts)
! 230: {
! 231: DIR *dir;
! 232: struct dirent *ent;
! 233:
! 234: char gpath[STRLEN];
! 235: int i;
! 236: int ct = 0;
! 237:
! 238: if ((dir = opendir (fma_global_path)) == NULL) {
! 239: fprintf (stderr, "fmadm: could not open global directory %s\n", fma_global_path);
! 240: return 1;
! 241: }
! 242:
! 243: printf ("\nFreeM Global Verify\n");
! 244: printf ("-------------------\n\n");
! 245:
! 246: printf ("Namespace: %s\n", fma_namespace);
! 247: printf ("Global Path: %s\n", fma_global_path);
! 248: printf ("Globals Selected: ");
! 249:
! 250: if (optc > fma_base_opt) {
! 251:
! 252: for (i = fma_base_opt; i < optc; i++) {
! 253: printf ("%s ", opts[i]);
! 254: }
! 255:
! 256: printf ("\n\n");
! 257:
! 258: }
! 259: else {
! 260: printf ("[ENTIRE NAMESPACE]\n\n");
! 261: }
! 262:
! 263:
! 264: if (optc > fma_base_opt) {
! 265:
! 266: for (i = fma_base_opt; i < optc; i++) {
! 267:
! 268: snprintf (gpath, STRLEN - 1, "%s/%s", fma_global_path, opts[i]);
! 269:
! 270: exstat = 0;
! 271: gverify (gpath);
! 272:
! 273: printf ("\n\t%d error(s) in %s\n", exstat, gpath);
! 274:
! 275: ct++;
! 276:
! 277: }
! 278:
! 279: }
! 280: else {
! 281:
! 282: while ((ent = readdir (dir)) != NULL) {
! 283:
! 284: strncpy (gpath, ent->d_name, STRLEN - 1);
! 285:
! 286: if (gpath[0] == '^') {
! 287:
! 288: snprintf (gpath, STRLEN - 1, "%s/%s", fma_global_path, ent->d_name);
! 289:
! 290: exstat = 0;
! 291: gverify (gpath);
! 292:
! 293: printf ("\n\t%d errors in %s\n", exstat, gpath);
! 294:
! 295: ct++;
! 296:
! 297: }
! 298:
! 299: }
! 300:
! 301: }
! 302:
! 303: printf ("\n\n");
! 304: printf (" - %d globals verified\n\n", ct);
! 305:
! 306: return 0;
! 307:
! 308: }
! 309:
! 310:
! 311: /* PRIVATE FUNCTIONS */
! 312:
! 313: /***
! 314: * gl(): list global
! 315: *
! 316: * global: name of global
! 317: * kf: key flag
! 318: * df: data flag
! 319: * nr: naked reference flag
! 320: */
! 321: void gl (char *global, short kf, short df, short nr, int chop)
! 322: {
! 323: short filedes; /* file descriptor */
! 324: char block[BLOCKLEN]; /* block to be read */
! 325: char key[512];
! 326: char prevkey[512]; /* previous key */
! 327: char data[1024]; /* if data has CTRLs it may become */
! 328: /* so long */
! 329: unsigned long blknbr;
! 330: short offset;
! 331: short length;
! 332: short koffs;
! 333: short dkf = TRUE;
! 334:
! 335: short CtrlFlag;
! 336: short n, k1;
! 337: register int i, j, k, ch;
! 338:
! 339: if ((filedes = open (global, 0)) == -1) {
! 340: printf ("%s: cannot open\012\015", global);
! 341:
! 342: return;
! 343: }
! 344:
! 345: if (kf == FALSE && df == FALSE) {
! 346: kf = TRUE;
! 347: df = TRUE;
! 348: }
! 349: else {
! 350: dkf = FALSE;
! 351: }
! 352:
! 353: blknbr = ROOT;
! 354: prevkey[0] = 0;
! 355: prevkey[1] = 0;
! 356: prevkey[2] = 0;
! 357:
! 358: for (;;) {
! 359:
! 360: lseek (filedes, blknbr * BLOCKLEN, 0);
! 361:
! 362: if (read (filedes, block, BLOCKLEN) == 0) {
! 363: fprintf (stderr, "\015*** something wrong ***\033[K\n\r");
! 364: exit (0);
! 365: }
! 366:
! 367: if (block[BTYP] == DATA) goto first;
! 368:
! 369: i = UNSIGN (block[0]) + 2;
! 370: blknbr = UNSIGN (block[i]) * 65536 + UNSIGN (block[i + 1]) * 256 + UNSIGN (block[i + 2]);
! 371:
! 372: }
! 373:
! 374: again:
! 375:
! 376: if (blknbr == 0) {
! 377: close (filedes);
! 378: return;
! 379: }
! 380:
! 381: lseek (filedes, blknbr * 1024L, 0);
! 382: read (filedes, block, BLOCKLEN);
! 383:
! 384: first:
! 385:
! 386: offset = UNSIGN (block[OFFS]) * 256 + UNSIGN (block[OFFS + 1]);
! 387: blknbr = UNSIGN (block[RLPTR]) * 65536 + UNSIGN (block[RLPTR + 1]) * 256 + UNSIGN (block[RLPTR + 2]);
! 388:
! 389: i = 0;
! 390: while (i < offset) {
! 391:
! 392: length = UNSIGN (block[i++]);
! 393: k = koffs = UNSIGN (block[i++]);
! 394:
! 395: if ((i + length) > offset) break;
! 396:
! 397: for (j = 0; j < length; j++) key[k++] = block[i++];
! 398:
! 399: key[k] = g_EOL;
! 400: {
! 401:
! 402: short ch0, i, j, k;
! 403:
! 404: j = 0;
! 405: i = 0;
! 406: data[j++] = '(';
! 407: k = 1;
! 408:
! 409: while ((ch = UNSIGN (key[i++])) != g_EOL) {
! 410:
! 411: if (k) {
! 412: k = 0;
! 413: if (ch > SP) data[j++] = '"';
! 414: }
! 415:
! 416: ch0 = (ch >= SP ? (ch >> 1) : /* 'string' chars */
! 417: (ch < 20 ? (ch >> 1) + '0' : /* 0...9 */
! 418: (ch >> 1) + SP)); /* '.' or '-' */
! 419:
! 420: if (ch0 == DEL) {
! 421: if ((ch0 = (UNSIGN (key[i++]) >> 1)) == DEL) {
! 422: ch0 = (UNSIGN (key[i++]) >> 1) + DEL;
! 423: }
! 424:
! 425: ch0 += DEL;
! 426: data[j] = '<';
! 427: data[++j] = '0' + ch0 / 100;
! 428: data[++j] = '0' + (ch0 % 100) / 10;
! 429: data[++j] = '0' + ch0 % 10;
! 430: data[++j] = '>';
! 431:
! 432: }
! 433: else {
! 434: data[j] = ch0;
! 435: }
! 436:
! 437: if (data[j++] == '"') data[j++] = '"';
! 438:
! 439: if (ch & 01) {
! 440:
! 441: if (ch > SP) data[j++] = '"';
! 442:
! 443: data[j++] = ',';
! 444: k = 1;
! 445:
! 446: }
! 447:
! 448: }
! 449:
! 450: data[j--] = 0;
! 451: data[j] = ')';
! 452:
! 453: if (j == 0) data[0] = 0;
! 454:
! 455: while (j >= 0) {
! 456: if ((ch = data[--j]) < SP || ch >= DEL) break;
! 457: }
! 458:
! 459: k1 = 0;
! 460: if (nr) {
! 461:
! 462: if (prevkey[0]) {
! 463:
! 464: n = ch = 0;
! 465:
! 466: while (data[n] == prevkey[n]) {
! 467:
! 468: if (prevkey[n] == '"') ch = !ch;
! 469: if (!ch && k1 == 0 && (prevkey[n] == '(')) k1 = n + 1;
! 470: if (!ch && (prevkey[n] == ',')) k1 = n + 1;
! 471:
! 472: n++;
! 473:
! 474: }
! 475:
! 476: while (prevkey[n]) {
! 477:
! 478: if (prevkey[n] == '"') ch = !ch;
! 479:
! 480: if (!ch && (prevkey[n] == ',')) {
! 481: k1 = 0;
! 482: break;
! 483: }
! 484:
! 485: n++;
! 486:
! 487: }
! 488:
! 489: }
! 490:
! 491: strcpy (prevkey, data);
! 492:
! 493: if (k1 > 1) {
! 494: strcpy (&data[1], &data[k1]);
! 495: }
! 496:
! 497: }
! 498:
! 499: if (j < 0) {
! 500:
! 501: if (kf) {
! 502:
! 503: if (k1) {
! 504: printf ("%c%s", '^', data);
! 505: }
! 506: else {
! 507: printf ("%s%s", global + chop + 1, data);
! 508: }
! 509:
! 510: }
! 511:
! 512: if (dkf && !nr) {
! 513: printf ("=");
! 514: }
! 515: else if (kf) {
! 516: printf ("\n");
! 517: }
! 518:
! 519: }
! 520: else {
! 521: fprintf (stderr, "[%d][%d] <illegal subscript>\n", length, koffs);
! 522: }
! 523:
! 524: }
! 525:
! 526: length = UNSIGN (block[i++]);
! 527:
! 528: stcpy0 (data, &block[i], (long) length);
! 529:
! 530: data[length] = EOL;
! 531:
! 532: if (numeric (data)) {
! 533: data[length] = 0;
! 534: i += length;
! 535: }
! 536: else {
! 537:
! 538: CtrlFlag = 0;
! 539: data[0] = '"';
! 540: k = 1;
! 541:
! 542: while (length-- > 0) {
! 543:
! 544: ch = UNSIGN (block[i++]);
! 545:
! 546: if ((ch >= SP) && (ch < DEL)) {
! 547:
! 548: if (CtrlFlag) { /* close Bracket after CTRL */
! 549:
! 550: data[k++] = ')';
! 551: data[k++] = '_';
! 552: data[k++] = '"';
! 553:
! 554: CtrlFlag = 0;
! 555:
! 556: }
! 557:
! 558: if ((data[k++] = ch) == '"') data[k++] = ch;
! 559:
! 560: }
! 561: else {
! 562:
! 563: if (((ch >= NUL) && (ch < SP)) || ch == DEL) {
! 564:
! 565: if (CtrlFlag) {
! 566: data[k++] = ',';
! 567: }
! 568: else {
! 569:
! 570: if (k > 1) {
! 571: data[k++] = '"';
! 572: data[k++] = '_';
! 573: }
! 574: else {
! 575: k = 0;
! 576: }
! 577:
! 578: data[k++] = '$';
! 579: data[k++] = 'C';
! 580: data[k++] = '(';
! 581:
! 582: CtrlFlag = 1;
! 583:
! 584: }
! 585:
! 586: if (ch == DEL) {
! 587: data[k++] = '1';
! 588: ch -= 100;
! 589: }
! 590:
! 591: if (ch >= 10) {
! 592: data[k++] = ch / 10 + '0';
! 593: ch = ch % 10;
! 594: }
! 595:
! 596: data[k++] = ch + '0';
! 597:
! 598: }
! 599: else {
! 600:
! 601: if (CtrlFlag) { /* close Bracket after CTRL */
! 602:
! 603: data[k++] = ')';
! 604: data[k++] = '_';
! 605: data[k++] = '"';
! 606:
! 607: CtrlFlag = 0;
! 608:
! 609: }
! 610:
! 611: data[k++] = '<';
! 612:
! 613: if (ch > 99) {
! 614: data[k++] = '0' + (ch / 100);
! 615: ch = ch % 100;
! 616: }
! 617:
! 618: if (ch > 9) {
! 619: data[k++] = '0' + (ch / 10);
! 620: ch = ch % 10;
! 621: }
! 622:
! 623: data[k++] = '0' + ch;
! 624: data[k++] = '>';
! 625:
! 626: }
! 627: }
! 628: }
! 629:
! 630: if (CtrlFlag) {
! 631: data[k++] = ')';
! 632: }
! 633: else {
! 634: data[k++] = '"';
! 635: }
! 636:
! 637: data[k] = 0;
! 638:
! 639: }
! 640:
! 641: if (df) printf ("%s\n", data);
! 642:
! 643: }
! 644:
! 645: if (i != offset) fprintf (stderr, "\nwrong offset %d vs. %d\n", offset, i);
! 646:
! 647: goto again;
! 648:
! 649: }
! 650:
! 651: int gverify (char *gpath)
! 652: {
! 653: register int j;
! 654:
! 655: printf ("\n%s:\n\n", gpath);
! 656:
! 657: if ((filedes = open (gpath, 0)) == -1) {
! 658: fprintf (stderr, "Cannot open file %s\007\n\r", gpath);
! 659: return 1;
! 660: }
! 661:
! 662: j = 0;
! 663:
! 664: while (j < MAXLEV) {
! 665:
! 666: rlink[j] = 0;
! 667: llink[j] = 0;
! 668:
! 669: j++;
! 670:
! 671: }
! 672:
! 673: level = 0;
! 674:
! 675: check (ROOT);
! 676:
! 677: j = 1; /* ignore level zero: there is no rightlink pointer (freeblocks instead) */
! 678: while (j < MAXLEV) { /* check last right link pointers (all zero!) */
! 679:
! 680: if (rlink[j] != 0) {
! 681: printf ("\tblock #%ld right link pointer mismatch 0 vs. %ld\012\015", llink[j], rlink[j]);
! 682: showpath ();
! 683: }
! 684:
! 685: j++;
! 686:
! 687: }
! 688:
! 689: /* check free blocks */
! 690: freeblks = UNSIGN (block[0][FREE]) * 65536 +
! 691: UNSIGN (block[0][FREE + 1]) * 256 +
! 692: UNSIGN (block[0][FREE + 2]);
! 693:
! 694: while (freeblks) {
! 695:
! 696: unsigned long free;
! 697: int i;
! 698:
! 699: if (freeblks > no_of_blks) {
! 700: printf ("\tblock# %ld (free list) greater than number of blocks (%ld)\012\015", freeblks, no_of_blks);
! 701: showpath ();
! 702: }
! 703:
! 704: lseek (filedes, (long) (freeblks) * BLOCKLEN, 0);
! 705:
! 706: if (read (filedes, block[0], BLOCKLEN) < BLOCKLEN) {
! 707:
! 708: printf ("\tblock #%ld is (partially) empty\012\015", freeblks);
! 709: showpath ();
! 710:
! 711: exit (exstat);
! 712:
! 713: }
! 714:
! 715: j = UNSIGN (block[0][OFFS]) * 256 +
! 716: UNSIGN (block[0][OFFS + 1]); /* offset */
! 717:
! 718: freeblks = UNSIGN (block[0][RLPTR]) * 65536 +
! 719: UNSIGN (block[0][RLPTR + 1]) * 256 +
! 720: UNSIGN (block[0][RLPTR + 1]);
! 721:
! 722: i = 0;
! 723:
! 724: while (i < j) {
! 725:
! 726: free = UNSIGN (block[0][i++]) * 65536;
! 727: free += UNSIGN (block[0][i++]) * 256;
! 728: free += UNSIGN (block[0][i++]);
! 729:
! 730: if (free > no_of_blks) {
! 731: printf ("\tblock #%ld (free) greater than number of blocks (%ld)\012\015", free, no_of_blks);
! 732: showpath ();
! 733: }
! 734:
! 735: lseek (filedes, free * BLOCKLEN, 0);
! 736: read (filedes, block[1], BLOCKLEN);
! 737:
! 738: if (block[1][BTYP] != EMPTY) {
! 739:
! 740: printf ("\tblock #%ld expected block type: EMPTY\012\015", free);
! 741:
! 742: if (++exstat >= ERRLIM) {
! 743: fprintf (stderr, "Error limit exceeded\012\015");
! 744: return exstat;
! 745: }
! 746:
! 747: }
! 748:
! 749: }
! 750:
! 751: }
! 752:
! 753: return exstat;
! 754:
! 755: }
! 756:
! 757: void check (unsigned long blknbr)
! 758: {
! 759: unsigned long left; /* current left link pointer */
! 760: unsigned long right; /* current right link pointer */
! 761: long i;
! 762: long k;
! 763:
! 764: lseek (filedes, blknbr * BLOCKLEN, 0);
! 765: blck = block[level];
! 766:
! 767: if (read (filedes, blck, BLOCKLEN) < BLOCKLEN) {
! 768: printf ("\tblock #%ld is (partially) empty\012\015", blknbr);
! 769: showpath ();
! 770: }
! 771:
! 772: type[level] = blck[BTYP];
! 773:
! 774: left = UNSIGN (blck[LLPTR]) * 65536 +
! 775: UNSIGN (blck[LLPTR + 1]) * 256 +
! 776: UNSIGN (blck[LLPTR + 2]);
! 777:
! 778: right = UNSIGN (blck[RLPTR]) * 65536 +
! 779: UNSIGN (blck[RLPTR + 1]) * 256 +
! 780: UNSIGN (blck[RLPTR + 2]);
! 781:
! 782: if (blknbr == ROOT) {
! 783: no_of_blks = UNSIGN (block[0][NRBLK]) * 65536 +
! 784: UNSIGN (block[0][NRBLK + 1]) * 256 +
! 785: UNSIGN (block[0][NRBLK + 2]);
! 786: }
! 787: else {
! 788:
! 789: if (blknbr > no_of_blks) {
! 790: printf ("\tblock# %ld greater than number of blocks (%ld)\012\015", blknbr, no_of_blks);
! 791: showpath ();
! 792: }
! 793:
! 794: }
! 795:
! 796: offsets[level] = UNSIGN (blck[OFFS]) * 256 + UNSIGN (blck[OFFS + 1]);
! 797:
! 798: if (rlink[level] != 0L && rlink[level] != blknbr) {
! 799: printf ("\tblock #%ld right link pointer mismatch %ld vs. %ld\012\015", llink[level], blknbr, rlink[level]);
! 800: showpath ();
! 801: }
! 802:
! 803: if (llink[level] != 0L && left != llink[level]) {
! 804: printf ("\tblock #%ld left link pointer mismatch %ld vs. %ld\012\015", blknbr, left, llink[level]);
! 805: showpath ();
! 806: }
! 807:
! 808: rlink[level] = right;
! 809: llink[level] = blknbr;
! 810:
! 811: if (blknbr != ROOT) {
! 812:
! 813: k = UNSIGN (blck[0]);
! 814: i = 0;
! 815:
! 816: while (i < k) {
! 817: if (blck[i + 2] != key[i]) {
! 818: printf ("\tblock #%ld first key mismatch to pointer block(%ld)\012\015", blknbr, llink[level - 1]);
! 819: showpath ();
! 820: break;
! 821: }
! 822: i++;
! 823: }
! 824:
! 825: }
! 826:
! 827: switch (type[level]) {
! 828:
! 829: case EMPTY:
! 830: printf ("\tblock #%ld unexpected block type: EMPTY\012\015", blknbr);
! 831: showpath ();
! 832: break;
! 833:
! 834: case FBLK:
! 835: printf ("\tblock #%ld unexpected block type: FBLK\012\015", blknbr);
! 836: showpath ();
! 837: break;
! 838:
! 839: case POINTER:
! 840: case BOTTOM:
! 841: /*******************************/
! 842: /* scan pointer block */
! 843: {
! 844: register long i;
! 845: register long k;
! 846: short j;
! 847: short len;
! 848: char key1[256];
! 849:
! 850: key1[0] = g_EOL;
! 851: i = 0;
! 852:
! 853: while (i < offsets[level]) {
! 854:
! 855: j = i++; /* save adress of current entry */
! 856:
! 857: if ((len = UNSIGN (blck[j]) + (k = UNSIGN (blck[i++]))) > 255) {
! 858: printf ("\tblock #%ld key too long\012\015", blknbr);
! 859: showpath ();
! 860: }
! 861: else {
! 862:
! 863: if (len == 0 && j) {
! 864: printf ("\tblock #%ld empty key\012\015", blknbr);
! 865: showpath ();
! 866: }
! 867:
! 868: while (k < len) key[k++] = blck[i++];
! 869:
! 870: key[k] = g_EOL;
! 871:
! 872: if (key_check (key)) {
! 873: printf ("\tblock #%ld illegal key\012\015", blknbr);
! 874: showpath ();
! 875: }
! 876:
! 877: if (g_collate (key1, key) == 0) {
! 878: printf ("\tblock #%ld collation mismatch\012\015", blknbr);
! 879: show (key1);
! 880: show (key);
! 881: showpath ();
! 882: }
! 883:
! 884: stcpy0 (key1, key, k + 1);
! 885: level++;
! 886:
! 887: check ((long) (UNSIGN (blck[i]) * 65536 +
! 888: UNSIGN (blck[i + 1]) * 256 +
! 889: UNSIGN (blck[i + 2])));
! 890:
! 891: blck = block[--level];
! 892:
! 893: }
! 894:
! 895: i += PLEN;
! 896:
! 897: if (i > DATALIM) {
! 898: printf ("\tblock #%ld pointer in status bytes\012\015", blknbr);
! 899: showpath ();
! 900: }
! 901:
! 902: }
! 903:
! 904: if (i > offsets[level]) {
! 905: printf ("\tblock #%ld offset mismatch %ld vs. %d\012\015", blknbr, i, offsets[level]);
! 906: showpath ();
! 907: }
! 908: }
! 909: break;
! 910:
! 911: case DATA:
! 912: /* scan data block */
! 913: {
! 914: register long i;
! 915: register long k;
! 916: short len;
! 917: char key0[256];
! 918: char key1[256];
! 919:
! 920: if (type[level - 1] != BOTTOM) {
! 921: printf ("\tblock #%ld unexpected block type: DATA\012\015", blknbr);
! 922: showpath ();
! 923: }
! 924:
! 925: key1[0] = g_EOL;
! 926: i = 0;
! 927:
! 928: while (i < offsets[level]) {
! 929:
! 930: len = UNSIGN (blck[i++]);
! 931: len += (k = UNSIGN (blck[i++]));
! 932:
! 933: if (len > 255) {
! 934: printf ("\tblock #%ld key too long\012\015", blknbr);
! 935: showpath ();
! 936: i += len - k;
! 937: }
! 938: else {
! 939:
! 940: if (len == 0 && i > 2) {
! 941: printf ("\tblock #%ld empty key\012\015", blknbr);
! 942: showpath ();
! 943: }
! 944:
! 945: while (k < len) key0[k++] = blck[i++];
! 946:
! 947: key0[k] = g_EOL;
! 948:
! 949: if (key_check (key0)) {
! 950: printf ("\tblock #%ld illegal key\012\015", blknbr);
! 951: showpath ();
! 952: }
! 953:
! 954: if (g_collate (key1, key0) == 0) {
! 955: printf ("\tblock #%ld collation mismatch\012\015", blknbr);
! 956: show (key1);
! 957: show (key0);
! 958: showpath ();
! 959: }
! 960:
! 961: stcpy0 (key1, key0, k + 1);
! 962: }
! 963:
! 964: k = i + 1;
! 965: len = UNSIGN (blck[i]);
! 966: i += UNSIGN (blck[i]);
! 967: i++; /* skip data */
! 968:
! 969: #ifdef NEVER
! 970: while (k < i) {
! 971: if (blck[k++] & ~0177) {
! 972: printf ("\tblock #%ld illegal character in data string\012\015", blknbr);
! 973: showpath ();
! 974: break;
! 975: }
! 976: }
! 977: #endif /* NEVER */
! 978:
! 979: if (i > DATALIM) {
! 980: printf ("\tblock #%ld data in status bytes\012\015", blknbr);
! 981: showpath ();
! 982: }
! 983:
! 984: }
! 985:
! 986: if (i > offsets[level]) {
! 987: printf ("\tblock #%ld offset mismatch %ld vs. %d\012\015", blknbr, i, offsets[level]);
! 988: showpath ();
! 989: }
! 990: }
! 991: break;
! 992:
! 993: default:
! 994: printf ("\tblock #%ld illegal type %d\012\015", blknbr, type[level]);
! 995: showpath ();
! 996:
! 997: }
! 998:
! 999: return;
! 1000:
! 1001: } /* end check */
! 1002: void
! 1003: showpath ()
! 1004: { /* display path of pointers */
! 1005: int i;
! 1006:
! 1007: if (level > 1)
! 1008: for (i = 0; i < level; i++)
! 1009: printf (" path level(%d)=%ld\012\015", i, llink[i]);
! 1010: if (++exstat >= ERRLIM) {
! 1011: fprintf (stderr, "Error limit exceeded (%hd errors)\012\015", exstat, ERRLIM);
! 1012: return;
! 1013: }
! 1014: return;
! 1015: }
! 1016: /******************************************************************************/
! 1017: int key_check (char *key) /* checks a global key in compressed form */
! 1018: {
! 1019: short ch,
! 1020: typ = 0;
! 1021:
! 1022: while ((ch = UNSIGN (*key++)) != g_EOL) {
! 1023: if (ch == (DEL << 1)) {
! 1024: if ((ch = UNSIGN (*key++)) == (DEL << 1))
! 1025: key++;
! 1026: ch = SP;
! 1027: }
! 1028: if (ch >= SP) {
! 1029: if (typ == 2)
! 1030: return 1;
! 1031: typ = 1;
! 1032: }
! 1033: /* alphabetics */
! 1034: else {
! 1035: if (typ == 1)
! 1036: return 1;
! 1037: typ = 2; /* numerics '.' '-' */
! 1038: if (ch >= 20 && ch != POINT && ch != MINUS)
! 1039: return 1; /* illegal character */
! 1040: }
! 1041: if (ch & 01)
! 1042: typ = 0; /* comma between two indices */
! 1043: }
! 1044: return 0;
! 1045: } /* end key_check */
! 1046: /******************************************************************************/
! 1047: static short int
! 1048: g_collate (s, t) /* if 't' follows 's' in MUMPS collating */
! 1049: char s[]; /* sequence a TRUE is returned */
! 1050: char t[];
! 1051:
! 1052: {
! 1053: register int chs = *s;
! 1054: register int cht = *t;
! 1055: register int tx = 0;
! 1056: register int sx;
! 1057: short dif;
! 1058:
! 1059: /* the empty one is the leader! */
! 1060: if (chs == g_EOL) {
! 1061: if (cht == g_EOL)
! 1062: return 2;
! 1063: return 1;
! 1064: }
! 1065: if (cht == g_EOL)
! 1066: return FALSE;
! 1067:
! 1068: while (cht == s[tx]) {
! 1069: if (cht == g_EOL)
! 1070: return 0;
! 1071: cht = t[++tx];
! 1072: } /* (s==t) */
! 1073: chs = s[tx];
! 1074: if (chs == OMEGA)
! 1075: return 0;
! 1076: if (chs == ALPHA)
! 1077: return cht != g_EOL;
! 1078: if (chs == g_EOL && t[tx - 1] & 01)
! 1079: return 1;
! 1080: if (cht == g_EOL && s[tx - 1] & 01)
! 1081: return 0;
! 1082:
! 1083: /* vade retro usque ad comma */
! 1084: if (tx > 0) {
! 1085: tx--;
! 1086: while ((t[tx] & 01) == 0)
! 1087: if (--tx < 0)
! 1088: break;
! 1089: tx++;
! 1090: }
! 1091: chs = s[tx];
! 1092: cht = t[tx];
! 1093: if (UNSIGN (chs) <= POINT) { /* then come numerics */
! 1094: if (UNSIGN (cht) > POINT)
! 1095: return UNSIGN (cht) != g_EOL;
! 1096: /* both are numeric! now compare numeric values */
! 1097: /*****g_comp()*********************************************************/
! 1098: if (chs == MINUS) {
! 1099: if (cht != MINUS)
! 1100: return 1;
! 1101: } else {
! 1102: if (cht == MINUS)
! 1103: return 0;
! 1104: }
! 1105: if (chs == 1 && cht == POINT)
! 1106: return 1;
! 1107: if (cht == 1 && chs == POINT)
! 1108: return 0;
! 1109: dif = sx = tx;
! 1110: while (s[sx] != POINT) {
! 1111: if (s[sx++] & 01)
! 1112: break;
! 1113: }
! 1114: while (t[tx] != POINT) {
! 1115: if (t[tx++] & 01)
! 1116: break;
! 1117: }
! 1118: if (tx > sx)
! 1119: return (cht != MINUS);
! 1120: if (tx < sx)
! 1121: return (cht == MINUS);
! 1122: tx = dif;
! 1123: while ((cht >> 1) == (chs >> 1)) {
! 1124: if (cht & 01)
! 1125: return t[dif] == MINUS;
! 1126: if (chs & 01)
! 1127: return t[dif] != MINUS;
! 1128: chs = s[++tx];
! 1129: cht = t[tx];
! 1130: }
! 1131: return (((cht >> 1) > (chs >> 1)) == (t[dif] != MINUS))
! 1132: && (t[tx] != s[tx]);
! 1133: /**********************************************************************/
! 1134: }
! 1135: if (UNSIGN (cht) <= POINT)
! 1136: return 0;
! 1137: while ((dif = (UNSIGN (cht) >> 1) - (UNSIGN (chs) >> 1)) == 0) { /* ASCII collating */
! 1138: if ((cht & 01) && ((chs & 01) == 0))
! 1139: return 0;
! 1140: if ((chs & 01) && ((cht & 01) == 0))
! 1141: return 1;
! 1142: chs = s[++tx];
! 1143: cht = t[tx];
! 1144: }
! 1145: if (chs == g_EOL)
! 1146: return 1;
! 1147: if (cht == g_EOL)
! 1148: return 0;
! 1149: return dif > 0;
! 1150: } /* end g_collate */
! 1151: /******************************************************************************/
! 1152: void
! 1153: show (key)
! 1154: char key[]; /* key in internal format to be expanded and shown */
! 1155: {
! 1156: int k,
! 1157: ch,
! 1158: i,
! 1159: j;
! 1160: char data[256];
! 1161:
! 1162: k = 0;
! 1163: i = 0;
! 1164: j = 0;
! 1165: while ((ch = UNSIGN (key[i++])) != g_EOL) {
! 1166: if (k) {
! 1167: k = 0;
! 1168: if (ch > ' ')
! 1169: data[j++] = '"';
! 1170: }
! 1171: data[j] = (ch > SP ? (ch >> 1) : (ch < 20 ? (ch >> 1) + '0' : (ch >> 1) + ' '));
! 1172: if (data[j++] == '"')
! 1173: data[j++] = '"';
! 1174: if (ch & 01) {
! 1175: if (ch > SP)
! 1176: data[j++] = '"';
! 1177: data[j++] = ',';
! 1178: k = 1;
! 1179: }
! 1180: }
! 1181: data[j--] = 0;
! 1182: printf ("(%s);", data);
! 1183: return;
! 1184: } /* end show() */
! 1185: /******************************************************************************/
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>