File:  [Coherent Logic Development] / freem / src / symtab_bltin.c
Revision 1.8: download - view: text, annotated - select for diffs
Fri Apr 4 12:46:13 2025 UTC (11 months, 3 weeks ago) by snw
Branches: MAIN
CVS tags: v0-63-1-rc1, HEAD
Patch Solaris 8 crash and bump version to 0.63.1-rc1

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

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