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