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