File:  [Coherent Logic Development] / freem / src / symtab_bltin.c
Revision 1.3: download - view: text, annotated - select for diffs
Sun Mar 9 15:20:18 2025 UTC (6 months, 2 weeks ago) by snw
Branches: MAIN
CVS tags: HEAD
Begin formatting overhaul and REUSE compliance

    1: /*
    2:  *                            *
    3:  *                           * *
    4:  *                          *   *
    5:  *                     ***************
    6:  *                      * *       * *
    7:  *                       *  MUMPS  *
    8:  *                      * *       * *
    9:  *                     ***************
   10:  *                          *   *
   11:  *                           * *
   12:  *                            *
   13:  *
   14:  *   symtab.c
   15:  *      FreeM local system table and user-defined special variable table 
   16:  *
   17:  *  
   18:  *   Author: Serena Willis <snw@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: #define ZNEW        'N'
   42: #include "mpsdef.h"
   43: #include <string.h>
   44: #include <sys/ipc.h>
   45: #include <sys/shm.h>
   46: #include <sys/sem.h>
   47: #include <unistd.h>
   48: #include "mdebug.h"
   49: #include "merr.h"
   50: #include "consttbl.h"
   51: #include "shmmgr.h"
   52: 
   53: /* Turn this on to get tons of lovely debugging messages about
   54: symbol-table calls */
   55: /* #define DEBUG_SYM  */
   56: 
   57: short restoring_consts = FALSE;
   58: int semid_symtab;
   59: 
   60: #if !defined(__OpenBSD__) && !defined(__APPLE__)
   61: union semun {
   62:     int              val;    /* Value for SETVAL */
   63:     struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
   64:     unsigned short  *array;  /* Array for GETALL, SETALL */
   65:     struct seminfo  *__buf;  /* Buffer for IPC_INFO
   66:                                 (Linux-specific) */
   67: };
   68: #endif
   69: 
   70: 
   71: long str2long(char *string) 
   72: {
   73:     int loop = 0; 
   74:     int mult = 1;
   75:     int exp = 1;
   76:     long value = 0;
   77:     
   78:     if (string[0] == '-') { 
   79:         mult = -1; 
   80:         string++; 
   81:     }
   82:     
   83:     while(string[loop] != EOL && string[loop] >= '0' && string[loop] <= '9') loop++;
   84:     
   85:     loop--;
   86:     
   87:     while(loop > -1) {
   88:         value += (string[loop] - '0') * exp;
   89:         exp *= 10; loop--;
   90:     }
   91: 
   92:     value *= mult;
   93:     
   94:     return value;
   95: }
   96: 
   97: void symtab_init (void)
   98: {
   99:     register int i;
  100:     union semun arg;
  101:     key_t symtab_sk;
  102:     symtab_sk = ftok (config_file, 6);
  103: 
  104:     
  105:     if (first_process) {
  106:         
  107:         for (i = 0; i < 128; i++) {
  108:             shm_config->hdr->alphptr[i] = 0L;
  109:         }
  110: 
  111:         shm_config->hdr->symlen = PSIZE;
  112:         shm_config->hdr->s = &mbpartition[PSIZE] - 256;
  113:         shm_config->hdr->PSIZE = DEFPSIZE;
  114:         shm_config->hdr->argptr = mbpartition;
  115:         
  116:         fprintf (stderr, "symtab_init:  initializing memory-backed globals\r\n");        
  117: 
  118:         semid_symtab = semget (symtab_sk, 1, 0666 | IPC_CREAT);
  119:         if (semid_symtab == -1) {
  120:             fprintf (stderr, "symtab_init:  failed to create symbol table semaphore\r\n");
  121:             exit (1);
  122:         }
  123:         else {
  124:             fprintf (stderr, "symtab_init:  symbol table semaphore created with semid %d\r\n", semid_symtab);
  125:         }
  126: 
  127:         arg.val = 1;
  128:         if (semctl (semid_symtab, 0, SETVAL, arg) == -1) {
  129:             fprintf (stderr, "symtab_init:  failed to initialize symbol table semaphore\r\n");
  130:             exit (1);
  131:         }
  132:         else {
  133:             fprintf (stderr, "symtab_init:  symbol table semaphore initialized\r\n");
  134:         }
  135: 
  136:         fprintf (stderr, "symtab_init:  allocating partition for memory-backed globals\r\n");
  137:         
  138:         mbpartition = (char *) shm_alloc ((size_t) PSIZE + 2);
  139:         NULLPTRCHK(mbpartition,"symtab_init");
  140: 
  141:         shm_config->hdr->partition = mbpartition;
  142:         
  143:         if (symtab_get_sem ()) {
  144:             for (i = 0; i < 128; i++) shm_config->hdr->alphptr[i] = 0L;
  145:             symtab_release_sem ();
  146:         }
  147:         
  148:     }
  149:     else {
  150: 
  151:         semid_symtab = semget (symtab_sk, 1, 0);
  152:         if (semid_symtab == -1) {
  153:             fprintf (stderr, "symtab_init:  could not attach to symbol table semaphore\r\n");
  154:             exit (1);
  155:         }
  156:         
  157:         mbpartition = shm_config->hdr->partition;
  158: 
  159:     }
  160:    
  161: }
  162: 
  163: short have_symtab_sem = FALSE;
  164: 
  165: short symtab_get_sem(void)
  166: {
  167:     int tries;
  168:     struct sembuf s = {0, -1, IPC_NOWAIT};
  169: 
  170:     if (have_symtab_sem) {
  171:         return TRUE;
  172:     }
  173:     
  174:     for (tries = 0; tries < 5; tries++) {
  175: 
  176:         if (semop (semid_symtab, &s, 1) != -1) {
  177:             have_symtab_sem = TRUE;           
  178:             return TRUE;
  179:         }
  180: 
  181:         sleep (1);
  182: 
  183:     }
  184:     fprintf (stderr, "symtab_get_sem:  fail\r\n");
  185:     
  186:     have_symtab_sem = FALSE;
  187:     return FALSE;
  188: }
  189: 
  190: void symtab_release_sem(void)
  191: {
  192:     struct sembuf s = {0, 1, 0};
  193: 
  194:     semop (semid_symtab, &s, 1);
  195: 
  196:     have_symtab_sem = FALSE;
  197: }
  198: 
  199: 
  200: void symtab_shm (short action, char *key, char *data)		/* symbol table functions */
  201: {
  202:     char *old_s;
  203:     char *old_argptr;
  204:     long old_psize;
  205:     long old_symlen;
  206:     unsigned long stptrs[128];
  207:     register int i;
  208:     char *old_partition = partition;
  209:     partition = mbpartition;
  210: 
  211:     writing_mb = TRUE;
  212: 
  213:     if (symtab_get_sem ()) {
  214: 
  215:         /* save off current non-shared symtab state */
  216:         old_s = s;
  217:         old_argptr = argptr;
  218:         old_psize = PSIZE;
  219:         old_symlen = symlen;
  220:         for (i = 0; i < 128; i++) {
  221:             stptrs[i] = alphptr[i];
  222:         }
  223: 
  224:         /* replace symtab state with the values from the shared symtab */
  225:         s = shm_config->hdr->s;
  226:         argptr = shm_config->hdr->argptr;
  227:         PSIZE = shm_config->hdr->PSIZE;
  228:         symlen = shm_config->hdr->symlen;       
  229:         for (i = 0; i < 128; i++) {
  230:             alphptr[i] = shm_config->hdr->alphptr[i];
  231:         }
  232: 
  233:         /* execute the action (symtab_bltin will now be working with the shared symbol table) */
  234:         symtab_bltin (action, key, data);
  235: 
  236:         /* copy new alphptr state back to shared memory */
  237:         for (i = 0; i < 128; i++) {
  238:             shm_config->hdr->alphptr[i] = alphptr[i];
  239:         }
  240: 
  241:         /* restore non-shared symtab alphptr state */
  242:         for (i = 0; i < 128; i++) {
  243:             alphptr[i] = stptrs[i];
  244:         }
  245: 
  246:         /* write the new shared symtab state back to shared memory */
  247:         shm_config->hdr->s = s;
  248:         shm_config->hdr->argptr = argptr;
  249:         shm_config->hdr->PSIZE = PSIZE;
  250:         shm_config->hdr->symlen = symlen;
  251: 
  252:         /* restore the non-shared symtab state */
  253:         s = old_s;
  254:         argptr = old_argptr;
  255:         PSIZE = old_psize;
  256:         symlen = old_symlen;        
  257:         
  258:         symtab_release_sem ();
  259:         
  260:     }
  261:     else {
  262:         fprintf (stderr, "symtab_shm:  failed to acquire symbol table sempahore\r\n");
  263:     }
  264: 
  265:     writing_mb = FALSE;
  266:     partition = old_partition;        
  267:     
  268: }
  269: 
  270: /* local symbol table management */
  271: /* (+)functions are now re-implemented */
  272: /* (!)functions are new */
  273: /* (?)re-implemented, with issues */
  274: /* +set_sym      +get_sym   */
  275: 
  276: /* +kill_sym     +$data     */
  277: /* +kill_all     +$fra_order    */
  278: /* +killexcl     +fra_query     */
  279: /* +new_sym      +bigquery  */
  280: /* +new_all      +getinc    */
  281: /* +newexcl                 */
  282: /* +killone      +m_alias   */
  283: /* !merge_sym    +zdata     */
  284: /* !pop_sym       */
  285: 
  286: 
  287: 
  288: /* The symbol table is placed at the high end of 'partition'. It begins at
  289: * 'symlen' and ends at 'PSIZE'. The layout is
  290: * (keylength)(key...)(<EOL>)(datalength)(data...[<EOL>])
  291: * The keys are sorted in $order sequence.
  292: * 
  293: * ****possible future layout with less space requirements****
  294: * (keylength)(statusbyte)(key...)[(datalength)(data...[<EOL>])]
  295: * 'keylength' is the length of 'key' overhead bytes not included.
  296: * 'statusbyte' is an indicator with the following bits:
  297: * 0  (LSB)        1=data information is missing 0=there is a data field
  298: * 1               1=key is numeric              0=key is alphabetic
  299: * 2..7            0..number of previous key_pieces
  300: * note, that the status byte of a defined unsubscripted variable
  301: * is zero.
  302: * If a subscripted variable is stored, the variablename and each
  303: * subscript are separate entries in the symbol table.
  304: * E.g. S USA("CA",6789)="California" ; with $D(ABC)=0 before the set
  305: * then the following format is used:
  306: * (3)(    1)ABC
  307: * (2)(1*4+1)CA
  308: * (4)(2*4+2)6789(10)California
  309: * ****end of "possible future layout"****
  310: * To have the same fast access regardless of the position in the
  311: * alphabet for each character a pointer to the first variable beginning
  312: * with that letter is maintained. (0 indicates there's no such var.)
  313: */
  314: 
  315: void symtab_bltin (short action, char *key, char *data)		/* symbol table functions */
  316: {
  317:     /* must be static:                */
  318:     static unsigned long tryfast = 0L;	/* last $order reference          */
  319: 
  320:     /* the following variables may    */
  321:     /* be static or not               */
  322:     static unsigned short nocompact = TRUE;	/* flag: do not compact symtab if */
  323: 
  324:     /* value becomes shorter          */
  325:     /* be static or dynamic:          */
  326: 
  327:     static long keyl, datal;			/* length of key and data                 */
  328:     static long kill_from;
  329:     static char tmp1[256], tmp2[256], tmp3[256];
  330: 
  331:     register long i, j, k, k1;
  332:     char tt_with[STRLEN];
  333:     char tt_key[STRLEN];
  334: 
  335: #ifdef DEBUG_SYM
  336: 
  337:     int i0, i1;
  338:     char *start;
  339: 
  340: #endif
  341: 
  342:     if (restoring_consts == FALSE) {
  343:         if (((action % 2) == 0) && const_is_defined (key)) {
  344:             merr_raise (CMODIFY);
  345:             return;
  346:         }
  347:     }
  348:     
  349:     if (action == kill_all) goto no_with;
  350:     if ((stlen (key) >= 5) && (strncmp (key, "%INT.", 5) == 0)) goto no_with;
  351:     if (strncmp (key, "^$", 2) == 0) goto no_with;
  352:     if (strncmp (key, "$", 1) == 0) goto no_with;
  353:     
  354:     stcpy (tt_with, i_with);
  355:     stcpy (tt_key, key);
  356:     
  357:     stcnv_m2c (tt_with);
  358:     stcnv_m2c (tt_key);
  359:     
  360:     snprintf (key, 100, "%s%s\201\201", tt_with, tt_key);
  361: 
  362:     
  363: no_with:    
  364:     
  365:     
  366:     if (dbg_enable_watch && ((action % 2) == 0)) dbg_fire_watch (key);
  367: 
  368:     if (key && key[1] != '$') stcpy (zloc, key);   
  369:     
  370:     if (v22ptr) {
  371: 
  372:         procv22 (key);
  373:         
  374:         if (key[0] == '^') {
  375:             
  376:             char    zrsav[256];
  377:             int     naksav;
  378:             char    gosav[256];
  379: 
  380:             stcpy (zrsav, zref);
  381:         
  382:             naksav = nakoffs;
  383:         
  384:             stcpy (gosav, g_o_val);
  385:             global  (action, key, data);
  386: 
  387:             stcpy (zref, zrsav);
  388:             
  389:             nakoffs = naksav;
  390:             
  391:             stcpy (l_o_val, g_o_val);
  392:             stcpy (g_o_val, gosav);
  393:             
  394:             return;
  395: 
  396:         }
  397: 
  398:     }
  399: 
  400:     /* process optional limitations */
  401:     if (glvnflag.all && key[0] >= '%' && key[0] <= 'z') {
  402:         
  403:         if ((i = glvnflag.one[0])) {	/* number of significant chars */
  404:             
  405:             j = 0;
  406:         
  407:             while ((k1 = key[j]) != DELIM && k1 != EOL) {
  408:                 
  409:                 if (j >= i) {
  410:        
  411:                     while ((k1 = key[++j]) != DELIM && k1 != EOL) ;
  412:         
  413:                     stcpy (&key[i], &key[j]);
  414:         
  415:                     break;
  416:         
  417:                 }
  418:                 
  419:                 j++;
  420:             }
  421:         
  422:         }
  423:         
  424:         if (glvnflag.one[1]) {		/* upper/lower sensitivity */
  425:         
  426:             j = 0;
  427:         
  428:             while ((k1 = key[j]) != DELIM && k1 != EOL) {
  429:                 
  430:                 if (k1 >= 'a' && k1 <= 'z') key[j] = k1 - 32;
  431:             
  432:                 j++;
  433: 
  434:             }
  435: 
  436:         }
  437: 
  438:         
  439:         if ((i = glvnflag.one[2])) {
  440: 
  441:             /* IMPACT: x11-94-28 */
  442:             if (stlen (key) > i) {
  443:                 merr_raise (M75);
  444:                 return;
  445:             }				/* key length limit */
  446: 
  447:         }
  448: 
  449:         if ((i = glvnflag.one[3])) {	/* subscript length limit */
  450:             
  451:             j = 0;
  452:             
  453:             while ((k1 = key[j++]) != DELIM && k1 != EOL) ;
  454:             
  455:             if (k1 == DELIM) {
  456: 
  457:                 k = 0;
  458: 
  459:                 for (;;) {
  460: 
  461:                     k1 = key[j++];
  462:                     
  463:                     if (k1 == DELIM || k1 == EOL) {
  464:                         
  465:                         if (k > i) {
  466:                             merr_raise (M75);
  467:                             return;
  468:                         }
  469:                     
  470:                         k = 0;
  471:                     
  472:                     }
  473:                     
  474:                     if (k1 == EOL) break;
  475:                     
  476:                     k++;
  477:                 
  478:                 }
  479:             }
  480:         }
  481:     }
  482: 
  483: 
  484:     
  485:     if (aliases && (action != m_alias)) {	/* there are aliases */
  486:     
  487:         i = 0;
  488:         j = 0;
  489:     
  490:         while (i < aliases) {
  491: 
  492:             k1 = i + UNSIGN (ali[i]) + 1;
  493:             
  494:             /* is current reference an alias ??? */
  495:             j = 0;
  496:             
  497:             while (ali[++i] == key[j]) {
  498: 
  499:                 if (ali[i] == EOL) break;
  500:             
  501:                 j++;
  502: 
  503:             }
  504: 
  505:             /* yes, it is, so resolve it now! */
  506:             if (ali[i] == EOL && (key[j] == EOL || key[j] == DELIM)) {
  507:                 
  508:                 stcpy (tmp1, key);
  509:                 stcpy (key, &ali[i + 1]);
  510:                 stcat (key, &tmp1[j]);
  511:                 
  512:                 i = 0;
  513:                 
  514:                 continue;		/* try again, it might be a double alias! */
  515: 
  516:             }
  517: 
  518:             i = k1;
  519: 
  520:         }
  521: 
  522:     }
  523: 
  524: #ifdef DEBUG_SYM 
  525:     
  526:     printf("DEBUG (%d): ",action);
  527: 
  528:     if(key) {
  529:     
  530:         printf("[key] is [");
  531:     
  532:         for(loop=0; key[loop] != EOL; loop++) printf("%c",(key[loop] == DELIM) ? '!' : key[loop]);
  533: 
  534:         printf("]\r\n");
  535: 
  536:     } 
  537:     else {  
  538:         printf("No key passed in.\r\n");
  539:     }
  540: 
  541:     if(data) {
  542:         
  543:         printf("[data] (datalen) is [");
  544:     
  545:         for(loop=0; data[loop] != EOL; loop++) printf("%c", data[loop]);
  546:     
  547:         printf("] (%d)\r\n",stlen(data));
  548:         printf("[Numeric?] is [%d]\r\n",is_numeric(data));
  549: 
  550:     } 
  551:     else { 
  552:         printf("No data passed in.\r\n");
  553:     }
  554: 
  555: #endif 
  556: 
  557:     switch (action) {
  558: 
  559:         
  560:         case get_sym:			/* retrieve */
  561:             
  562: 
  563:             /* OLD get_sym routine */     
  564:             if ((i = alphptr[(int) key[0]])) {
  565: 
  566: //                printf ("alphptr match; writing_mb = %d\r\n", writing_mb);                
  567:                 
  568:                 k = 1;
  569:                 j = i + 1;			/* first char always matches! */
  570:                 
  571:                 do {
  572:                     
  573:                     while (key[k] == partition[++j]) {	/* compare keys */
  574: 
  575:                         if (key[k] == EOL) {
  576: 
  577:                             /* IMPACT: x11-94-28  */
  578:                             i = UNSIGN (partition[++j]);
  579:                             
  580:                             if (i < 4) {
  581:                             
  582:                                 k = 0;
  583:                             
  584:                                 while (k < i) data[k++] = partition[++j];
  585: 
  586:                             } 
  587:                             else {
  588:                                 stcpy0 (data, &partition[j + 1], i);
  589:                             }
  590:                             
  591:                             data[i] = EOL;
  592:                             
  593:                             return;
  594:                         
  595:                         }
  596:                         
  597:                         k++;
  598: 
  599:                     }
  600: 
  601:                     i += UNSIGN (partition[i]);	/* skip key */
  602:                     i += UNSIGN (partition[i]) + 1;		/* skip data */
  603: 
  604:                     k = 0;
  605:                     j = i;
  606:                 
  607:                 } while (i < PSIZE);
  608:             }
  609: 
  610:             merr_raise (M6);
  611:             data[0] = EOL;
  612:             
  613:             return;
  614: 
  615: 
  616: 
  617: 
  618: 
  619:         case set_sym:			/* store/create variable */
  620: 
  621: 
  622:             /* HANDLE ISVs FROM unnew() */
  623: 
  624:             if (key[0] == '$') {
  625: 
  626:                 switch (key[1]) {
  627: 
  628:                     case 't':               /* $TEST */
  629: 
  630:                         test = data[0];
  631:                         break;
  632: 
  633:                     case 'z':               /* $Z ISVs */
  634: 
  635:                         if (key[2] == 'r') {  /* $ZREFERENCE / $REFERENCE */
  636:                             stcpy (zref, data);
  637:                         }
  638: 
  639:                         break;
  640: 
  641:                 }
  642: 
  643:             }
  644: 
  645:             datal = stlen (data);		/* data length */
  646: 
  647: 
  648: 
  649: 
  650: 
  651:             /* Old set_sym routine */
  652:             /* check whether the key has subscripts or not */
  653:             if ((keyl = stlen (key) + 2) > STRLEN) { 
  654:                 merr_raise (M75); 
  655:                 return; 
  656:             }
  657:             
  658:             k1 = 0;
  659:             i = 1;
  660:             
  661:             while (key[i] != EOL) {
  662: 
  663:                 if (key[i++] == DELIM) {
  664:                     k1 = i;
  665:                     break;
  666:                 }
  667: 
  668:             }
  669: 
  670:             if ((i = alphptr[(int) key[0]])) {	/* previous entry */
  671:                 
  672:                 j = i + 1;
  673:                 k = 1;
  674: 
  675:             } 
  676:             else {
  677:                 
  678:                 i = symlen;
  679:                 j = i;
  680:                 k = 0;
  681: 
  682:             }
  683: 
  684:             if (k1 == 0)			/* key was unsubscripted */
  685: 
  686:                 /* compare keys */            
  687:                 while (i < PSIZE) {
  688:                     
  689:                     while (key[k] == partition[++j]) {
  690:                     
  691:                         if (key[k] == EOL) goto old;
  692:                     
  693:                         k++;
  694:                     
  695:                     }
  696:                     
  697:                     if (key[k] < partition[j]) break;
  698:                     
  699:                     i += UNSIGN (partition[i]);	/* skip key */
  700:                     i += UNSIGN (partition[i]) + 1;		/* skip data */
  701:                     
  702:                     j = i;
  703:                     k = 0;
  704: 
  705:                 } 
  706:                 else {				/* key was subscripted */
  707:             
  708:                     /* compare keys */
  709:                     while (i < PSIZE) {
  710:                         
  711:                         while (key[k] == partition[++j]) {
  712:                             
  713:                             if (key[k] == EOL) goto old;
  714:                             
  715:                             k++;
  716: 
  717:                         }
  718: 
  719:                         
  720:                         if (k < k1) {
  721:                             if (key[k] < partition[j]) break;
  722:                         } 
  723:                         else {
  724:                             
  725:                             long    m, n, o, ch;
  726: 
  727:                             /* get complete subscripts */
  728:                             n = k;
  729:                             
  730:                             while (key[--n] != DELIM) ;
  731:                             
  732:                             n++;
  733:                             m = j + n - k;
  734:                             o = 0;
  735:                             
  736:                             while ((ch = tmp3[o++] = partition[m++]) != EOL && ch != DELIM) ;
  737:                             
  738:                             if (ch == DELIM) tmp3[--o] = EOL;
  739:                             
  740:                             o = 0;
  741:                             
  742:                             while ((ch = tmp2[o++] = key[n++]) != EOL && ch != DELIM) ;
  743:                             
  744:                             if (ch == DELIM) tmp2[--o] = EOL;
  745: 
  746:                             if (collate (tmp3, tmp2) == FALSE) {
  747:                                 if (stcmp (tmp2, tmp3) || ch == EOL) break;
  748:                             }
  749: 
  750:                         }
  751:                     
  752:                         i += UNSIGN (partition[i]);	/* skip key */
  753:                         i += UNSIGN (partition[i]) + 1;		/* skip data */
  754:                         
  755:                         j = i;
  756:                         k = 0;
  757: 
  758:                     }
  759:                 }
  760: 
  761:                 /* if    entry found,     i pointer to searched entry
  762:                 * else  entry not found, i pointer to alphabetically next entry */
  763:                 
  764:                 /* new entry */
  765:                 if (setop) {
  766: 
  767:                     tmp1[0] = EOL;
  768:                     
  769:                     m_op (tmp1, data, setop);
  770:                     
  771:                     setop = 0;
  772:                     
  773:                     if (merr () > OK) return;
  774: 
  775:                     datal = stcpy (data, tmp1);
  776:                 
  777:                 }
  778:                 
  779:                 k = i;
  780:                 j = key[0];
  781:                 i = keyl + datal + 1;
  782:                 
  783:                 if (alphptr['%']) alphptr['%'] -= i;
  784: 
  785:                 for (k1 = 'A'; k1 <= j; k1++) {
  786:                     if (alphptr[k1]) alphptr[k1] -= i;
  787:                 }
  788: 
  789:                 i = k - i;
  790:                 
  791:                 if (alphptr[j] == 0 || alphptr[j] > i) alphptr[j] = i;
  792: 
  793:                 j = keyl + datal + 1;
  794:                 i = symlen - j;
  795:                 
  796:                 if (i <= 256) {			/* more space needed. try to get it */
  797:                     
  798:                     long    dif = 0L;
  799: 
  800:                     dif = getpmore ();
  801:                     
  802:                     if (dif == 0) {
  803:                         merr_raise (STORE);
  804:                         return;
  805:                     }
  806: 
  807:                     data = argptr;
  808:                     i += dif;
  809:                     k += dif;
  810: 
  811:                 }
  812: 
  813:                 symlen = i;
  814:                 s = &partition[i] - 256;
  815:                 
  816:                 stcpy0 (&partition[i], &partition[j + i], k - i);
  817:                 
  818:                 i = k - (keyl + datal + 1);
  819:                 partition[i++] = (char) (keyl);
  820:                 
  821:                 stcpy (&partition[i], key);	/* store new key */
  822:                 
  823:                 i += keyl - 1;
  824: 
  825:                 /* IMPACT: x11-94-28 */
  826:                 partition[i++] = (char) (datal);
  827:                 
  828:                 stcpy0 (&partition[i], data, datal);	/* store new data */
  829:                 
  830:                 return;
  831: 
  832:                 /* there is a previous value */
  833: old:
  834:                 i += UNSIGN (partition[i]);
  835:                 
  836:                 if (setop) {
  837: 
  838:                     j = UNSIGN (partition[i]);
  839:                     stcpy0 (tmp1, &partition[i + 1], j);
  840:                     
  841:                     tmp1[j] = EOL;
  842:                     
  843:                     m_op (tmp1, data, setop);
  844:                     
  845:                     setop = 0;
  846:                     
  847:                     if (merr () > OK) return;
  848: 
  849:                     datal = stcpy (data, tmp1);
  850:                 
  851:                 }
  852: 
  853: old0:				/* entry from getinc */
  854: 
  855:                 /* IMPACT: x11-94-28 */
  856:                 j = UNSIGN (partition[i]) - datal;
  857:                 
  858:                 if (j < 0) {			/* more space needed */
  859: 
  860:                     if ((symlen + j) <= 256) {
  861:                      
  862:                         long    dif = 0L;
  863: 
  864:                         dif = getpmore ();
  865:                     
  866:                         if (dif == 0L) {
  867:                             merr_raise (STORE);
  868:                             return;
  869:                         }
  870: 
  871:                         data = argptr;
  872:                         i += dif;
  873:     
  874:                     }
  875:     
  876:                     for (k = 36; k < key[0]; k++) {
  877:                         if (alphptr[k])
  878:                         alphptr[k] += j;
  879:                     }
  880: 
  881:                     if (alphptr[k] && alphptr[k] < i) alphptr[k] += j;
  882: 
  883:                     stcpy0 (&partition[symlen + j], &partition[symlen], i - symlen);
  884:                     
  885:                     i += j;
  886:                     symlen += j;
  887:                     s = &partition[symlen] - 256;
  888:                     tryfast = 0;
  889: 
  890:                 } 
  891:                 else if (j > 0) {		/* surplus space */
  892:                                         
  893:                     if (nocompact) {
  894:                         
  895:                         /* in a dynamic environment it is sufficient to          */
  896:                         /* set newdatalength=olddatalength                       */ 
  897:                         
  898:                         datal += j;
  899: 
  900:                     }
  901:                     else {
  902:                 
  903:                         /* instead of compression of the local symbol table,     */
  904:                         /* which the following piece of code does                */
  905:                         
  906:                         symlen += j;
  907:                         s = &partition[symlen] - 256;
  908:                         
  909:                         for (k = 36; k < key[0]; k++) {
  910:                             if (alphptr[k]) alphptr[k] += j;
  911:                         }
  912: 
  913:                         if (alphptr[k] && alphptr[k] < i) alphptr[k] += j;
  914:                         
  915:                         i += j;
  916:                         k = i;
  917:                         j = i - j;
  918:                         
  919:                         while (i >= symlen) {
  920:                             partition[i--] = partition[j--];
  921:                         }
  922: 
  923:                         i = k;
  924:                         tryfast = 0;
  925:                         nocompact = TRUE;
  926:                     
  927:                     }
  928:                 }
  929: 
  930:                 /* IMPACT: x11-94-28 */
  931:                 partition[i++] = (char) (datal);
  932:                 j = datal;
  933:                 
  934:                 if (j < 4) {
  935:                     
  936:                     k = 0;
  937:                     
  938:                     while (k < j) partition[i++] = data[k++];
  939:                     
  940:                     return;
  941: 
  942:                 }
  943: 
  944:                 stcpy0 (&partition[i], data, j);	/* store new data */
  945: 
  946:                 return;
  947: 
  948:             /* end of set_sym section */
  949: 
  950:             
  951:             case dat:
  952: 
  953: 
  954:                 /* note: we assume EOL<DELIM<ASCII */
  955:                 data[0] = '0';
  956:                 data[1] = EOL;
  957:                 
  958:                 if ((i = alphptr[(int) key[0]])) {
  959: 
  960:                     data[2] = EOL;
  961:                     j = i + 1;
  962:                     k = 1;
  963:                     
  964:                     do {
  965: 
  966:                         while ((k1 = key[k] - partition[++j]) == 0) {	/* compare keys */
  967:                             
  968:                             if (key[k] == EOL) break;
  969:                             
  970:                             k++;
  971: 
  972:                         }
  973: 
  974:                         if (k1 == 0) {
  975:                             data[0] = '1';
  976:                         }
  977:                         else {
  978:                             
  979:                             if (partition[j] == DELIM && key[k] == EOL) {
  980:                             
  981:                                 data[1] = data[0];
  982:                                 data[0] = '1';
  983:                             
  984:                                 return;
  985:                             
  986:                             }
  987:                             
  988:                             if (k1 < 0 && k < 2) return;
  989: 
  990:                         }
  991:                         
  992:                         i += UNSIGN (partition[i]);	/* skip key */
  993:                         i += UNSIGN (partition[i]) + 1;		/* skip data */
  994:                         
  995:                         j = i;
  996:                         k = 0;
  997: 
  998:                     } while (i < PSIZE);
  999: 
 1000:                 }
 1001: 
 1002:                 return;
 1003: 
 1004: 
 1005: 
 1006:             /* end of $data section */
 1007: 
 1008: 
 1009:  
 1010: 
 1011:             case getinc:			/* increment by one and retrieve */
 1012: 
 1013: #ifdef DEBUG_SYM
 1014:                 
 1015:                 printf ("DEBUG GETINC: ");
 1016:                 printf ("[key] is [");
 1017: 
 1018:                 for (loop = 0; key[loop] != EOL; loop++) printf ("%c", (key[loop] == DELIM) ? '!' : key[loop]);
 1019: 
 1020:                 printf("]\r\n");
 1021: #endif
 1022: 
 1023: 
 1024:                 if ((i = alphptr[(int) key[0]])) {
 1025: 
 1026:                     j = i + 1;
 1027:                     k = 1;
 1028:                     
 1029:                     do {
 1030:                         
 1031:                         while (key[k] == partition[++j]) {	/* compare keys */
 1032:                     
 1033:                             if (key[k] == EOL) {
 1034: 
 1035:                                 i = UNSIGN (partition[++j]);
 1036:                                 stcpy0 (data, &partition[j + 1], i);
 1037:                                 
 1038:                                 data[i] = EOL;	/* data retrieved ... now increment */
 1039:                                 
 1040:                                 /****************increment by one*******************/
 1041:                                 if (i == 0) i++;	/* if data was empty  use EOL as dummy value */
 1042:                                 if (i > 1 && data[0] == '0') i++;	/* leading zero  use EOL as dummy value */
 1043:                                 
 1044:                                 k = 0;
 1045:                                 
 1046:                                 while (k < i) {
 1047: 
 1048:                                     if ((k1 = data[k++]) < '0' || k1 > '9') {	/* no positive integer */
 1049:                                         
 1050:                                         numlit (data);
 1051:                                         
 1052:                                         tmp1[0] = '1';
 1053:                                         tmp1[1] = EOL;
 1054:                                         
 1055:                                         add (data, tmp1);
 1056:                                         
 1057:                                         datal = stlen (data);
 1058:                                         
 1059:                                         i = j;
 1060:                                         
 1061:                                         nocompact = FALSE;	/* getinc needs compacted symtab */
 1062:                                         
 1063:                                         goto old0; 
 1064: 
 1065:                                     }
 1066: 
 1067:                                 }
 1068: 
 1069:                                 k1 = k--;	/* length of string */
 1070:                                 
 1071:                                 while ((partition[j + 1 + k] = ++data[k]) > '9') {
 1072: 
 1073:                                     partition[j + 1 + k] = '0';
 1074:                                     data[k--] = '0';
 1075:                                     
 1076:                                     if (k < 0) {
 1077: 
 1078:                                         k = k1;
 1079:                                         
 1080:                                         while (k >= 0) {
 1081:                                             data[k + 1] = data[k];
 1082:                                             k--;
 1083:                                         }
 1084: 
 1085:                                         data[0] = '1';
 1086:                                         s = &partition[--symlen] - 256;
 1087:                                         
 1088:                                         if (alphptr['%']) alphptr['%']--;
 1089: 
 1090:                                         for (k = 'A'; k <= key[0]; k++) {
 1091:                                             if (alphptr[k]) alphptr[k]--;
 1092:                                         }
 1093: 
 1094:                                         k = j - 1;
 1095:                                         j = symlen;
 1096:                                         
 1097:                                         stcpy0 (&partition[j], &partition[j + 1], k - j);
 1098:                                         
 1099:                                         partition[k] = (char) ++i;
 1100:                                         partition[++k] = '1';
 1101:                                         
 1102:                                         return;
 1103: 
 1104:                                     }
 1105: 
 1106:                                 }
 1107: 
 1108:                                 return;
 1109:                                 
 1110:                                 /************end increment by one*******************/
 1111:                             
 1112:                             }
 1113:                     
 1114:                             k++;
 1115: 
 1116:                         }
 1117: 
 1118:                         /** if (key[k]<partition[j]) break; **/
 1119:                         i += UNSIGN (partition[i]);	/* skip key */
 1120:                         i += UNSIGN (partition[i]) + 1;		/* skip data */
 1121: 
 1122:                         j = i;
 1123:                         k = 0;
 1124:                         
 1125:                     } while (i < PSIZE);
 1126:                 
 1127:                 }
 1128:                 
 1129:                 data[0] = EOL;
 1130:                 merr_raise (UNDEF);
 1131:                 
 1132:                 return;
 1133: 
 1134: 
 1135: 
 1136:             case fra_order:			/* next one please */
 1137: 
 1138: 
 1139:                 if (ordercnt < 0) goto zinv;
 1140: 
 1141:                 k1 = (j = stcpy (tmp1, key) - 1);
 1142:                 
 1143:                 while (tmp1[k1] != DELIM) {
 1144:                     if ((--k1) <= 0) goto unsubscr;
 1145:                 }
 1146: 
 1147:                 tmp1[++k1] = EOL;
 1148:                 
 1149:                 stcpy (tmp2, &key[k1]);
 1150:                 
 1151:                 if (ordercnt == 0) {
 1152:                 
 1153:                     stcpy (data, tmp2);
 1154: 
 1155:                     l_o_val[0] = EOL;
 1156:                     
 1157:                     return;
 1158: 
 1159:                 }
 1160: 
 1161:                 data[0] = EOL;
 1162:                 
 1163:                 if ((i = alphptr[(int) key[0]]) == 0) {
 1164: 
 1165:                     l_o_val[0] = EOL;
 1166: 
 1167:                     
 1168:                     return;
 1169: 
 1170:                 }
 1171: 
 1172:                 /***************************/
 1173:                 /* frequent special case: the key of which we search the next
 1174:                 * entry is defined ! */
 1175:                 if (tmp2[0] != EOL) {
 1176: 
 1177:                     if (tryfast && stcmp (key, &partition[tryfast + 1]) == 0) {
 1178:                         
 1179:                         j = tryfast;
 1180:                         j += UNSIGN (partition[j]);	/* skip key */
 1181:                         j += UNSIGN (partition[j]) + 1;		/* skip data */
 1182:                         
 1183:                         goto begorder;
 1184: 
 1185:                     }
 1186: 
 1187:                     k = 1;
 1188:                     j = i + 1;			/* first char always matches! */
 1189:                     
 1190:                     do {
 1191: 
 1192:                         while (key[k] == partition[++j]) {	/* compare keys */
 1193: 
 1194:                             if (key[k++] == EOL) {
 1195:                                 j = i;
 1196:                                 goto begorder;
 1197:                             }
 1198:                         
 1199:                         }
 1200:                         
 1201:                         i += UNSIGN (partition[i]);	/* skip key */
 1202:                         i += UNSIGN (partition[i]) + 1;		/* skip data */
 1203:                         
 1204:                         k = 0;
 1205:                         j = i;
 1206: 
 1207:                     } while (i < PSIZE);
 1208: 
 1209:                 }
 1210: 
 1211:                 /* the key was not defined */
 1212:                 /***************************/
 1213:                 j = alphptr[(int) key[0]];
 1214: 
 1215: begorder:
 1216: 
 1217:                 do {
 1218:                     
 1219:                     if (key[0] != partition[j + 1]) {
 1220:                     
 1221:                         l_o_val[0] = EOL;
 1222:                         data[0] = EOL;
 1223:                         
 1224:                         return;
 1225:                     
 1226:                     }
 1227: 
 1228:                     stcpy0 (data, &partition[j + 1], k1);
 1229:                     
 1230:                     data[k1] = EOL;
 1231: 
 1232:                     if (stcmp (tmp1, data) == 0) {
 1233:                         
 1234:                         stcpy (data, &partition[j + 1 + k1]);	/* index on same level */
 1235:                         
 1236:                         k = 0;
 1237:                         
 1238:                         while (data[k] != EOL && data[k] != DELIM) k++;
 1239: 
 1240:                         data[k] = EOL;
 1241:                         
 1242:                         if (collate (tmp2, data)) {
 1243: 
 1244:                             if (--ordercnt <= 0) {
 1245: 
 1246:                                 tryfast = j;
 1247:                                 
 1248:                                 /* save data value for inspection with $V(110) */
 1249:                                 j += UNSIGN (partition[j]);	/* skip key */
 1250:                                 k = UNSIGN (partition[j++]);
 1251:                                 stcpy0 (l_o_val, &partition[j], k);
 1252:                                 
 1253:                                 l_o_val[k] = EOL;
 1254:                                 
 1255:                                 return;
 1256: 
 1257:                             }
 1258: 
 1259:                             ordercounter++;
 1260: 
 1261:                         }
 1262: 
 1263:                     }
 1264:                     
 1265:                     j += UNSIGN (partition[j]);	/* skip key */
 1266:                     j += UNSIGN (partition[j]) + 1;	/* skip data */
 1267: 
 1268:                 } while (j < PSIZE);
 1269: 
 1270:                 data[0] = EOL;
 1271:                 tryfast = 0;
 1272:                 l_o_val[0] = EOL;
 1273:                 
 1274:                 return;
 1275: 
 1276:             /* end of $order section */
 1277: 
 1278: 
 1279:         case kill_all:
 1280: 
 1281: genocid:
 1282: 
 1283: 
 1284: 
 1285: 
 1286:             /* Old genocide routine */
 1287:             alphptr['%'] = 0;
 1288:             
 1289:             for (i = 'A'; i <= 'z'; alphptr[i++] = 0) ;
 1290:             
 1291:             symlen = PSIZE;
 1292:             s = &partition[symlen] - 256;
 1293:             tryfast = 0;
 1294: 
 1295:             ssvn_system_update ();
 1296:             ssvn_job_update ();
 1297:             ssvn_routine_update ();
 1298: 
 1299: #if defined(HAVE_MWAPI_MOTIF)
 1300:             ssvn_display_update ();
 1301: #endif
 1302: 
 1303:             const_restore ();
 1304:             
 1305:             return;
 1306: 
 1307: 
 1308: 
 1309: 
 1310:         case kill_sym:			/* kill them dirty bloody variables */
 1311: 
 1312: 
 1313:             /* Old Kill Routine */ 
 1314: 
 1315:             if ((i = alphptr[(int) key[0]]) == 0) return;			/* damn - nothing to kill */
 1316:             
 1317:             kill_from = 0;
 1318:             
 1319:             while (i < PSIZE) {
 1320: 
 1321:                 j = i;
 1322:                 k = 0;
 1323:                 
 1324:                 while ((k1 = key[k]) == partition[++j]) {	/* compare keys */
 1325:                     
 1326:                     if (k1 == EOL) break;
 1327:                 
 1328:                     k++;
 1329: 
 1330:                 }
 1331: 
 1332:                 if (k1 == EOL && (partition[j] == DELIM || partition[j] == EOL)) {
 1333:                     
 1334:                     if (kill_from == 0) kill_from = i;
 1335: 
 1336:                 } 
 1337:                 else {
 1338:                     if (kill_from) break;
 1339:                 }
 1340: 
 1341:                 i += UNSIGN (partition[i]);	/* skip key */
 1342:                 i += UNSIGN (partition[i]) + 1;	/* skip data */
 1343:             
 1344:             }
 1345: 
 1346: k_entry:			/* entry from killone section */
 1347: 
 1348: 
 1349:             if (kill_from) {
 1350: 
 1351:                 j = i - kill_from;
 1352:                 symlen += j;
 1353:                 s = &partition[symlen] - 256;
 1354:                 
 1355:                 for (k = 36; k < key[0]; k++) {
 1356:                     if (alphptr[k]) alphptr[k] += j;
 1357:                 }
 1358: 
 1359:                 if (alphptr[k] == kill_from) {
 1360: 
 1361:                     alphptr[k] = i;
 1362:                     
 1363:                     if (partition[i + 1] != key[0]) alphptr[k] = 0;
 1364: 
 1365:                 } 
 1366:                 else {
 1367:                     alphptr[k] += j;
 1368:                 }
 1369: 
 1370:                 /*         j=i-j; while(i>symlen) partition[--i]=partition[--j];  */
 1371:                 stcpy1 (&partition[i - 1], &partition[i - j - 1], i - symlen);
 1372: 
 1373:             }
 1374: 
 1375:             tryfast = 0;
 1376:             
 1377:             return;
 1378: 
 1379: 
 1380:         /* end of kill_sym section */
 1381: 
 1382:         case killone:			/* kill one variable, not descendants */
 1383: 
 1384: 
 1385:             if ((i = alphptr[(int) key[0]]) == 0) return;			/* nothing to kill */
 1386:             
 1387:             kill_from = 0;
 1388:             
 1389:             while (i < PSIZE) {
 1390: 
 1391:                 j = i;
 1392:                 k = 0;
 1393:                 
 1394:                 while ((k1 = key[k]) == partition[++j]) {	/* compare keys */
 1395:                     
 1396:                     if (k1 == EOL) break;
 1397: 
 1398:                     k++;
 1399: 
 1400:                 }
 1401: 
 1402:                 k = i;
 1403:                 i += UNSIGN (partition[i]);	/* skip key */
 1404:                 i += UNSIGN (partition[i]) + 1;	/* skip data */
 1405:                 
 1406:                 if (k1 == EOL) {
 1407: 
 1408:                     if (partition[j] == DELIM) return;		/* descendant */
 1409:                 
 1410:                     kill_from = k;
 1411:                     
 1412:                     goto k_entry; 
 1413:                 
 1414:                 }
 1415: 
 1416:             }
 1417: 
 1418:             tryfast = 0;
 1419:             
 1420:             return;
 1421: 
 1422:         
 1423:         /* end of killone section */
 1424: 
 1425:         case killexcl:			/* exclusive kill */
 1426: 
 1427: 
 1428:             i = symlen;
 1429: 
 1430:             while (i < PSIZE) {
 1431: 
 1432:                 tmp2[0] = SP;
 1433:                 kill_from = i;
 1434:                 
 1435:                 stcpy (tmp3, &partition[i + 1]);
 1436:                 stcpy (&tmp2[1], tmp3);
 1437:                 stcat (tmp2, " \201");
 1438:                 
 1439:                 i += UNSIGN (partition[i]);
 1440:                 i += UNSIGN (partition[i]) + 1;
 1441:                 
 1442:                 if (kill_ok (key, tmp2) == 0) continue;		/* don't kill */
 1443: 
 1444:                 while (i < PSIZE) {
 1445: 
 1446:                     j = i;
 1447:                     k = 0;
 1448:                     
 1449:                     while ((k1 = tmp3[k]) == partition[++j]) {	/* compare keys */
 1450:                         
 1451:                         if (k1 == EOL) break;
 1452:                         
 1453:                         k++;
 1454:                     
 1455:                     }
 1456:                     
 1457:                     if (k1 != EOL || (partition[j] != DELIM && partition[j] != EOL)) break;
 1458:                     
 1459:                     i += UNSIGN (partition[i]);	/* skip key */
 1460:                     i += UNSIGN (partition[i]) + 1;		/* skip data */
 1461: 
 1462:                 }
 1463: 
 1464:                 j = i - kill_from;
 1465:                 symlen += j;
 1466:                 s = &partition[symlen] - 256;
 1467:                 
 1468:                 for (k = 36; k < tmp3[0]; k++) {
 1469:                     if (alphptr[k]) alphptr[k] += j;
 1470:                 }
 1471: 
 1472:                 if (alphptr[k] == kill_from) {
 1473:                     
 1474:                     alphptr[k] = i;
 1475:                     
 1476:                     if (partition[i + 1] != tmp3[0]) alphptr[k] = 0;
 1477: 
 1478:                 } 
 1479:                 else {
 1480:                     alphptr[k] += j;
 1481:                 }
 1482: 
 1483:                 stcpy1 (&partition[i - 1], &partition[i - j - 1], i - symlen);
 1484:                 
 1485:                 i = kill_from + j;
 1486:             
 1487:             }
 1488:             
 1489:             tryfast = 0;
 1490:             
 1491:             return;
 1492: 
 1493:             /* end of killexcl section */
 1494: 
 1495:         case fra_query:			/* next entry */
 1496:         case bigquery:
 1497: 
 1498: 
 1499:             if (ordercnt == 0) {
 1500: 
 1501:                 l_o_val[0] = EOL;
 1502:                 
 1503:                 zname (data, key + stlen (i_with));
 1504: 		
 1505:                 return;
 1506: 
 1507:             }
 1508: 
 1509:             /***************************/
 1510:             /* frequent special case: the key which we search for is the next
 1511:             * entry */
 1512: 
 1513:             if ((i = alphptr[(int) key[0]])) {
 1514: 
 1515:                 if (stcmp (key, &partition[tryfast + 1]) == 0) {
 1516:                     i = tryfast;
 1517:                 }
 1518:                 else {
 1519:                     
 1520:                     j = i;
 1521:                 
 1522:                     do {
 1523: 
 1524:                         if (stcmp (key, &partition[j + 1]) == 0) {
 1525:                             i = j;
 1526:                             break;
 1527:                         }
 1528:                         
 1529:                         j += UNSIGN (partition[j]);		/* skip key */
 1530:                         j += UNSIGN (partition[j]) + 1;	/* skip data */
 1531: 
 1532:                     } while (j < PSIZE);
 1533:                 
 1534:                 }
 1535:             } 
 1536:             else {
 1537:                 i = symlen;			/* no previous entry */
 1538:             }
 1539:             /***************************/
 1540: 
 1541: 
 1542:             /* check whether the key has subscripts or not */
 1543:             k1 = 0;
 1544:             k = 1;
 1545: 
 1546:             while (key[k] != EOL) {
 1547:                 
 1548:                 if (key[k++] == DELIM) {
 1549:                     k1 = k;
 1550:                     break;
 1551:                 }
 1552: 
 1553:             }
 1554: 
 1555:             while (i < PSIZE) {
 1556: 
 1557:                 j = i;
 1558:                 k = 0;
 1559:                 
 1560:                 while (key[k] == partition[++j]) {	/* compare keys */
 1561:                     
 1562:                     if (key[k] == EOL) break;
 1563:                     
 1564:                     k++;
 1565:                 
 1566:                 }
 1567: 
 1568:                 if (key[k] == EOL) {
 1569: 
 1570:                     if (partition[j] == EOL) {
 1571:                         i += UNSIGN (partition[i]);
 1572:                         i += UNSIGN (partition[i]) + 1;
 1573:                     }
 1574: 
 1575:                     break;
 1576: 
 1577:                 }
 1578: 
 1579:                 if (k < k1 || k1 == 0) {
 1580:                 
 1581:                     if (key[k] < partition[j]) break;
 1582:                 
 1583:                 } 
 1584:                 else {
 1585:                     long    m, n, o, ch;
 1586:                     
 1587:                     /* get complete subscripts */
 1588:                     n = k;
 1589:                     
 1590:                     while (key[--n] != DELIM) ;
 1591:                     
 1592:                     n++;
 1593:                     m = j + n - k;
 1594:                     o = 0;
 1595:                     
 1596:                     while ((ch = tmp2[o++] = key[n++]) != EOL && ch != DELIM) ;
 1597:                     
 1598:                     if (ch == DELIM) tmp2[--o] = EOL;
 1599: 
 1600:                     o = 0;
 1601:  
 1602:                     while ((ch = tmp3[o++] = partition[m++]) != EOL && ch != DELIM) ;
 1603:  
 1604:                     if (ch == DELIM) tmp3[--o] = EOL;
 1605: 
 1606:                     if (collate (tmp2, tmp3)) break;
 1607: 
 1608:                 }
 1609: 
 1610:                 i += UNSIGN (partition[i]);	/* skip key */
 1611:                 i += UNSIGN (partition[i]) + 1;	/* skip data */
 1612: 
 1613:             }
 1614: 
 1615:             /* multiple backward query */
 1616:             if (ordercnt < 0) {
 1617: 
 1618:                 j = symlen;
 1619:                 k = ordercnt - 1;
 1620:                 
 1621:                 while (j < i) {		/* count entries */
 1622:                     
 1623:                     j += UNSIGN (partition[j]);	/* skip key */
 1624:                     j += UNSIGN (partition[j]) + 1;		/* skip data */
 1625: 
 1626:                     k++;
 1627: 
 1628:                 }
 1629: 
 1630:                 if (k < 0) {
 1631: 
 1632:                     data[0] = EOL;
 1633:                     l_o_val[0] = EOL;
 1634:                     
 1635:                     return;
 1636: 
 1637:                 }
 1638: 
 1639:                 i = symlen;
 1640:                 
 1641:                 while (--k >= 0) {
 1642:                     
 1643:                     i += UNSIGN (partition[i]);	/* skip key */
 1644:                     i += UNSIGN (partition[i]) + 1;		/* skip data */
 1645: 
 1646:                 }
 1647: 
 1648:             }
 1649:             /* end: multiple backward query */
 1650: 
 1651:             while (--ordercnt > 0) {	/* multiple forward $query */
 1652:                 
 1653:                 if (i >= PSIZE) break;
 1654: 
 1655:                 i += UNSIGN (partition[i]);	/* skip key */
 1656:                 i += UNSIGN (partition[i]) + 1;	/* skip data */
 1657: 
 1658:             }
 1659: 
 1660:             /* now 'i' is pointer to 'next' entry */
 1661:             tryfast = i;
 1662: 
 1663:             /* save data value for inspection with $V(110) */
 1664:             j = i;
 1665: 
 1666:             j += UNSIGN (partition[j]);
 1667:             k = UNSIGN (partition[j]);
 1668: 
 1669:             stcpy0 (l_o_val, &partition[j + 1], k);
 1670:             l_o_val[k] = EOL;
 1671:             
 1672:             keyl = i;
 1673:             keyl += UNSIGN (partition[i++]) - 2;
 1674: 
 1675:             /* action==bigquery may return a result in a different lvn */
 1676:             /* which is illegal with $query() */
 1677:             if (action == fra_query) {
 1678: 
 1679:                 k = 0; /* is result same lvn? */
 1680:                 
 1681:                 while (partition[i+k] == key[k]) {
 1682:                     
 1683:                     if (key[k] == DELIM) break;
 1684:                 
 1685:                     k++;
 1686: 
 1687:                 }
 1688: 
 1689:                 if (partition[i+k] != DELIM) i = keyl + 1; /* discard result! */
 1690:             
 1691:             }
 1692:             
 1693:             if (i <= keyl) {
 1694:                 zname (data, &partition[i + stlen (i_with)]);		
 1695:             }
 1696:             else {
 1697:                 data[0] = EOL;
 1698:             }
 1699:             
 1700:             return;
 1701: /* end of $query section */
 1702: 
 1703: zinv:				/* previous one please */
 1704:             
 1705:             data[0] = EOL;
 1706:             l_o_val[0] = EOL;
 1707:             
 1708:             k1 = (j = stcpy (tmp1, key) - 1);
 1709:             
 1710:             while (tmp1[k1] != DELIM) {
 1711:                 
 1712:                 if ((--k1) <= 0) {
 1713:                     merr_raise (NEXTER);
 1714:                     return;
 1715:                 }
 1716: 
 1717:             }
 1718: 
 1719:             tmp1[++k1] = EOL;
 1720:             
 1721:             stcpy (tmp2, &key[k1]);
 1722:             
 1723:             if (tmp2[0] == EOL) {
 1724:                 
 1725:                 tmp2[0] = DEL;
 1726:                 tmp2[1] = DEL;
 1727:                 tmp2[2] = EOL;
 1728: 
 1729:             }
 1730: 
 1731:             k = (int) (key[0]);
 1732:             
 1733:             if (alphptr[k] == 0) return;
 1734:             
 1735:             j = alphptr[k];
 1736:             
 1737:             do {
 1738: 
 1739:                 if (key[0] != partition[j + 1]) goto zinvend;
 1740: 
 1741:                 stcpy0 (tmp3, &partition[j + 1], k1);
 1742:                 
 1743:                 tmp3[k1] = EOL;
 1744: 
 1745:                 if (stcmp (tmp1, tmp3) == 0) {
 1746:                     
 1747:                     stcpy (tmp3, &partition[j + 1 + k1]);	/* index on same level */
 1748:                     
 1749:                     k = 0;
 1750:                     
 1751:                     while (tmp3[k] != EOL && tmp3[k] != DELIM) k++;
 1752: 
 1753:                     tmp3[k] = EOL;
 1754:                     
 1755:                     if (collate (tmp3, tmp2) == FALSE) goto zinvend;
 1756:                     
 1757:                     stcpy (data, tmp3);
 1758:                     
 1759:                     /* save data value for inspection with $V(110) */
 1760:                     i = j;
 1761:                     
 1762:                     i += UNSIGN (partition[i]);
 1763:                     k = UNSIGN (partition[i]);
 1764:                     
 1765:                     stcpy0 (l_o_val, &partition[i + 1], k);
 1766:                     
 1767:                     l_o_val[k] = EOL;
 1768: 
 1769:                 }
 1770: 
 1771:                 j += UNSIGN (partition[j]);	/* skip key */
 1772:                 j += UNSIGN (partition[j]) + 1;	/* skip data */
 1773: 
 1774:             } while (j < PSIZE);
 1775: 
 1776: zinvend:
 1777: 
 1778:             if (data[0] == EOL) return;
 1779: 
 1780:             ordercounter++;
 1781:             
 1782:             if (++ordercnt >= 0) return;
 1783:             
 1784:             stcpy (&key[k1], data);
 1785:             
 1786:             goto zinv;
 1787: 
 1788: 
 1789: 
 1790: 
 1791: 
 1792:         /* end of $zinverse section */
 1793:         
 1794: 
 1795:         case new_sym:			/* new one symbol */
 1796: 
 1797:             if (key[0] == '$') {		/* $svn: save current value on new stack */
 1798: 
 1799: 
 1800: 
 1801:                 if (newptr > newlimit && getnewmore ()) return;
 1802: 
 1803:                 if ((key[1] | 0140) == 't') {	/* NEW $TEST */
 1804:                     
 1805:                     *newptr++ = test;
 1806:                     *newptr++ = EOL;
 1807:                     *newptr++ = 1;
 1808:                     
 1809:                     k1 = stcpy (newptr, "$t\201");
 1810:                     
 1811:                     newptr += k1;
 1812:                     *newptr++ = EOL;
 1813:                     *newptr++ = k1;
 1814:                     *newptr++ = set_sym;
 1815:                     
 1816:                     //if (mcmnd != ZNEW) test = FALSE;
 1817: 
 1818:                     return;
 1819: 
 1820:                 }
 1821: 
 1822:                 if ((key[1] | 0140) == 'j') {	/* NEW $JOB */
 1823: 
 1824:                     *newptr++ = pid / 256;
 1825:                     *newptr++ = pid % 256;
 1826:                     *newptr++ = EOL;
 1827:                     *newptr++ = 2;
 1828:                     
 1829:                     k1 = stcpy (newptr, "$j\201");
 1830:                     
 1831:                     newptr += k1;
 1832:                     *newptr++ = EOL;
 1833:                     *newptr++ = k1;
 1834:                     *newptr++ = set_sym;
 1835:                     
 1836:                     return;
 1837: 
 1838:                 }
 1839: 
 1840:                 if (((key[1] | 0140) == 'z') &&	((key[2] | 0140) == 'i')) { /* NEW $ZINRPT */
 1841:                     
 1842:                     *newptr++ = breakon;
 1843:                     *newptr++ = EOL;
 1844:                     *newptr++ = 1;
 1845:                     
 1846:                     k1 = stcpy (newptr, "$zi\201");
 1847:                     
 1848:                     newptr += k1;
 1849:                     *newptr++ = EOL;
 1850:                     *newptr++ = k1;
 1851:                     *newptr++ = set_sym;
 1852:                     
 1853:                     return;
 1854:                 
 1855:                 }
 1856: 
 1857: 
 1858:                 /* NEW $ETRAP added 10 Oct 2020, JPW */
 1859:                 if (((key[1] | 0140) == 'e') && ((key[2] | 0140) == 't')) { /* NEW $ETRAP */
 1860:                     
 1861:                     j = stcpy (newptr, etrap);
 1862: 
 1863:                     newptr += j;
 1864:                     *newptr++ = EOL;
 1865:                     *newptr++ = j;
 1866: 
 1867:                     k1 = stcpy (newptr, "$et\201");
 1868: 
 1869:                     newptr += k1;
 1870:                     *newptr++ = EOL;
 1871:                     *newptr++ = k1;
 1872:                     *newptr++ = set_sym;
 1873:                                        
 1874:                     return;
 1875:                 
 1876:                 }
 1877: 
 1878:                 /* NEW $ESTACK added 12 Oct 2020, JPW */
 1879:                 if (((key[1] | 0140) == 'e') && ((key[2] | 0140) == 's')) { /* NEW $ESTACK */
 1880:                     
 1881:                     char esbuf[256];
 1882: 
 1883:                     snprintf (esbuf, 255, "%d\201", estack);
 1884: 
 1885:                     j = stcpy (newptr, esbuf);
 1886: 
 1887:                     newptr += j;
 1888:                     *newptr++ = EOL;
 1889:                     *newptr++ = j;
 1890: 
 1891:                     k1 = stcpy (newptr, "$es\201");
 1892: 
 1893:                     newptr += k1;
 1894:                     *newptr++ = EOL;
 1895:                     *newptr++ = k1;
 1896:                     *newptr++ = set_sym;
 1897: 
 1898:                     estack = 0;
 1899:                                        
 1900:                     return;
 1901:                 
 1902:                 }
 1903: 
 1904:                 j = stcpy (newptr, zref);	/* NEW $ZREFERENCE */
 1905:                 
 1906:                 newptr += j;
 1907:                 *newptr++ = EOL;
 1908:                 *newptr++ = j;
 1909:                 
 1910:                 k1 = stcpy (newptr, "$zr\201");
 1911:                 
 1912:                 newptr += k1;
 1913:                 *newptr++ = EOL;
 1914:                 *newptr++ = nakoffs;
 1915:                 
 1916:                 k1++;
 1917:                 
 1918:                 *newptr++ = k1;
 1919:                 *newptr++ = set_sym;
 1920:                 
 1921:                 if (mcmnd != ZNEW) zref[0] = EOL;
 1922: 
 1923:                 return;
 1924: 
 1925: 
 1926:             }
 1927: 
 1928: 
 1929: 
 1930:             if ((i = alphptr[(int) key[0]])) {	/* is there something to be saved?/killed */
 1931:                 
 1932:                 /* always FALSE with special variables    */ 
 1933:                 kill_from = 0;
 1934:                 
 1935:                 while (i < PSIZE) {
 1936:                     
 1937:                     j = i;
 1938:                     k = 0;
 1939:                     
 1940:                     while ((k1 = key[k]) == partition[++j]) {	/* compare keys */
 1941:                         
 1942:                         if (k1 == EOL) break;
 1943:                     
 1944:                         k++;
 1945: 
 1946:                     }
 1947: 
 1948:                     if (k1 == EOL && (partition[j] == DELIM || partition[j] == EOL)) {
 1949:                         
 1950:                         if (kill_from == 0) kill_from = i;
 1951: 
 1952:                     } 
 1953:                     else {
 1954:                         if (kill_from) break;
 1955:                     }
 1956: 
 1957:                     if (kill_from) {	/* save current values on new stack */
 1958:                         
 1959:                         j = UNSIGN (partition[i]);                        
 1960:                         k = i + 1;
 1961:                         k1 = j;
 1962:                         i += j;
 1963:                         j = UNSIGN (partition[i]);
 1964: 
 1965:                         if (newptr > newlimit && getnewmore ()) return;
 1966:                         
 1967: #ifdef DEBUG_SYM
 1968: 
 1969:                         start = newptr;
 1970: 
 1971: #endif
 1972: 
 1973:                         stcpy0 (newptr, &partition[i + 1], j);
 1974: 
 1975:                         newptr += j;
 1976:                         *newptr++ = EOL;
 1977:                         *newptr++ = j;
 1978:                         
 1979:                         i += (j + 1);
 1980:                         
 1981:                         stcpy0 (newptr, &partition[k], k1);
 1982:                         
 1983:                         newptr += k1;
 1984:                         *newptr++ = EOL;
 1985:                         *newptr++ = k1;
 1986:                         *newptr++ = set_sym;
 1987:                         
 1988: #ifdef DEBUG_SYM
 1989: 
 1990:                         printf ("SAVING [newptr] newptr became [");
 1991: 
 1992:                         while (start < newptr) { 
 1993:                         
 1994:                             printf ("%c(%d)", (*start==EOL) ? ('!') : *start, *start); 
 1995:                         
 1996:                             start++; 
 1997:                         
 1998:                         }
 1999:                         
 2000:                         printf("{%d}]\r\n", *(newptr - 1));
 2001: 
 2002: #endif
 2003:                     
 2004:                     } 
 2005:                     else {
 2006:                         
 2007:                         i += UNSIGN (partition[i]);		/* skip key */
 2008:                         i += UNSIGN (partition[i]) + 1;	/* skip data */
 2009: 
 2010:                     }
 2011: 
 2012:                 }
 2013: 
 2014:                 if (kill_from && mcmnd != ZNEW) {
 2015: 
 2016:                     j = i - kill_from;
 2017:                     symlen += j;
 2018:                     s = &partition[symlen] - 256;
 2019:                     
 2020:                     for (k = 36; k < key[0]; k++) {                    
 2021:                         if (alphptr[k]) alphptr[k] += j;                    
 2022:                     }
 2023: 
 2024:                     if (alphptr[k] == kill_from) {
 2025: 
 2026:                         alphptr[k] = i;
 2027:                         
 2028:                         if (partition[i + 1] != key[0]) alphptr[k] = 0;
 2029:                     
 2030:                     } 
 2031:                     else {
 2032:                         alphptr[k] += j;
 2033:                     }
 2034: 
 2035:                     stcpy1 (&partition[i - 1], &partition[i - j - 1], i - symlen);
 2036: 
 2037:                 }
 2038: 
 2039:                 tryfast = 0;
 2040:             
 2041:             }
 2042: 
 2043:             if (newptr > newlimit && getnewmore ()) return;
 2044:             
 2045: #ifdef DEBUG_SYM
 2046:             start = newptr;
 2047: #endif
 2048: 
 2049:             j = stcpy (newptr, key);
 2050: 
 2051:             newptr += j;
 2052:             *newptr++ = EOL;
 2053:             *newptr++ = j;
 2054:             *newptr++ = kill_sym;
 2055:             
 2056: #ifdef DEBUG_SYM
 2057: 
 2058:             printf ("KILLING [newptr] newptr became [");
 2059:             
 2060:             while (start < newptr) {                 
 2061:                 printf ("%c(%d)", (*start == EOL) ? ('!') : *start,*start ); 
 2062:                 
 2063:                 start++; 
 2064: 
 2065:             }
 2066: 
 2067:             printf ("{%d}]\r\n", *(newptr - 1));
 2068: 
 2069: #endif
 2070: 
 2071:             return;
 2072: 
 2073:         /* end of new_sym section */
 2074:         
 2075: 
 2076:         case new_all:			/* new all symbols */
 2077: 
 2078: 
 2079: 
 2080:             i = symlen;
 2081:             
 2082:             while (i < PSIZE) {
 2083: 
 2084:                 j = UNSIGN (partition[i]);
 2085:                 k = i + 1;
 2086:                 k1 = j;
 2087:                 i += j;
 2088:                 j = UNSIGN (partition[i]);
 2089:                 
 2090:                 if (newptr > newlimit && getnewmore ()) return;
 2091: 
 2092:                 stcpy0 (newptr, &partition[i + 1], j);
 2093:                 
 2094:                 newptr += j;
 2095:                 *newptr++ = EOL;
 2096:                 *newptr++ = j;
 2097:                 i += (j + 1);
 2098:                 
 2099:                 stcpy0 (newptr, &partition[k], k1);
 2100:                 
 2101:                 newptr += k1;
 2102:                 *newptr++ = EOL;
 2103:                 *newptr++ = k1;
 2104:                 *newptr++ = set_sym;
 2105: 
 2106:             }
 2107:             
 2108:             *newptr++ = kill_all;
 2109:             
 2110:             if (mcmnd == ZNEW) return;
 2111:             
 2112:             goto genocid;			/* ... and now kill them all */
 2113: 
 2114:         /* end of new_all section */
 2115: 
 2116: 
 2117:         case newexcl:			/* new all except specified */
 2118: 
 2119: 
 2120: 
 2121:             i = symlen;
 2122: 
 2123:             while (i < PSIZE) {
 2124: 
 2125:                 tmp2[0] = SP;
 2126:                 kill_from = i;
 2127:                 
 2128:                 stcpy (tmp3, &partition[i + 1]);
 2129:                 stcpy (&tmp2[1], tmp3);
 2130:                 stcat (tmp2, " \201");
 2131:                 
 2132:                 if (kill_ok (key, tmp2) == 0) {	/* don't new */
 2133: 
 2134:                     i += UNSIGN (partition[i]);
 2135:                     i += UNSIGN (partition[i]) + 1;
 2136:                 
 2137:                     continue;
 2138:                 
 2139:                 }
 2140:                 
 2141:                 j = UNSIGN (partition[i]);
 2142:                 k = i + 1;
 2143:                 k1 = j;
 2144:                 i += j;
 2145:                 j = UNSIGN (partition[i]);
 2146:                 
 2147:                 if (newptr > newlimit && getnewmore ()) return;
 2148: 
 2149:                 stcpy0 (newptr, &partition[i + 1], j);
 2150:                 
 2151:                 newptr += j;
 2152:                 *newptr++ = EOL;
 2153:                 *newptr++ = j;
 2154:                 i += (j + 1);
 2155:                 
 2156:                 stcpy0 (newptr, &partition[k], k1);
 2157:                 
 2158:                 newptr += k1;
 2159:                 *newptr++ = EOL;
 2160:                 *newptr++ = k1;
 2161:                 *newptr++ = set_sym;
 2162: 
 2163:                 while (i < PSIZE) {
 2164:                     
 2165:                     j = i;
 2166:                     k = 0;
 2167:                     
 2168:                     while ((k1 = tmp3[k]) == partition[++j]) {	/* compare keys */
 2169:                         
 2170:                         if (k1 == EOL) break;
 2171:                     
 2172:                         k++;
 2173: 
 2174:                     }
 2175: 
 2176:                     if (k1 != EOL || (partition[j] != DELIM && partition[j] != EOL)) break;
 2177: 
 2178:                     j = UNSIGN (partition[i]);
 2179:                     k = i + 1;
 2180:                     k1 = j;
 2181:                     i += j;
 2182:                     j = UNSIGN (partition[i]);
 2183: 
 2184:                     if (newptr > newlimit && getnewmore ()) return;
 2185: 
 2186:                     stcpy0 (newptr, &partition[i + 1], j);
 2187:                     
 2188:                     newptr += j;
 2189:                     *newptr++ = EOL;
 2190:                     *newptr++ = j;
 2191:                     i += (j + 1);
 2192:                     
 2193:                     stcpy0 (newptr, &partition[k], k1);
 2194:                     
 2195:                     newptr += k1;
 2196:                     *newptr++ = EOL;
 2197:                     *newptr++ = k1;
 2198:                     *newptr++ = set_sym;
 2199: 
 2200:                 }
 2201:                 
 2202:                 if (mcmnd == ZNEW) continue;
 2203: 
 2204:                 j = i - kill_from;
 2205:                 symlen += j;
 2206:                 s = &partition[symlen] - 256;
 2207: 
 2208:                 for (k = 36; k < tmp3[0]; k++) {
 2209:                     
 2210:                     if (alphptr[k]) alphptr[k] += j;
 2211: 
 2212:                 }
 2213: 
 2214:                 if (alphptr[k] == kill_from) {
 2215:                     
 2216:                     alphptr[k] = i;
 2217:                     
 2218:                     if (partition[i + 1] != tmp3[0]) alphptr[k] = 0;
 2219: 
 2220:                 } 
 2221:                 else {
 2222:                     alphptr[k] += j;
 2223:                 }
 2224: 
 2225:                 stcpy1 (&partition[i - 1], &partition[i - j - 1], i - symlen);
 2226:                 
 2227:                 i = kill_from + j;
 2228:             
 2229:             }
 2230:             
 2231:             tryfast = 0;
 2232:             
 2233:             if (newptr > newlimit && getnewmore ()) return;
 2234: 
 2235:             j = stcpy (newptr, key);
 2236:             
 2237:             newptr += (j + 1);
 2238:             *newptr++ = j;
 2239:             *newptr++ = killexcl;
 2240:             
 2241:             return;
 2242: 
 2243: 
 2244:         /* end of newexcl section */
 2245: 
 2246:         
 2247:         case m_alias:			/* define an alias of a variable */
 2248: 
 2249: 
 2250:             /* process stuff */
 2251:             if (stcmp (key, data) == 0) return;			/* sorry, that's no alias */
 2252:             
 2253:             if (data[0] == EOL) {		/* delete an alias from the table */
 2254:                 
 2255:                 if (aliases) {		/* there are aliases */
 2256: 
 2257:                     i = 0;
 2258:                     
 2259:                     while (i < aliases) {
 2260: 
 2261:                         k = i;
 2262:                         k1 = i + UNSIGN (ali[i]) + 1;
 2263:                         j = 0;		/* is current reference an alias ??? */
 2264:                         
 2265:                         while (ali[++i] == key[j]) {
 2266:                             
 2267:                             if (ali[i] == EOL) break;
 2268: 
 2269:                             j++;
 2270: 
 2271:                         }
 2272: 
 2273:                         /* yes, it is, so resolve it now! */
 2274:                         if (ali[i] == EOL && key[j] == EOL) {
 2275: 
 2276:                             if (aliases > k1) stcpy0 (&ali[k], &ali[k1], aliases - k1);
 2277: 
 2278:                             aliases -= (k1 - k);
 2279:                             
 2280:                             return;
 2281: 
 2282:                         }
 2283: 
 2284:                         i = k1;
 2285: 
 2286:                     }
 2287: 
 2288:                 }
 2289: 
 2290:                 return;
 2291: 
 2292:             }
 2293: 
 2294:             /* new entry to alias table. there is no check agains duplicate entries */
 2295:             i = stlen (key);
 2296:             j = stlen (data);
 2297:             
 2298:             ali[aliases++] = (char) (i + j + 2);	/* byte for fast skipping */            
 2299:             
 2300:             stcpy (&ali[aliases], key);            
 2301:             aliases += (i + 1);
 2302:             
 2303:             stcpy (&ali[aliases], data);
 2304:             aliases += (j + 1);
 2305: 
 2306:             /* write note to unmake the alias */
 2307:             j = stcpy (newptr, key);
 2308:             newptr += (j + 1);
 2309:             *newptr++ = j;
 2310:             *newptr++ = m_alias;
 2311: 
 2312:             return;
 2313: 
 2314:         case zdata:			/* nonstandard data function */
 2315: 
 2316: 
 2317:             
 2318:             {
 2319:                 long counties[128];
 2320:                 int icnt, icnt0;
 2321: 
 2322:                 i = 0;
 2323: 
 2324:                 while (i < 128) counties[i++] = 0L;	/* init count;  */
 2325:                 
 2326:                 /* note: we assume EOL<DELIM<ASCII */
 2327:                 
 2328:                 icnt = 0;
 2329:                 i = 0;
 2330:                 
 2331:                 while ((j = key[i++]) != EOL) {
 2332:                     if (j == DELIM) {
 2333:                         icnt++;
 2334:                     }
 2335:                 }
 2336: 
 2337:                 if ((i = alphptr[(int) key[0]])) {
 2338: 
 2339:                     data[2] = EOL;
 2340:                     j = i + 1;
 2341:                     k = 1;
 2342:                     
 2343:                     do {
 2344: 
 2345:                         icnt0 = j + 1;
 2346:                         
 2347:                         while ((k1 = key[k] - partition[++j]) == 0) {	/* compare keys */
 2348:                             
 2349:                             if (key[k] == EOL) break;
 2350: 
 2351:                             k++;
 2352: 
 2353:                         }                        
 2354: 
 2355:                         if (k1 == 0) {
 2356:                             counties[0] = 1;
 2357:                         }
 2358:                         else {
 2359: 
 2360:                             if (partition[j] == DELIM && key[k] == EOL) {
 2361:                                 
 2362:                                 int ch;
 2363: 
 2364:                                 j = icnt0;
 2365:                                 icnt0 = 0;
 2366:                                 
 2367:                                 while ((ch = partition[j++]) != EOL) {
 2368:                                     
 2369:                                     if (ch == DELIM) {
 2370:                                         icnt0++;
 2371:                                     }
 2372: 
 2373:                                 }
 2374:                                 
 2375:                                 if (icnt0 <= icnt) break;
 2376: 
 2377:                                 counties[icnt0 - icnt]++;
 2378: 
 2379:                             }
 2380: 
 2381:                             /*                  if (k1<0 && k<2) break;     */
 2382:                         
 2383:                         }
 2384:                         
 2385:                         i += UNSIGN (partition[i]);		/* skip key */
 2386:                         i += UNSIGN (partition[i]) + 1;	/* skip data */
 2387:                         
 2388:                         j = i;
 2389:                         k = 0;
 2390: 
 2391:                     } while (i < PSIZE);
 2392: 
 2393:                 }
 2394: 
 2395:                 i = 128;
 2396:                 
 2397:                 while (counties[--i] == 0L) ;
 2398:                 
 2399:                 lintstr (data, counties[0]);
 2400:                 
 2401:                 j = 1;
 2402:                 tmp1[0] = ',';
 2403:                 
 2404:                 while (j <= i) {
 2405:                 
 2406:                     lintstr (&tmp1[1], counties[j++]);
 2407:                     stcat (data, tmp1);
 2408: 
 2409:                 }
 2410: 
 2411:                 return;
 2412:             }				/* end of $zdata section */
 2413: 
 2414:     }					/* end of action switch */
 2415: 
 2416: 
 2417: /* return next variable or array name - non standard */
 2418: unsubscr:
 2419: 
 2420:     if (standard) {
 2421:         merr_raise (NEXTER);
 2422:         return;
 2423:     }
 2424: 
 2425:     j = key[0];
 2426:     data[0] = EOL;
 2427: 
 2428:     while (alphptr[j] == 0) {
 2429:         if (++j >= DEL) return;
 2430:     }
 2431: 
 2432:     i = alphptr[j];
 2433:     
 2434:     while (i < PSIZE) {
 2435:         
 2436:         j = i;
 2437:         k = 0;
 2438:         
 2439:         while ((k1 = key[k] - partition[++j]) == 0) {	/* compare keys */
 2440:             
 2441:             if (key[k] == EOL) break;
 2442:         
 2443:             k++;
 2444:         
 2445:         }
 2446: 
 2447:         if (k1 < 0 && (partition[j] != DELIM || key[k] != EOL)) {
 2448:             
 2449:             j = i;
 2450:             i = 0;
 2451:             
 2452:             while ((data[i] = partition[++j]) != EOL) {
 2453:                 
 2454:                 if (data[i] == DELIM) {
 2455:                     data[i] = EOL;
 2456:                     break;
 2457:                 }
 2458:                 
 2459:                 i++;
 2460: 
 2461:             }
 2462: 
 2463:             return;
 2464: 
 2465:         }
 2466: 
 2467:         i += UNSIGN (partition[i]);	/* skip key */
 2468:         i += UNSIGN (partition[i]) + 1;	/* skip data */
 2469: 
 2470:     }
 2471: 
 2472:     return;
 2473: 
 2474: }					/* end of symtab() */
 2475: 
 2476: 
 2477: /******************************************************************************/
 2478:     /* if 't' follows 's' in MUMPS collating sequence a 1 is returned
 2479:      * otherwise 0
 2480:      */
 2481: 
 2482: short int collate (char *s, char *t)
 2483: {
 2484:     short dif;
 2485: 
 2486:     if (s[0] == EOL) return (t[0] != EOL);		/* the empty one is the leader! */
 2487:     if (t[0] == EOL) return FALSE;
 2488:     if ((dif = stcmp (t, s)) == 0) return FALSE;
 2489:     
 2490:     if (numeric (s)) {			/* then come numerics */
 2491:         
 2492:         if (numeric (t) == FALSE) return TRUE;
 2493:     
 2494:         return comp (s, t);
 2495: 
 2496:     }
 2497: 
 2498:     if (numeric (t)) return FALSE;
 2499: 
 2500:     return dif > 0;
 2501: 
 2502: }					/* end of collate() */
 2503: 
 2504: /******************************************************************************/
 2505: short int numeric (char *str)
 2506:     /**
 2507:      *  boolean function that tests
 2508:      *  whether str is a canonical
 2509:      *  numeric
 2510:      */
 2511: {
 2512:     register int ptr = 0, ch;
 2513:     register int point;
 2514: 
 2515: 
 2516:     
 2517:     if (str[0] == '-') {
 2518:         ptr = 1;
 2519:     }
 2520:     if (str[ptr] == EOL) {
 2521:         return FALSE;
 2522:     }
 2523:     if (str[ptr] == '0') return str[1] == EOL;		/* leading zero */
 2524:     
 2525:     point = FALSE;
 2526: 
 2527:     while ((ch = str[ptr++]) != EOL) {
 2528: 
 2529:         
 2530:         if (ch > '9') {
 2531:             return FALSE;
 2532:         }
 2533:         
 2534:         if (ch < '0') {
 2535: 
 2536:             if (ch != '.') return FALSE;
 2537:             if (point) return FALSE;		/* multiple points */
 2538:         
 2539:             point = TRUE;
 2540:         
 2541:         }
 2542: 
 2543:     }
 2544: 
 2545:     if (point) {
 2546: 
 2547:         if ((ch = str[ptr - 2]) == '0') return FALSE;		/* trailing zero */
 2548:         if (ch == '.') return FALSE;		/* trailing point */
 2549:     }
 2550:     return TRUE;
 2551: }					/* end of numeric() */
 2552: 
 2553: /******************************************************************************/
 2554:     /* s and t are strings representing */
 2555:     /* MUMPS numbers. comp returns t>s  */
 2556: 
 2557: short int comp (char *s, char *t)
 2558: {
 2559: 
 2560:     register int s1 = s[0], t1 = t[0], point = '.';
 2561: 
 2562: #if !defined(_AIX)    
 2563:     if (fp_mode) {
 2564:         double fp_s;
 2565:         double fp_t;
 2566: 
 2567:         stcnv_m2c (s);
 2568:         stcnv_m2c (t);
 2569: 
 2570:         fp_s = atof (s);
 2571:         fp_t = atof (t);
 2572: 
 2573:         return fp_t > fp_s;
 2574:     }
 2575: #endif    
 2576:     
 2577:     if (s1 != t1) {
 2578: 
 2579:         if (s1 == '-') return TRUE;		/* s<0<t */
 2580:         if (t1 == '-') return FALSE;		/* t<0<s */
 2581:         if (s1 == point && t1 == '0') return FALSE;		/* s>0; t==0 */
 2582:         if (t1 == point && s1 == '0') return TRUE;		/* t>0; s==0 */
 2583: 
 2584:     }
 2585: 
 2586:     if (t1 == '-') {
 2587:     
 2588:         char *a;
 2589: 
 2590:         a = &t[1];
 2591:         t = &s[1];
 2592:         s = a;
 2593: 
 2594:     }
 2595: 
 2596:     s1 = 0;
 2597:     
 2598:     while (s[s1] > point) s1++;				/* Note: EOL<'.' */
 2599:     
 2600:     t1 = 0;
 2601:     
 2602:     while (t[t1] > point) t1++;
 2603: 
 2604:     if (t1 > s1) return TRUE;
 2605:     if (t1 < s1) return FALSE;
 2606:     
 2607:     while (*t == *s) {
 2608: 
 2609:         if (*t == EOL) return FALSE;
 2610:     
 2611:         t++;
 2612:         s++;
 2613:     
 2614:     }
 2615: 
 2616:     if (*t > *s) return TRUE;
 2617:     
 2618:     return FALSE;
 2619: 
 2620: }					/* end of comp() */
 2621: /******************************************************************************/
 2622: void intstr (char *str, short integ)			/* converts integer to string */
 2623: {
 2624: 
 2625:     if (integ < 0) {
 2626:         integ = (-integ);
 2627:         *str++ = '-';
 2628:     }
 2629: 
 2630:     if (integ < 10) {
 2631: 
 2632:         *str++ = integ + '0';
 2633:         *str = EOL;
 2634:         
 2635:         return;
 2636: 
 2637:     } 
 2638:     else if (integ < 100) {
 2639:         str += 2;
 2640:     } 
 2641:     else if (integ < 1000) {
 2642:         str += 3;
 2643:     } 
 2644:     else if (integ < 10000) {
 2645:         str += 4;
 2646:     } 
 2647:     else {
 2648:         str += 5;
 2649:     }
 2650: 
 2651:     *str = EOL;
 2652:     
 2653:     do {
 2654:         *(--str) = integ % 10 + '0';
 2655:     } while (integ /= 10);
 2656:     
 2657:     return;
 2658: }					/* end of intstr() */
 2659: 
 2660: /******************************************************************************/
 2661: void lintstr (char *str, long integ)			/* converts long integer to string */
 2662: {
 2663:     char result[11];			/* 32 bit = 10 digits+sign */
 2664:     register int i = 0;
 2665: 
 2666:     if (integ < 0) {
 2667:         integ = (-integ);
 2668:         *str++ = '-';
 2669:     }
 2670: 
 2671:     do {
 2672:         result[i++] = integ % 10 + '0';
 2673:     } while (integ /= 10);
 2674:     
 2675:     do {
 2676:         *str++ = result[--i];
 2677:     } while (i > 0);
 2678:     
 2679:     *str = EOL;
 2680:     
 2681:     return;
 2682: 
 2683: }					/* end of lintstr() */
 2684: 
 2685: /****************************************************************/
 2686: 
 2687: /* user defined special variable table management */
 2688: /* The symbol table is placed at the high end of 'svntable'. It begins at
 2689:  * 'svnlen' and ends at 'UDFSVSIZ'. The layout is
 2690:  * (keylength)(key...)(<EOL>)(datalength)(data...[<EOL>])
 2691:  * The keys are sorted in alphabetic sequence.
 2692:  * 
 2693:  * To have the same fast access regardless of the position in the
 2694:  * alphabet for each character a pointer to the first variable beginning
 2695:  * with that letter is maintained. (0 indicates there's no such var.)
 2696:  */
 2697: 
 2698: void udfsvn (short action, char *key, char *data)		/* symbol table functions */
 2699: {
 2700: 
 2701: long keyl;			/* length of key                  */
 2702: long datal;			/* length of data                 */
 2703: register long int i, j, k, k1;
 2704: 
 2705: 
 2706: 
 2707: #ifdef DEBUG_SYM
 2708:     
 2709:     char *start;
 2710: 
 2711: #endif
 2712: 
 2713:     switch (action) {
 2714: 
 2715: 
 2716:         case get_sym:			/* retrieve */
 2717: 
 2718: 
 2719:             if ((i = svnaptr[(int) key[0]])) {
 2720: 
 2721:                 k = 1;
 2722:                 j = i + 1;			/* first char always matches! */
 2723: 
 2724:                 do {
 2725: 
 2726:                     while (key[k] == svntable[++j]) {	/* compare keys */
 2727:                         
 2728:                         if (key[k++] == EOL) {
 2729:                             
 2730:                             i = UNSIGN (svntable[++j]);
 2731:                             stcpy0 (data, &svntable[j + 1], i);
 2732:                             data[i] = EOL;
 2733:                         
 2734:                             return;
 2735:                         }
 2736: 
 2737:                     }
 2738: 
 2739:                     i += UNSIGN (svntable[i]);	/* skip key */
 2740:                     i += UNSIGN (svntable[i]) + 1;	/* skip data */
 2741:                     
 2742:                     k = 0;
 2743:                     j = i;
 2744: 
 2745:                 } while (i < UDFSVSIZ);
 2746: 
 2747:             }
 2748:             
 2749:             merr_raise (ILLFUN);            
 2750:             return;
 2751: 
 2752: 
 2753:         case set_sym:			/* store/create variable; */
 2754: 
 2755: 
 2756:             if ((keyl = stlen (key) + 2) > STRLEN) {
 2757:                 merr_raise (M75);
 2758:                 return;
 2759:             }				/* key length +2 */
 2760:             
 2761:             datal = stlen (data);		/* data length */
 2762: 
 2763:             if ((i = svnaptr[(int) key[0]])) {	/* previous entry */
 2764:                 
 2765:                 j = i + 1;
 2766:                 k = 1;
 2767: 
 2768:             } 
 2769:             else {
 2770:                 
 2771:                 i = svnlen;
 2772:                 j = i;
 2773:                 k = 0;
 2774: 
 2775:             }
 2776: 
 2777:             while (i < UDFSVSIZ) {		/* compare keys */
 2778:                 
 2779:                 while (key[k] == svntable[++j]) {
 2780:                     
 2781:                     if (key[k] == EOL) goto old;
 2782:                     
 2783:                     k++;
 2784:                 
 2785:                 }
 2786:                 
 2787:                 if (key[k] < svntable[j]) break;
 2788:                 
 2789:                 i += UNSIGN (svntable[i]);	/* skip key */
 2790:                 i += UNSIGN (svntable[i]) + 1;	/* skip data */
 2791:                 j = i;
 2792:                 k = 0;
 2793: 
 2794:             }
 2795: 
 2796:             /* if    entry found,     i pointer to searched entry
 2797:             * else  entry not found, i pointer to alphabetically next entry */
 2798:             /* new entry */
 2799:             
 2800:             k = i;
 2801:             j = key[0];
 2802:             i = keyl + datal + 1;
 2803:             
 2804:             if (svnlen <= i) {
 2805: 
 2806:                 long dif;
 2807: 
 2808:                 dif = getumore ();
 2809:                 
 2810:                 if (dif == 0L) return;
 2811:                 
 2812:                 k += dif;
 2813: 
 2814:             }
 2815: 
 2816:             for (k1 = 'a'; k1 <= j; k1++) {
 2817:                 if (svnaptr[k1]) svnaptr[k1] -= i;
 2818:             }
 2819: 
 2820:             i = k - i;
 2821:             
 2822:             if (svnaptr[j] == 0 || svnaptr[j] > i) svnaptr[j] = i;
 2823: 
 2824:             i = (svnlen -= (j = keyl + datal + 1));            
 2825:             stcpy0 (&svntable[i], &svntable[j + i], k - i);            
 2826: 
 2827:             i = k - (keyl + datal + 1);
 2828:             svntable[i++] = (char) (keyl);            
 2829:             stcpy (&svntable[i], key);	/* store new key */
 2830:             
 2831:             i += keyl - 1;
 2832:             svntable[i++] = (char) (datal);
 2833:             stcpy0 (&svntable[i], data, datal);	/* store new data */
 2834:             
 2835:             return;
 2836: 
 2837:             /* there is a previous value */
 2838: old:
 2839: 
 2840:             i += UNSIGN (svntable[i]);
 2841:             j = UNSIGN (svntable[i]) - datal;
 2842:             
 2843:             if (j < 0) {			/* more space needed */
 2844:                 
 2845:                 if (svnlen <= (-j)) {
 2846:                     
 2847:                     long dif;
 2848: 
 2849:                     dif = getumore ();
 2850:                     
 2851:                     if (dif == 0L) return;
 2852: 
 2853:                     i += dif;
 2854: 
 2855:                 }
 2856: 
 2857:                 svnlen += j;
 2858:                 
 2859:                 for (k = 'a'; k < key[0]; k++) {
 2860:                     if (svnaptr[k]) svnaptr[k] += j;
 2861:                 }
 2862: 
 2863:                 if (svnaptr[k] && svnaptr[k] < i) svnaptr[k] += j;
 2864:                 
 2865:                 k = i + j;
 2866:                 i = svnlen;
 2867:                 stcpy0 (&svntable[i], &svntable[i - j], k - i);
 2868:                 
 2869:                 i = k;
 2870:             
 2871:             } 
 2872:             else if (j > 0) {		/* surplus space */
 2873:                
 2874:                 svnlen += j;
 2875:                 
 2876:                 for (k = 'a'; k < key[0]; k++) {
 2877:                     if (svnaptr[k]) svnaptr[k] += j;
 2878:                 }
 2879: 
 2880:                 if (svnaptr[k] && svnaptr[k] < i) svnaptr[k] += j;
 2881:                 
 2882:                 i += j;
 2883:                 k = i;
 2884:                 j = i - j;
 2885:                 
 2886:                 while (i >= svnlen) {
 2887:                     svntable[i--] = svntable[j--];
 2888:                 }
 2889: 
 2890:                 i = k;
 2891: 
 2892:             }
 2893: 
 2894:             svntable[i++] = (char) (datal);
 2895:             
 2896:             stcpy0 (&svntable[i], data, datal);	/* store new data */
 2897:             
 2898:             return;
 2899:             /* end of set_sym section */
 2900:         }
 2901: }					/* end user defined special variable table */
 2902: 
 2903: 
 2904: /******************************************************************************/
 2905: long getpmore (void)
 2906: {					/* try to get more 'partition' space. returns size increment */
 2907:     
 2908:     long siz;
 2909:     long dif;
 2910: 
 2911:     if (autopsize == FALSE) return 0L;
 2912:     
 2913:     siz = PSIZE;
 2914:     
 2915:     if (siz % 1024) siz = (siz & ~01777) + 02000;	/* round for full kB; */
 2916:     
 2917:     siz += 01777;
 2918:     dif = siz - PSIZE;
 2919:     
 2920:     if (newpsize (siz)) return 0L;
 2921:     
 2922:     return dif;
 2923: 
 2924: }					/* end getpmore */
 2925: 
 2926: /******************************************************************************/
 2927: long getumore (void)
 2928: {					/* try to get more udfsvntab space. returns size increment */
 2929:     long siz, dif;
 2930: 
 2931:     if (autousize == FALSE) {
 2932:         merr_raise (STORE);
 2933:         return 0L;
 2934:     }
 2935: 
 2936:     siz = UDFSVSIZ;
 2937:     
 2938:     if (siz % 1024) siz = (siz & ~01777) + 02000;	/* round for full kB; */
 2939:     
 2940:     siz += 01777;
 2941:     dif = siz - UDFSVSIZ;
 2942:     
 2943:     if (newusize (siz)) {
 2944:         merr_raise (STORE);
 2945:         return 0L;
 2946:     }
 2947: 
 2948:     return dif;
 2949: 
 2950: }					/* end getumore */
 2951: 
 2952: /******************************************************************************/
 2953: long getrmore (void)
 2954: {					/* try to get more routine space. returns size increment */
 2955:     long siz, dif;
 2956:     short i;
 2957: 
 2958:     if (autorsize == FALSE) {
 2959:         merr_raise (PGMOV);
 2960:         return 0L;
 2961:     }
 2962:     
 2963:     siz = PSIZE0;
 2964:     
 2965:     if (siz % 1024) siz = (siz & ~01777) + 02000;	/* round for full kB; */
 2966:     
 2967:     siz += 01777;
 2968:     dif = siz - PSIZE0;
 2969:     
 2970:     for (i = 0; i < NO_OF_RBUF; i++) {	/* empty routine buffer */
 2971:         pgms[i][0] = EOL;
 2972:         ages[i] = 0L;
 2973:     }
 2974: 
 2975:     if (newrsize (siz, NO_OF_RBUF)) {
 2976:         merr_raise (PGMOV);
 2977:         return 0L;
 2978:     }
 2979: 
 2980:     return dif;
 2981: 
 2982: }					/* end getrmore */
 2983: 
 2984: /******************************************************************************/
 2985: short int getnewmore (void)
 2986: {					/* enlarge new_buffers */
 2987:     char *newbuf;
 2988:     int i;
 2989:     long dif;
 2990: 
 2991:     newbuf = calloc ((unsigned) (NSIZE + 4096), 1);	/* new_buffer                      */
 2992:     
 2993:     if (newbuf == NULL) {		/* could not allocate stuff...     */
 2994:         merr_raise (STKOV);
 2995:         return 1;
 2996:     }
 2997: 
 2998:     stcpy0 (newbuf, newstack, (long) NSIZE);
 2999:     
 3000:     dif = newbuf - newstack;
 3001:     
 3002:     free (newstack);			/* free previously allocated space */
 3003:     
 3004:     newstack = newbuf;
 3005:     NSIZE += 4096;
 3006:     newptr += dif;
 3007:     newlimit = newstack + NSIZE - 1024;
 3008:     i = 0;
 3009: 
 3010:     while (i <= nstx) {
 3011:         
 3012:         if (nestnew[i]) nestnew[i] += dif;
 3013:         
 3014:         i++;
 3015: 
 3016:     }
 3017: 
 3018:     return 0;
 3019: 
 3020: }					/* end getnewmore() */
 3021: /******************************************************************************/
 3022: 
 3023: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>