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