Annotation of freem/src/fma_globals.c, revision 1.1.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>