![]() ![]() | ![]() |
Convert remainder of K&R prototypes to ANSI
/* * * * * * * * * * *************** * * * * * * * MUMPS * * * * * * * *************** * * * * * * * * * * symtab.c * FreeM local system table and user-defined special variable table * * * Author: Serena Willis <jpw@coherent-logic.com> * Copyright (C) 1998 MUG Deutschland * Copyright (C) 2020 Coherent Logic Development LLC * * * This file is part of FreeM. * * FreeM is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * FreeM is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero Public License for more details. * * You should have received a copy of the GNU Affero Public License * along with FreeM. If not, see <https://www.gnu.org/licenses/>. * **/ #include <stdlib.h> #define ZNEW 'N' #include "mpsdef.h" #include <string.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/sem.h> #include <unistd.h> #include "mdebug.h" #include "merr.h" #include "consttbl.h" #include "shmmgr.h" /* Turn this on to get tons of lovely debugging messages about symbol-table calls */ /* #define DEBUG_SYM */ short restoring_consts = FALSE; int semid_symtab; #if !defined(__OpenBSD__) && !defined(__APPLE__) union semun { int val; /* Value for SETVAL */ struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* Array for GETALL, SETALL */ struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */ }; #endif long str2long(char *string) { int loop = 0; int mult = 1; int exp = 1; long value = 0; if (string[0] == '-') { mult = -1; string++; } while(string[loop] != EOL && string[loop] >= '0' && string[loop] <= '9') loop++; loop--; while(loop > -1) { value += (string[loop] - '0') * exp; exp *= 10; loop--; } value *= mult; return value; } void symtab_init (void) { register int i; union semun arg; key_t symtab_sk; symtab_sk = ftok (config_file, 6); if (first_process) { for (i = 0; i < 128; i++) { shm_config->hdr->alphptr[i] = 0L; } shm_config->hdr->symlen = PSIZE; shm_config->hdr->s = &mbpartition[PSIZE] - 256; shm_config->hdr->PSIZE = DEFPSIZE; shm_config->hdr->argptr = mbpartition; fprintf (stderr, "symtab_init: initializing memory-backed globals\r\n"); semid_symtab = semget (symtab_sk, 1, 0666 | IPC_CREAT); if (semid_symtab == -1) { fprintf (stderr, "symtab_init: failed to create symbol table semaphore\r\n"); exit (1); } else { fprintf (stderr, "symtab_init: symbol table semaphore created with semid %d\r\n", semid_symtab); } arg.val = 1; if (semctl (semid_symtab, 0, SETVAL, arg) == -1) { fprintf (stderr, "symtab_init: failed to initialize symbol table semaphore\r\n"); exit (1); } else { fprintf (stderr, "symtab_init: symbol table semaphore initialized\r\n"); } fprintf (stderr, "symtab_init: allocating partition for memory-backed globals\r\n"); mbpartition = (char *) shm_alloc ((size_t) PSIZE + 2); NULLPTRCHK(mbpartition,"symtab_init"); shm_config->hdr->partition = mbpartition; if (symtab_get_sem ()) { for (i = 0; i < 128; i++) shm_config->hdr->alphptr[i] = 0L; symtab_release_sem (); } } else { semid_symtab = semget (symtab_sk, 1, 0); if (semid_symtab == -1) { fprintf (stderr, "symtab_init: could not attach to symbol table semaphore\r\n"); exit (1); } mbpartition = shm_config->hdr->partition; } } short have_symtab_sem = FALSE; short symtab_get_sem(void) { int tries; struct sembuf s = {0, -1, IPC_NOWAIT}; if (have_symtab_sem) { return TRUE; } for (tries = 0; tries < 5; tries++) { if (semop (semid_symtab, &s, 1) != -1) { have_symtab_sem = TRUE; return TRUE; } sleep (1); } fprintf (stderr, "symtab_get_sem: fail\r\n"); have_symtab_sem = FALSE; return FALSE; } void symtab_release_sem(void) { struct sembuf s = {0, 1, 0}; semop (semid_symtab, &s, 1); have_symtab_sem = FALSE; } void symtab_shm (short action, char *key, char *data) /* symbol table functions */ { char *old_s; char *old_argptr; long old_psize; long old_symlen; unsigned long stptrs[128]; register int i; char *old_partition = partition; partition = mbpartition; writing_mb = TRUE; if (symtab_get_sem ()) { /* save off current non-shared symtab state */ old_s = s; old_argptr = argptr; old_psize = PSIZE; old_symlen = symlen; for (i = 0; i < 128; i++) { stptrs[i] = alphptr[i]; } /* replace symtab state with the values from the shared symtab */ s = shm_config->hdr->s; argptr = shm_config->hdr->argptr; PSIZE = shm_config->hdr->PSIZE; symlen = shm_config->hdr->symlen; for (i = 0; i < 128; i++) { alphptr[i] = shm_config->hdr->alphptr[i]; } /* execute the action (symtab_bltin will now be working with the shared symbol table) */ symtab_bltin (action, key, data); /* copy new alphptr state back to shared memory */ for (i = 0; i < 128; i++) { shm_config->hdr->alphptr[i] = alphptr[i]; } /* restore non-shared symtab alphptr state */ for (i = 0; i < 128; i++) { alphptr[i] = stptrs[i]; } /* write the new shared symtab state back to shared memory */ shm_config->hdr->s = s; shm_config->hdr->argptr = argptr; shm_config->hdr->PSIZE = PSIZE; shm_config->hdr->symlen = symlen; /* restore the non-shared symtab state */ s = old_s; argptr = old_argptr; PSIZE = old_psize; symlen = old_symlen; symtab_release_sem (); } else { fprintf (stderr, "symtab_shm: failed to acquire symbol table sempahore\r\n"); } writing_mb = FALSE; partition = old_partition; } /* local symbol table management */ /* (+)functions are now re-implemented */ /* (!)functions are new */ /* (?)re-implemented, with issues */ /* +set_sym +get_sym */ /* +kill_sym +$data */ /* +kill_all +$fra_order */ /* +killexcl +fra_query */ /* +new_sym +bigquery */ /* +new_all +getinc */ /* +newexcl */ /* +killone +m_alias */ /* !merge_sym +zdata */ /* !pop_sym */ /* The symbol table is placed at the high end of 'partition'. It begins at * 'symlen' and ends at 'PSIZE'. The layout is * (keylength)(key...)(<EOL>)(datalength)(data...[<EOL>]) * The keys are sorted in $order sequence. * * ****possible future layout with less space requirements**** * (keylength)(statusbyte)(key...)[(datalength)(data...[<EOL>])] * 'keylength' is the length of 'key' overhead bytes not included. * 'statusbyte' is an indicator with the following bits: * 0 (LSB) 1=data information is missing 0=there is a data field * 1 1=key is numeric 0=key is alphabetic * 2..7 0..number of previous key_pieces * note, that the status byte of a defined unsubscripted variable * is zero. * If a subscripted variable is stored, the variablename and each * subscript are separate entries in the symbol table. * E.g. S USA("CA",6789)="California" ; with $D(ABC)=0 before the set * then the following format is used: * (3)( 1)ABC * (2)(1*4+1)CA * (4)(2*4+2)6789(10)California * ****end of "possible future layout"**** * To have the same fast access regardless of the position in the * alphabet for each character a pointer to the first variable beginning * with that letter is maintained. (0 indicates there's no such var.) */ void symtab_bltin (short action, char *key, char *data) /* symbol table functions */ { /* must be static: */ static unsigned long tryfast = 0L; /* last $order reference */ /* the following variables may */ /* be static or not */ static unsigned short nocompact = TRUE; /* flag: do not compact symtab if */ /* value becomes shorter */ /* be static or dynamic: */ static long keyl, datal; /* length of key and data */ static long kill_from; static char tmp1[256], tmp2[256], tmp3[256]; register long i, j, k, k1; char tt_with[STRLEN]; char tt_key[STRLEN]; #ifdef DEBUG_SYM int i0, i1; char *start; #endif if (restoring_consts == FALSE) { if (((action % 2) == 0) && const_is_defined (key)) { merr_raise (CMODIFY); return; } } if (action == kill_all) goto no_with; if ((stlen (key) >= 5) && (strncmp (key, "%INT.", 5) == 0)) goto no_with; if (strncmp (key, "^$", 2) == 0) goto no_with; if (strncmp (key, "$", 1) == 0) goto no_with; stcpy (tt_with, i_with); stcpy (tt_key, key); stcnv_m2c (tt_with); stcnv_m2c (tt_key); snprintf (key, 100, "%s%s\201\201", tt_with, tt_key); no_with: if (dbg_enable_watch && ((action % 2) == 0)) dbg_fire_watch (key); if (key && key[1] != '$') stcpy (zloc, key); if (v22ptr) { procv22 (key); if (key[0] == '^') { char zrsav[256]; int naksav; char gosav[256]; stcpy (zrsav, zref); naksav = nakoffs; stcpy (gosav, g_o_val); global (action, key, data); stcpy (zref, zrsav); nakoffs = naksav; stcpy (l_o_val, g_o_val); stcpy (g_o_val, gosav); return; } } /* process optional limitations */ if (glvnflag.all && key[0] >= '%' && key[0] <= 'z') { if ((i = glvnflag.one[0])) { /* number of significant chars */ j = 0; while ((k1 = key[j]) != DELIM && k1 != EOL) { if (j >= i) { while ((k1 = key[++j]) != DELIM && k1 != EOL) ; stcpy (&key[i], &key[j]); break; } j++; } } if (glvnflag.one[1]) { /* upper/lower sensitivity */ j = 0; while ((k1 = key[j]) != DELIM && k1 != EOL) { if (k1 >= 'a' && k1 <= 'z') key[j] = k1 - 32; j++; } } if ((i = glvnflag.one[2])) { /* IMPACT: x11-94-28 */ if (stlen (key) > i) { merr_raise (M75); return; } /* key length limit */ } if ((i = glvnflag.one[3])) { /* subscript length limit */ j = 0; while ((k1 = key[j++]) != DELIM && k1 != EOL) ; if (k1 == DELIM) { k = 0; for (;;) { k1 = key[j++]; if (k1 == DELIM || k1 == EOL) { if (k > i) { merr_raise (M75); return; } k = 0; } if (k1 == EOL) break; k++; } } } } if (aliases && (action != m_alias)) { /* there are aliases */ i = 0; j = 0; while (i < aliases) { k1 = i + UNSIGN (ali[i]) + 1; /* is current reference an alias ??? */ j = 0; while (ali[++i] == key[j]) { if (ali[i] == EOL) break; j++; } /* yes, it is, so resolve it now! */ if (ali[i] == EOL && (key[j] == EOL || key[j] == DELIM)) { stcpy (tmp1, key); stcpy (key, &ali[i + 1]); stcat (key, &tmp1[j]); i = 0; continue; /* try again, it might be a double alias! */ } i = k1; } } #ifdef DEBUG_SYM printf("DEBUG (%d): ",action); if(key) { printf("[key] is ["); for(loop=0; key[loop] != EOL; loop++) printf("%c",(key[loop] == DELIM) ? '!' : key[loop]); printf("]\r\n"); } else { printf("No key passed in.\r\n"); } if(data) { printf("[data] (datalen) is ["); for(loop=0; data[loop] != EOL; loop++) printf("%c", data[loop]); printf("] (%d)\r\n",stlen(data)); printf("[Numeric?] is [%d]\r\n",is_numeric(data)); } else { printf("No data passed in.\r\n"); } #endif switch (action) { case get_sym: /* retrieve */ /* OLD get_sym routine */ if ((i = alphptr[(int) key[0]])) { // printf ("alphptr match; writing_mb = %d\r\n", writing_mb); k = 1; j = i + 1; /* first char always matches! */ do { while (key[k] == partition[++j]) { /* compare keys */ if (key[k] == EOL) { /* IMPACT: x11-94-28 */ i = UNSIGN (partition[++j]); if (i < 4) { k = 0; while (k < i) data[k++] = partition[++j]; } else { stcpy0 (data, &partition[j + 1], i); } data[i] = EOL; return; } k++; } i += UNSIGN (partition[i]); /* skip key */ i += UNSIGN (partition[i]) + 1; /* skip data */ k = 0; j = i; } while (i < PSIZE); } merr_raise (M6); data[0] = EOL; return; case set_sym: /* store/create variable */ /* HANDLE ISVs FROM unnew() */ if (key[0] == '$') { switch (key[1]) { case 't': /* $TEST */ test = data[0]; break; case 'z': /* $Z ISVs */ if (key[2] == 'r') { /* $ZREFERENCE / $REFERENCE */ stcpy (zref, data); } break; } } datal = stlen (data); /* data length */ /* Old set_sym routine */ /* check whether the key has subscripts or not */ if ((keyl = stlen (key) + 2) > STRLEN) { merr_raise (M75); return; } k1 = 0; i = 1; while (key[i] != EOL) { if (key[i++] == DELIM) { k1 = i; break; } } if ((i = alphptr[(int) key[0]])) { /* previous entry */ j = i + 1; k = 1; } else { i = symlen; j = i; k = 0; } if (k1 == 0) /* key was unsubscripted */ /* compare keys */ while (i < PSIZE) { while (key[k] == partition[++j]) { if (key[k] == EOL) goto old; k++; } if (key[k] < partition[j]) break; i += UNSIGN (partition[i]); /* skip key */ i += UNSIGN (partition[i]) + 1; /* skip data */ j = i; k = 0; } else { /* key was subscripted */ /* compare keys */ while (i < PSIZE) { while (key[k] == partition[++j]) { if (key[k] == EOL) goto old; k++; } if (k < k1) { if (key[k] < partition[j]) break; } else { long m, n, o, ch; /* get complete subscripts */ n = k; while (key[--n] != DELIM) ; n++; m = j + n - k; o = 0; while ((ch = tmp3[o++] = partition[m++]) != EOL && ch != DELIM) ; if (ch == DELIM) tmp3[--o] = EOL; o = 0; while ((ch = tmp2[o++] = key[n++]) != EOL && ch != DELIM) ; if (ch == DELIM) tmp2[--o] = EOL; if (collate (tmp3, tmp2) == FALSE) { if (stcmp (tmp2, tmp3) || ch == EOL) break; } } i += UNSIGN (partition[i]); /* skip key */ i += UNSIGN (partition[i]) + 1; /* skip data */ j = i; k = 0; } } /* if entry found, i pointer to searched entry * else entry not found, i pointer to alphabetically next entry */ /* new entry */ if (setop) { tmp1[0] = EOL; m_op (tmp1, data, setop); setop = 0; if (merr () > OK) return; datal = stcpy (data, tmp1); } k = i; j = key[0]; i = keyl + datal + 1; if (alphptr['%']) alphptr['%'] -= i; for (k1 = 'A'; k1 <= j; k1++) { if (alphptr[k1]) alphptr[k1] -= i; } i = k - i; if (alphptr[j] == 0 || alphptr[j] > i) alphptr[j] = i; j = keyl + datal + 1; i = symlen - j; if (i <= 256) { /* more space needed. try to get it */ long dif = 0L; dif = getpmore (); if (dif == 0) { merr_raise (STORE); return; } data = argptr; i += dif; k += dif; } symlen = i; s = &partition[i] - 256; stcpy0 (&partition[i], &partition[j + i], k - i); i = k - (keyl + datal + 1); partition[i++] = (char) (keyl); stcpy (&partition[i], key); /* store new key */ i += keyl - 1; /* IMPACT: x11-94-28 */ partition[i++] = (char) (datal); stcpy0 (&partition[i], data, datal); /* store new data */ return; /* there is a previous value */ old: i += UNSIGN (partition[i]); if (setop) { j = UNSIGN (partition[i]); stcpy0 (tmp1, &partition[i + 1], j); tmp1[j] = EOL; m_op (tmp1, data, setop); setop = 0; if (merr () > OK) return; datal = stcpy (data, tmp1); } old0: /* entry from getinc */ /* IMPACT: x11-94-28 */ j = UNSIGN (partition[i]) - datal; if (j < 0) { /* more space needed */ if ((symlen + j) <= 256) { long dif = 0L; dif = getpmore (); if (dif == 0L) { merr_raise (STORE); return; } data = argptr; i += dif; } for (k = 36; k < key[0]; k++) { if (alphptr[k]) alphptr[k] += j; } if (alphptr[k] && alphptr[k] < i) alphptr[k] += j; stcpy0 (&partition[symlen + j], &partition[symlen], i - symlen); i += j; symlen += j; s = &partition[symlen] - 256; tryfast = 0; } else if (j > 0) { /* surplus space */ if (nocompact) { /* in a dynamic environment it is sufficient to */ /* set newdatalength=olddatalength */ datal += j; } else { /* instead of compression of the local symbol table, */ /* which the following piece of code does */ symlen += j; s = &partition[symlen] - 256; for (k = 36; k < key[0]; k++) { if (alphptr[k]) alphptr[k] += j; } if (alphptr[k] && alphptr[k] < i) alphptr[k] += j; i += j; k = i; j = i - j; while (i >= symlen) { partition[i--] = partition[j--]; } i = k; tryfast = 0; nocompact = TRUE; } } /* IMPACT: x11-94-28 */ partition[i++] = (char) (datal); j = datal; if (j < 4) { k = 0; while (k < j) partition[i++] = data[k++]; return; } stcpy0 (&partition[i], data, j); /* store new data */ return; /* end of set_sym section */ case dat: /* note: we assume EOL<DELIM<ASCII */ data[0] = '0'; data[1] = EOL; if ((i = alphptr[(int) key[0]])) { data[2] = EOL; j = i + 1; k = 1; do { while ((k1 = key[k] - partition[++j]) == 0) { /* compare keys */ if (key[k] == EOL) break; k++; } if (k1 == 0) { data[0] = '1'; } else { if (partition[j] == DELIM && key[k] == EOL) { data[1] = data[0]; data[0] = '1'; return; } if (k1 < 0 && k < 2) return; } i += UNSIGN (partition[i]); /* skip key */ i += UNSIGN (partition[i]) + 1; /* skip data */ j = i; k = 0; } while (i < PSIZE); } return; /* end of $data section */ case getinc: /* increment by one and retrieve */ #ifdef DEBUG_SYM printf ("DEBUG GETINC: "); printf ("[key] is ["); for (loop = 0; key[loop] != EOL; loop++) printf ("%c", (key[loop] == DELIM) ? '!' : key[loop]); printf("]\r\n"); #endif if ((i = alphptr[(int) key[0]])) { j = i + 1; k = 1; do { while (key[k] == partition[++j]) { /* compare keys */ if (key[k] == EOL) { i = UNSIGN (partition[++j]); stcpy0 (data, &partition[j + 1], i); data[i] = EOL; /* data retrieved ... now increment */ /****************increment by one*******************/ if (i == 0) i++; /* if data was empty use EOL as dummy value */ if (i > 1 && data[0] == '0') i++; /* leading zero use EOL as dummy value */ k = 0; while (k < i) { if ((k1 = data[k++]) < '0' || k1 > '9') { /* no positive integer */ numlit (data); tmp1[0] = '1'; tmp1[1] = EOL; add (data, tmp1); datal = stlen (data); i = j; nocompact = FALSE; /* getinc needs compacted symtab */ goto old0; } } k1 = k--; /* length of string */ while ((partition[j + 1 + k] = ++data[k]) > '9') { partition[j + 1 + k] = '0'; data[k--] = '0'; if (k < 0) { k = k1; while (k >= 0) { data[k + 1] = data[k]; k--; } data[0] = '1'; s = &partition[--symlen] - 256; if (alphptr['%']) alphptr['%']--; for (k = 'A'; k <= key[0]; k++) { if (alphptr[k]) alphptr[k]--; } k = j - 1; j = symlen; stcpy0 (&partition[j], &partition[j + 1], k - j); partition[k] = (char) ++i; partition[++k] = '1'; return; } } return; /************end increment by one*******************/ } k++; } /** if (key[k]<partition[j]) break; **/ i += UNSIGN (partition[i]); /* skip key */ i += UNSIGN (partition[i]) + 1; /* skip data */ j = i; k = 0; } while (i < PSIZE); } data[0] = EOL; merr_raise (UNDEF); return; case fra_order: /* next one please */ if (ordercnt < 0) goto zinv; k1 = (j = stcpy (tmp1, key) - 1); while (tmp1[k1] != DELIM) { if ((--k1) <= 0) goto unsubscr; } tmp1[++k1] = EOL; stcpy (tmp2, &key[k1]); if (ordercnt == 0) { stcpy (data, tmp2); l_o_val[0] = EOL; return; } data[0] = EOL; if ((i = alphptr[(int) key[0]]) == 0) { l_o_val[0] = EOL; return; } /***************************/ /* frequent special case: the key of which we search the next * entry is defined ! */ if (tmp2[0] != EOL) { if (tryfast && stcmp (key, &partition[tryfast + 1]) == 0) { j = tryfast; j += UNSIGN (partition[j]); /* skip key */ j += UNSIGN (partition[j]) + 1; /* skip data */ goto begorder; } k = 1; j = i + 1; /* first char always matches! */ do { while (key[k] == partition[++j]) { /* compare keys */ if (key[k++] == EOL) { j = i; goto begorder; } } i += UNSIGN (partition[i]); /* skip key */ i += UNSIGN (partition[i]) + 1; /* skip data */ k = 0; j = i; } while (i < PSIZE); } /* the key was not defined */ /***************************/ j = alphptr[(int) key[0]]; begorder: do { if (key[0] != partition[j + 1]) { l_o_val[0] = EOL; data[0] = EOL; return; } stcpy0 (data, &partition[j + 1], k1); data[k1] = EOL; if (stcmp (tmp1, data) == 0) { stcpy (data, &partition[j + 1 + k1]); /* index on same level */ k = 0; while (data[k] != EOL && data[k] != DELIM) k++; data[k] = EOL; if (collate (tmp2, data)) { if (--ordercnt <= 0) { tryfast = j; /* save data value for inspection with $V(110) */ j += UNSIGN (partition[j]); /* skip key */ k = UNSIGN (partition[j++]); stcpy0 (l_o_val, &partition[j], k); l_o_val[k] = EOL; return; } ordercounter++; } } j += UNSIGN (partition[j]); /* skip key */ j += UNSIGN (partition[j]) + 1; /* skip data */ } while (j < PSIZE); data[0] = EOL; tryfast = 0; l_o_val[0] = EOL; return; /* end of $order section */ case kill_all: genocid: /* Old genocide routine */ alphptr['%'] = 0; for (i = 'A'; i <= 'z'; alphptr[i++] = 0) ; symlen = PSIZE; s = &partition[symlen] - 256; tryfast = 0; ssvn_system_update (); ssvn_job_update (); ssvn_routine_update (); #if defined(HAVE_MWAPI_MOTIF) ssvn_display_update (); #endif const_restore (); return; case kill_sym: /* kill them dirty bloody variables */ /* Old Kill Routine */ if ((i = alphptr[(int) key[0]]) == 0) return; /* damn - nothing to kill */ kill_from = 0; while (i < PSIZE) { j = i; k = 0; while ((k1 = key[k]) == partition[++j]) { /* compare keys */ if (k1 == EOL) break; k++; } if (k1 == EOL && (partition[j] == DELIM || partition[j] == EOL)) { if (kill_from == 0) kill_from = i; } else { if (kill_from) break; } i += UNSIGN (partition[i]); /* skip key */ i += UNSIGN (partition[i]) + 1; /* skip data */ } k_entry: /* entry from killone section */ if (kill_from) { j = i - kill_from; symlen += j; s = &partition[symlen] - 256; for (k = 36; k < key[0]; k++) { if (alphptr[k]) alphptr[k] += j; } if (alphptr[k] == kill_from) { alphptr[k] = i; if (partition[i + 1] != key[0]) alphptr[k] = 0; } else { alphptr[k] += j; } /* j=i-j; while(i>symlen) partition[--i]=partition[--j]; */ stcpy1 (&partition[i - 1], &partition[i - j - 1], i - symlen); } tryfast = 0; return; /* end of kill_sym section */ case killone: /* kill one variable, not descendants */ if ((i = alphptr[(int) key[0]]) == 0) return; /* nothing to kill */ kill_from = 0; while (i < PSIZE) { j = i; k = 0; while ((k1 = key[k]) == partition[++j]) { /* compare keys */ if (k1 == EOL) break; k++; } k = i; i += UNSIGN (partition[i]); /* skip key */ i += UNSIGN (partition[i]) + 1; /* skip data */ if (k1 == EOL) { if (partition[j] == DELIM) return; /* descendant */ kill_from = k; goto k_entry; } } tryfast = 0; return; /* end of killone section */ case killexcl: /* exclusive kill */ i = symlen; while (i < PSIZE) { tmp2[0] = SP; kill_from = i; stcpy (tmp3, &partition[i + 1]); stcpy (&tmp2[1], tmp3); stcat (tmp2, " \201"); i += UNSIGN (partition[i]); i += UNSIGN (partition[i]) + 1; if (kill_ok (key, tmp2) == 0) continue; /* don't kill */ while (i < PSIZE) { j = i; k = 0; while ((k1 = tmp3[k]) == partition[++j]) { /* compare keys */ if (k1 == EOL) break; k++; } if (k1 != EOL || (partition[j] != DELIM && partition[j] != EOL)) break; i += UNSIGN (partition[i]); /* skip key */ i += UNSIGN (partition[i]) + 1; /* skip data */ } j = i - kill_from; symlen += j; s = &partition[symlen] - 256; for (k = 36; k < tmp3[0]; k++) { if (alphptr[k]) alphptr[k] += j; } if (alphptr[k] == kill_from) { alphptr[k] = i; if (partition[i + 1] != tmp3[0]) alphptr[k] = 0; } else { alphptr[k] += j; } stcpy1 (&partition[i - 1], &partition[i - j - 1], i - symlen); i = kill_from + j; } tryfast = 0; return; /* end of killexcl section */ case fra_query: /* next entry */ case bigquery: if (ordercnt == 0) { l_o_val[0] = EOL; zname (data, key + stlen (i_with)); return; } /***************************/ /* frequent special case: the key which we search for is the next * entry */ if ((i = alphptr[(int) key[0]])) { if (stcmp (key, &partition[tryfast + 1]) == 0) { i = tryfast; } else { j = i; do { if (stcmp (key, &partition[j + 1]) == 0) { i = j; break; } j += UNSIGN (partition[j]); /* skip key */ j += UNSIGN (partition[j]) + 1; /* skip data */ } while (j < PSIZE); } } else { i = symlen; /* no previous entry */ } /***************************/ /* check whether the key has subscripts or not */ k1 = 0; k = 1; while (key[k] != EOL) { if (key[k++] == DELIM) { k1 = k; break; } } while (i < PSIZE) { j = i; k = 0; while (key[k] == partition[++j]) { /* compare keys */ if (key[k] == EOL) break; k++; } if (key[k] == EOL) { if (partition[j] == EOL) { i += UNSIGN (partition[i]); i += UNSIGN (partition[i]) + 1; } break; } if (k < k1 || k1 == 0) { if (key[k] < partition[j]) break; } else { long m, n, o, ch; /* get complete subscripts */ n = k; while (key[--n] != DELIM) ; n++; m = j + n - k; o = 0; while ((ch = tmp2[o++] = key[n++]) != EOL && ch != DELIM) ; if (ch == DELIM) tmp2[--o] = EOL; o = 0; while ((ch = tmp3[o++] = partition[m++]) != EOL && ch != DELIM) ; if (ch == DELIM) tmp3[--o] = EOL; if (collate (tmp2, tmp3)) break; } i += UNSIGN (partition[i]); /* skip key */ i += UNSIGN (partition[i]) + 1; /* skip data */ } /* multiple backward query */ if (ordercnt < 0) { j = symlen; k = ordercnt - 1; while (j < i) { /* count entries */ j += UNSIGN (partition[j]); /* skip key */ j += UNSIGN (partition[j]) + 1; /* skip data */ k++; } if (k < 0) { data[0] = EOL; l_o_val[0] = EOL; return; } i = symlen; while (--k >= 0) { i += UNSIGN (partition[i]); /* skip key */ i += UNSIGN (partition[i]) + 1; /* skip data */ } } /* end: multiple backward query */ while (--ordercnt > 0) { /* multiple forward $query */ if (i >= PSIZE) break; i += UNSIGN (partition[i]); /* skip key */ i += UNSIGN (partition[i]) + 1; /* skip data */ } /* now 'i' is pointer to 'next' entry */ tryfast = i; /* save data value for inspection with $V(110) */ j = i; j += UNSIGN (partition[j]); k = UNSIGN (partition[j]); stcpy0 (l_o_val, &partition[j + 1], k); l_o_val[k] = EOL; keyl = i; keyl += UNSIGN (partition[i++]) - 2; /* action==bigquery may return a result in a different lvn */ /* which is illegal with $query() */ if (action == fra_query) { k = 0; /* is result same lvn? */ while (partition[i+k] == key[k]) { if (key[k] == DELIM) break; k++; } if (partition[i+k] != DELIM) i = keyl + 1; /* discard result! */ } if (i <= keyl) { zname (data, &partition[i + stlen (i_with)]); } else { data[0] = EOL; } return; /* end of $query section */ zinv: /* previous one please */ data[0] = EOL; l_o_val[0] = EOL; k1 = (j = stcpy (tmp1, key) - 1); while (tmp1[k1] != DELIM) { if ((--k1) <= 0) { merr_raise (NEXTER); return; } } tmp1[++k1] = EOL; stcpy (tmp2, &key[k1]); if (tmp2[0] == EOL) { tmp2[0] = DEL; tmp2[1] = DEL; tmp2[2] = EOL; } k = (int) (key[0]); if (alphptr[k] == 0) return; j = alphptr[k]; do { if (key[0] != partition[j + 1]) goto zinvend; stcpy0 (tmp3, &partition[j + 1], k1); tmp3[k1] = EOL; if (stcmp (tmp1, tmp3) == 0) { stcpy (tmp3, &partition[j + 1 + k1]); /* index on same level */ k = 0; while (tmp3[k] != EOL && tmp3[k] != DELIM) k++; tmp3[k] = EOL; if (collate (tmp3, tmp2) == FALSE) goto zinvend; stcpy (data, tmp3); /* save data value for inspection with $V(110) */ i = j; i += UNSIGN (partition[i]); k = UNSIGN (partition[i]); stcpy0 (l_o_val, &partition[i + 1], k); l_o_val[k] = EOL; } j += UNSIGN (partition[j]); /* skip key */ j += UNSIGN (partition[j]) + 1; /* skip data */ } while (j < PSIZE); zinvend: if (data[0] == EOL) return; ordercounter++; if (++ordercnt >= 0) return; stcpy (&key[k1], data); goto zinv; /* end of $zinverse section */ case new_sym: /* new one symbol */ if (key[0] == '$') { /* $svn: save current value on new stack */ if (newptr > newlimit && getnewmore ()) return; if ((key[1] | 0140) == 't') { /* NEW $TEST */ *newptr++ = test; *newptr++ = EOL; *newptr++ = 1; k1 = stcpy (newptr, "$t\201"); newptr += k1; *newptr++ = EOL; *newptr++ = k1; *newptr++ = set_sym; //if (mcmnd != ZNEW) test = FALSE; return; } if ((key[1] | 0140) == 'j') { /* NEW $JOB */ *newptr++ = pid / 256; *newptr++ = pid % 256; *newptr++ = EOL; *newptr++ = 2; k1 = stcpy (newptr, "$j\201"); newptr += k1; *newptr++ = EOL; *newptr++ = k1; *newptr++ = set_sym; return; } if (((key[1] | 0140) == 'z') && ((key[2] | 0140) == 'i')) { /* NEW $ZINRPT */ *newptr++ = breakon; *newptr++ = EOL; *newptr++ = 1; k1 = stcpy (newptr, "$zi\201"); newptr += k1; *newptr++ = EOL; *newptr++ = k1; *newptr++ = set_sym; return; } /* NEW $ETRAP added 10 Oct 2020, JPW */ if (((key[1] | 0140) == 'e') && ((key[2] | 0140) == 't')) { /* NEW $ETRAP */ j = stcpy (newptr, etrap); newptr += j; *newptr++ = EOL; *newptr++ = j; k1 = stcpy (newptr, "$et\201"); newptr += k1; *newptr++ = EOL; *newptr++ = k1; *newptr++ = set_sym; return; } /* NEW $ESTACK added 12 Oct 2020, JPW */ if (((key[1] | 0140) == 'e') && ((key[2] | 0140) == 's')) { /* NEW $ESTACK */ char esbuf[256]; snprintf (esbuf, 255, "%d\201", estack); j = stcpy (newptr, esbuf); newptr += j; *newptr++ = EOL; *newptr++ = j; k1 = stcpy (newptr, "$es\201"); newptr += k1; *newptr++ = EOL; *newptr++ = k1; *newptr++ = set_sym; estack = 0; return; } j = stcpy (newptr, zref); /* NEW $ZREFERENCE */ newptr += j; *newptr++ = EOL; *newptr++ = j; k1 = stcpy (newptr, "$zr\201"); newptr += k1; *newptr++ = EOL; *newptr++ = nakoffs; k1++; *newptr++ = k1; *newptr++ = set_sym; if (mcmnd != ZNEW) zref[0] = EOL; return; } if ((i = alphptr[(int) key[0]])) { /* is there something to be saved?/killed */ /* always FALSE with special variables */ kill_from = 0; while (i < PSIZE) { j = i; k = 0; while ((k1 = key[k]) == partition[++j]) { /* compare keys */ if (k1 == EOL) break; k++; } if (k1 == EOL && (partition[j] == DELIM || partition[j] == EOL)) { if (kill_from == 0) kill_from = i; } else { if (kill_from) break; } if (kill_from) { /* save current values on new stack */ j = UNSIGN (partition[i]); k = i + 1; k1 = j; i += j; j = UNSIGN (partition[i]); if (newptr > newlimit && getnewmore ()) return; #ifdef DEBUG_SYM start = newptr; #endif stcpy0 (newptr, &partition[i + 1], j); newptr += j; *newptr++ = EOL; *newptr++ = j; i += (j + 1); stcpy0 (newptr, &partition[k], k1); newptr += k1; *newptr++ = EOL; *newptr++ = k1; *newptr++ = set_sym; #ifdef DEBUG_SYM printf ("SAVING [newptr] newptr became ["); while (start < newptr) { printf ("%c(%d)", (*start==EOL) ? ('!') : *start, *start); start++; } printf("{%d}]\r\n", *(newptr - 1)); #endif } else { i += UNSIGN (partition[i]); /* skip key */ i += UNSIGN (partition[i]) + 1; /* skip data */ } } if (kill_from && mcmnd != ZNEW) { j = i - kill_from; symlen += j; s = &partition[symlen] - 256; for (k = 36; k < key[0]; k++) { if (alphptr[k]) alphptr[k] += j; } if (alphptr[k] == kill_from) { alphptr[k] = i; if (partition[i + 1] != key[0]) alphptr[k] = 0; } else { alphptr[k] += j; } stcpy1 (&partition[i - 1], &partition[i - j - 1], i - symlen); } tryfast = 0; } if (newptr > newlimit && getnewmore ()) return; #ifdef DEBUG_SYM start = newptr; #endif j = stcpy (newptr, key); newptr += j; *newptr++ = EOL; *newptr++ = j; *newptr++ = kill_sym; #ifdef DEBUG_SYM printf ("KILLING [newptr] newptr became ["); while (start < newptr) { printf ("%c(%d)", (*start == EOL) ? ('!') : *start,*start ); start++; } printf ("{%d}]\r\n", *(newptr - 1)); #endif return; /* end of new_sym section */ case new_all: /* new all symbols */ i = symlen; while (i < PSIZE) { j = UNSIGN (partition[i]); k = i + 1; k1 = j; i += j; j = UNSIGN (partition[i]); if (newptr > newlimit && getnewmore ()) return; stcpy0 (newptr, &partition[i + 1], j); newptr += j; *newptr++ = EOL; *newptr++ = j; i += (j + 1); stcpy0 (newptr, &partition[k], k1); newptr += k1; *newptr++ = EOL; *newptr++ = k1; *newptr++ = set_sym; } *newptr++ = kill_all; if (mcmnd == ZNEW) return; goto genocid; /* ... and now kill them all */ /* end of new_all section */ case newexcl: /* new all except specified */ i = symlen; while (i < PSIZE) { tmp2[0] = SP; kill_from = i; stcpy (tmp3, &partition[i + 1]); stcpy (&tmp2[1], tmp3); stcat (tmp2, " \201"); if (kill_ok (key, tmp2) == 0) { /* don't new */ i += UNSIGN (partition[i]); i += UNSIGN (partition[i]) + 1; continue; } j = UNSIGN (partition[i]); k = i + 1; k1 = j; i += j; j = UNSIGN (partition[i]); if (newptr > newlimit && getnewmore ()) return; stcpy0 (newptr, &partition[i + 1], j); newptr += j; *newptr++ = EOL; *newptr++ = j; i += (j + 1); stcpy0 (newptr, &partition[k], k1); newptr += k1; *newptr++ = EOL; *newptr++ = k1; *newptr++ = set_sym; while (i < PSIZE) { j = i; k = 0; while ((k1 = tmp3[k]) == partition[++j]) { /* compare keys */ if (k1 == EOL) break; k++; } if (k1 != EOL || (partition[j] != DELIM && partition[j] != EOL)) break; j = UNSIGN (partition[i]); k = i + 1; k1 = j; i += j; j = UNSIGN (partition[i]); if (newptr > newlimit && getnewmore ()) return; stcpy0 (newptr, &partition[i + 1], j); newptr += j; *newptr++ = EOL; *newptr++ = j; i += (j + 1); stcpy0 (newptr, &partition[k], k1); newptr += k1; *newptr++ = EOL; *newptr++ = k1; *newptr++ = set_sym; } if (mcmnd == ZNEW) continue; j = i - kill_from; symlen += j; s = &partition[symlen] - 256; for (k = 36; k < tmp3[0]; k++) { if (alphptr[k]) alphptr[k] += j; } if (alphptr[k] == kill_from) { alphptr[k] = i; if (partition[i + 1] != tmp3[0]) alphptr[k] = 0; } else { alphptr[k] += j; } stcpy1 (&partition[i - 1], &partition[i - j - 1], i - symlen); i = kill_from + j; } tryfast = 0; if (newptr > newlimit && getnewmore ()) return; j = stcpy (newptr, key); newptr += (j + 1); *newptr++ = j; *newptr++ = killexcl; return; /* end of newexcl section */ case m_alias: /* define an alias of a variable */ /* process stuff */ if (stcmp (key, data) == 0) return; /* sorry, that's no alias */ if (data[0] == EOL) { /* delete an alias from the table */ if (aliases) { /* there are aliases */ i = 0; while (i < aliases) { k = i; k1 = i + UNSIGN (ali[i]) + 1; j = 0; /* is current reference an alias ??? */ while (ali[++i] == key[j]) { if (ali[i] == EOL) break; j++; } /* yes, it is, so resolve it now! */ if (ali[i] == EOL && key[j] == EOL) { if (aliases > k1) stcpy0 (&ali[k], &ali[k1], aliases - k1); aliases -= (k1 - k); return; } i = k1; } } return; } /* new entry to alias table. there is no check agains duplicate entries */ i = stlen (key); j = stlen (data); ali[aliases++] = (char) (i + j + 2); /* byte for fast skipping */ stcpy (&ali[aliases], key); aliases += (i + 1); stcpy (&ali[aliases], data); aliases += (j + 1); /* write note to unmake the alias */ j = stcpy (newptr, key); newptr += (j + 1); *newptr++ = j; *newptr++ = m_alias; return; case zdata: /* nonstandard data function */ { long counties[128]; int icnt, icnt0; i = 0; while (i < 128) counties[i++] = 0L; /* init count; */ /* note: we assume EOL<DELIM<ASCII */ icnt = 0; i = 0; while ((j = key[i++]) != EOL) { if (j == DELIM) { icnt++; } } if ((i = alphptr[(int) key[0]])) { data[2] = EOL; j = i + 1; k = 1; do { icnt0 = j + 1; while ((k1 = key[k] - partition[++j]) == 0) { /* compare keys */ if (key[k] == EOL) break; k++; } if (k1 == 0) { counties[0] = 1; } else { if (partition[j] == DELIM && key[k] == EOL) { int ch; j = icnt0; icnt0 = 0; while ((ch = partition[j++]) != EOL) { if (ch == DELIM) { icnt0++; } } if (icnt0 <= icnt) break; counties[icnt0 - icnt]++; } /* if (k1<0 && k<2) break; */ } i += UNSIGN (partition[i]); /* skip key */ i += UNSIGN (partition[i]) + 1; /* skip data */ j = i; k = 0; } while (i < PSIZE); } i = 128; while (counties[--i] == 0L) ; lintstr (data, counties[0]); j = 1; tmp1[0] = ','; while (j <= i) { lintstr (&tmp1[1], counties[j++]); stcat (data, tmp1); } return; } /* end of $zdata section */ } /* end of action switch */ /* return next variable or array name - non standard */ unsubscr: if (standard) { merr_raise (NEXTER); return; } j = key[0]; data[0] = EOL; while (alphptr[j] == 0) { if (++j >= DEL) return; } i = alphptr[j]; while (i < PSIZE) { j = i; k = 0; while ((k1 = key[k] - partition[++j]) == 0) { /* compare keys */ if (key[k] == EOL) break; k++; } if (k1 < 0 && (partition[j] != DELIM || key[k] != EOL)) { j = i; i = 0; while ((data[i] = partition[++j]) != EOL) { if (data[i] == DELIM) { data[i] = EOL; break; } i++; } return; } i += UNSIGN (partition[i]); /* skip key */ i += UNSIGN (partition[i]) + 1; /* skip data */ } return; } /* end of symtab() */ /******************************************************************************/ /* if 't' follows 's' in MUMPS collating sequence a 1 is returned * otherwise 0 */ short int collate (char *s, char *t) { short dif; if (s[0] == EOL) return (t[0] != EOL); /* the empty one is the leader! */ if (t[0] == EOL) return FALSE; if ((dif = stcmp (t, s)) == 0) return FALSE; if (numeric (s)) { /* then come numerics */ if (numeric (t) == FALSE) return TRUE; return comp (s, t); } if (numeric (t)) return FALSE; return dif > 0; } /* end of collate() */ /******************************************************************************/ short int numeric (char *str) /** * boolean function that tests * whether str is a canonical * numeric */ { register int ptr = 0, ch; register int point; if (str[0] == '-') { ptr = 1; } if (str[ptr] == EOL) { return FALSE; } if (str[ptr] == '0') return str[1] == EOL; /* leading zero */ point = FALSE; while ((ch = str[ptr++]) != EOL) { if (ch > '9') { return FALSE; } if (ch < '0') { if (ch != '.') return FALSE; if (point) return FALSE; /* multiple points */ point = TRUE; } } if (point) { if ((ch = str[ptr - 2]) == '0') return FALSE; /* trailing zero */ if (ch == '.') return FALSE; /* trailing point */ } return TRUE; } /* end of numeric() */ /******************************************************************************/ /* s and t are strings representing */ /* MUMPS numbers. comp returns t>s */ short int comp (char *s, char *t) { register int s1 = s[0], t1 = t[0], point = '.'; #if !defined(_AIX) if (fp_mode) { double fp_s; double fp_t; stcnv_m2c (s); stcnv_m2c (t); fp_s = atof (s); fp_t = atof (t); return fp_t > fp_s; } #endif if (s1 != t1) { if (s1 == '-') return TRUE; /* s<0<t */ if (t1 == '-') return FALSE; /* t<0<s */ if (s1 == point && t1 == '0') return FALSE; /* s>0; t==0 */ if (t1 == point && s1 == '0') return TRUE; /* t>0; s==0 */ } if (t1 == '-') { char *a; a = &t[1]; t = &s[1]; s = a; } s1 = 0; while (s[s1] > point) s1++; /* Note: EOL<'.' */ t1 = 0; while (t[t1] > point) t1++; if (t1 > s1) return TRUE; if (t1 < s1) return FALSE; while (*t == *s) { if (*t == EOL) return FALSE; t++; s++; } if (*t > *s) return TRUE; return FALSE; } /* end of comp() */ /******************************************************************************/ void intstr (char *str, short integ) /* converts integer to string */ { if (integ < 0) { integ = (-integ); *str++ = '-'; } if (integ < 10) { *str++ = integ + '0'; *str = EOL; return; } else if (integ < 100) { str += 2; } else if (integ < 1000) { str += 3; } else if (integ < 10000) { str += 4; } else { str += 5; } *str = EOL; do { *(--str) = integ % 10 + '0'; } while (integ /= 10); return; } /* end of intstr() */ /******************************************************************************/ void lintstr (char *str, long integ) /* converts long integer to string */ { char result[11]; /* 32 bit = 10 digits+sign */ register int i = 0; if (integ < 0) { integ = (-integ); *str++ = '-'; } do { result[i++] = integ % 10 + '0'; } while (integ /= 10); do { *str++ = result[--i]; } while (i > 0); *str = EOL; return; } /* end of lintstr() */ /****************************************************************/ /* user defined special variable table management */ /* The symbol table is placed at the high end of 'svntable'. It begins at * 'svnlen' and ends at 'UDFSVSIZ'. The layout is * (keylength)(key...)(<EOL>)(datalength)(data...[<EOL>]) * The keys are sorted in alphabetic sequence. * * To have the same fast access regardless of the position in the * alphabet for each character a pointer to the first variable beginning * with that letter is maintained. (0 indicates there's no such var.) */ void udfsvn (short action, char *key, char *data) /* symbol table functions */ { long keyl; /* length of key */ long datal; /* length of data */ register long int i, j, k, k1; #ifdef DEBUG_SYM char *start; #endif switch (action) { case get_sym: /* retrieve */ if ((i = svnaptr[(int) key[0]])) { k = 1; j = i + 1; /* first char always matches! */ do { while (key[k] == svntable[++j]) { /* compare keys */ if (key[k++] == EOL) { i = UNSIGN (svntable[++j]); stcpy0 (data, &svntable[j + 1], i); data[i] = EOL; return; } } i += UNSIGN (svntable[i]); /* skip key */ i += UNSIGN (svntable[i]) + 1; /* skip data */ k = 0; j = i; } while (i < UDFSVSIZ); } merr_raise (ILLFUN); return; case set_sym: /* store/create variable; */ if ((keyl = stlen (key) + 2) > STRLEN) { merr_raise (M75); return; } /* key length +2 */ datal = stlen (data); /* data length */ if ((i = svnaptr[(int) key[0]])) { /* previous entry */ j = i + 1; k = 1; } else { i = svnlen; j = i; k = 0; } while (i < UDFSVSIZ) { /* compare keys */ while (key[k] == svntable[++j]) { if (key[k] == EOL) goto old; k++; } if (key[k] < svntable[j]) break; i += UNSIGN (svntable[i]); /* skip key */ i += UNSIGN (svntable[i]) + 1; /* skip data */ j = i; k = 0; } /* if entry found, i pointer to searched entry * else entry not found, i pointer to alphabetically next entry */ /* new entry */ k = i; j = key[0]; i = keyl + datal + 1; if (svnlen <= i) { long dif; dif = getumore (); if (dif == 0L) return; k += dif; } for (k1 = 'a'; k1 <= j; k1++) { if (svnaptr[k1]) svnaptr[k1] -= i; } i = k - i; if (svnaptr[j] == 0 || svnaptr[j] > i) svnaptr[j] = i; i = (svnlen -= (j = keyl + datal + 1)); stcpy0 (&svntable[i], &svntable[j + i], k - i); i = k - (keyl + datal + 1); svntable[i++] = (char) (keyl); stcpy (&svntable[i], key); /* store new key */ i += keyl - 1; svntable[i++] = (char) (datal); stcpy0 (&svntable[i], data, datal); /* store new data */ return; /* there is a previous value */ old: i += UNSIGN (svntable[i]); j = UNSIGN (svntable[i]) - datal; if (j < 0) { /* more space needed */ if (svnlen <= (-j)) { long dif; dif = getumore (); if (dif == 0L) return; i += dif; } svnlen += j; for (k = 'a'; k < key[0]; k++) { if (svnaptr[k]) svnaptr[k] += j; } if (svnaptr[k] && svnaptr[k] < i) svnaptr[k] += j; k = i + j; i = svnlen; stcpy0 (&svntable[i], &svntable[i - j], k - i); i = k; } else if (j > 0) { /* surplus space */ svnlen += j; for (k = 'a'; k < key[0]; k++) { if (svnaptr[k]) svnaptr[k] += j; } if (svnaptr[k] && svnaptr[k] < i) svnaptr[k] += j; i += j; k = i; j = i - j; while (i >= svnlen) { svntable[i--] = svntable[j--]; } i = k; } svntable[i++] = (char) (datal); stcpy0 (&svntable[i], data, datal); /* store new data */ return; /* end of set_sym section */ } } /* end user defined special variable table */ /******************************************************************************/ long getpmore (void) { /* try to get more 'partition' space. returns size increment */ long siz; long dif; if (autopsize == FALSE) return 0L; siz = PSIZE; if (siz % 1024) siz = (siz & ~01777) + 02000; /* round for full kB; */ siz += 01777; dif = siz - PSIZE; if (newpsize (siz)) return 0L; return dif; } /* end getpmore */ /******************************************************************************/ long getumore (void) { /* try to get more udfsvntab space. returns size increment */ long siz, dif; if (autousize == FALSE) { merr_raise (STORE); return 0L; } siz = UDFSVSIZ; if (siz % 1024) siz = (siz & ~01777) + 02000; /* round for full kB; */ siz += 01777; dif = siz - UDFSVSIZ; if (newusize (siz)) { merr_raise (STORE); return 0L; } return dif; } /* end getumore */ /******************************************************************************/ long getrmore (void) { /* try to get more routine space. returns size increment */ long siz, dif; short i; if (autorsize == FALSE) { merr_raise (PGMOV); return 0L; } siz = PSIZE0; if (siz % 1024) siz = (siz & ~01777) + 02000; /* round for full kB; */ siz += 01777; dif = siz - PSIZE0; for (i = 0; i < NO_OF_RBUF; i++) { /* empty routine buffer */ pgms[i][0] = EOL; ages[i] = 0L; } if (newrsize (siz, NO_OF_RBUF)) { merr_raise (PGMOV); return 0L; } return dif; } /* end getrmore */ /******************************************************************************/ short int getnewmore (void) { /* enlarge new_buffers */ char *newbuf; int i; long dif; newbuf = calloc ((unsigned) (NSIZE + 4096), 1); /* new_buffer */ if (newbuf == NULL) { /* could not allocate stuff... */ merr_raise (STKOV); return 1; } stcpy0 (newbuf, newstack, (long) NSIZE); dif = newbuf - newstack; free (newstack); /* free previously allocated space */ newstack = newbuf; NSIZE += 4096; newptr += dif; newlimit = newstack + NSIZE - 1024; i = 0; while (i <= nstx) { if (nestnew[i]) nestnew[i] += dif; i++; } return 0; } /* end getnewmore() */ /******************************************************************************/