1: /*
2: * $Id: mlib.c,v 1.6 2025/04/13 04:22:43 snw Exp $
3: * Function prototypes, structs, and macros for FreeM
4: * binding library
5: *
6: *
7: * Author: Serena Willis <snw@coherent-logic.com>
8: * Copyright (C) 1998 MUG Deutschland
9: * Copyright (C) 2020, 2025 Coherent Logic Development LLC
10: *
11: *
12: * This file is part of FreeM.
13: *
14: * FreeM is free software: you can redistribute it and/or modify
15: * it under the terms of the GNU Affero Public License as published by
16: * the Free Software Foundation, either version 3 of the License, or
17: * (at your option) any later version.
18: *
19: * FreeM is distributed in the hope that it will be useful,
20: * but WITHOUT ANY WARRANTY; without even the implied warranty of
21: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22: * GNU Affero Public License for more details.
23: *
24: * You should have received a copy of the GNU Affero Public License
25: * along with FreeM. If not, see <https://www.gnu.org/licenses/>.
26: *
27: * $Log: mlib.c,v $
28: * Revision 1.6 2025/04/13 04:22:43 snw
29: * Fix snprintf calls
30: *
31: * Revision 1.5 2025/04/10 01:24:38 snw
32: * Remove C++ style comments
33: *
34: * Revision 1.4 2025/03/24 04:13:11 snw
35: * Replace action macro dat with fra_dat to avoid symbol conflict on OS/2
36: *
37: * Revision 1.3 2025/03/09 19:50:47 snw
38: * Second phase of REUSE compliance and header reformat
39: *
40: *
41: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
42: * SPDX-License-Identifier: AGPL-3.0-or-later
43: **/
44:
45: #include <stdlib.h>
46:
47: #include "mpsdef.h"
48: #include "freem.h"
49: #include "init.h"
50: #include "transact.h"
51: #include "version.h"
52:
53: #include <stdio.h>
54: #include <ctype.h>
55: #include <string.h>
56: #include <errno.h>
57:
58: /* the following function prototypes are not in freem.h, as they are intended to be
59: * private and internal to mlib.c
60: */
61: void mref2str(freem_ref_t *ref, char *key);
62: void freem_release_io(void);
63: void freem_return_io(void);
64:
65: extern int xecline(int typ);
66:
67: void mref2str(freem_ref_t *ref, char *key)
68: {
69: register int i;
70:
71: for (i = 0; i < 256; i++) key[i] = NUL;
72:
73: switch (ref->reftype) {
74:
75: case MREF_RT_LOCAL: /* do nothing for locals, as they have no sigil */
76: break;
77:
78: case MREF_RT_GLOBAL:
79: strcat (key, "^");
80: break;
81:
82: case MREF_RT_SSVN:
83: strcat (key, "^$");
84: break;
85:
86: }
87:
88: if (ref->subscript_count > 0) {
89: strcat (key, ref->name);
90: strcat (key, "\202");
91:
92: for (i = 0; i < ref->subscript_count; i++) {
93: strcat (key, ref->subscripts[i]);
94:
95: if (i < ref->subscript_count - 1) strcat (key, "\202");
96: }
97: }
98: else {
99: strcat (key, ref->name);
100: }
101:
102: /* ends with EOL */
103: strncat (key, "\201", 2);
104:
105: }
106:
107: pid_t freem_init(char *environment_name, char *namespace_name)
108: {
109: int ierr_sav;
110: int errno_sav;
111:
112: libflag = TRUE;
113: noclear = TRUE;
114: frm_filter = TRUE;
115: direct_mode = FALSE;
116:
117: errno = 0;
118:
119: strcpy (shm_env, environment_name);
120: snprintf (config_file, sizeof (config_file) - 1, "%s/freem/%s/freem.conf", SYSCONFDIR, shm_env);
121:
122: init (namespace_name);
123: ierr_sav = ierr;
124: errno_sav = errno;
125:
126: freem_release_io ();
127:
128:
129: if (ierr_sav > OK || errno_sav != 0) {
130: return -1;
131: }
132: else {
133: return pid;
134: }
135: }
136:
137: short freem_version(char *result)
138: {
139: strncpy (result, FREEM_VERSION_ID, 255);
140:
141: return OK;
142: }
143:
144: short freem_get(freem_ref_t *ref)
145: {
146: char key[256];
147: char result[256];
148:
149: freem_return_io ();
150:
151: /* set up the EOL-delimited string */
152: mref2str (ref, key);
153:
154: switch (ref->reftype) {
155:
156: case MREF_RT_LOCAL:
157: /* call into the symbol table to get the local var */
158: symtab (get_sym, key, result);
159: ref->status = merr ();
160: break;
161:
162: case MREF_RT_GLOBAL:
163: /* call into the FreeM global handler; result in &result */
164: global (get_sym, key, result);
165: ref->status = merr ();
166: break;
167:
168: case MREF_RT_SSVN:
169: /* call into the SSVN code */
170: ssvn (get_sym, key, result);
171: ref->status = merr ();
172: break;
173:
174: }
175:
176: stcnv_m2c (result);
177:
178: strncpy (ref->value, result, sizeof (ref->value));
179:
180: freem_release_io ();
181:
182: return ref->status;
183: }
184:
185: short freem_set(freem_ref_t *ref)
186: {
187: char key[256];
188: char data[256];
189:
190: freem_return_io ();
191:
192: mref2str (ref, key);
193:
194: snprintf (data, sizeof (data) - 1, "%s\201", ref->value);
195:
196: switch (ref->reftype) {
197:
198: case MREF_RT_LOCAL:
199: /* call into the symbol table to set the local var */
200: symtab (set_sym, key, data);
201: ref->status = merr ();
202: break;
203:
204: case MREF_RT_GLOBAL:
205: /* call into the FreeM global handler; data in &data */
206: global (set_sym, key, data);
207: ref->status = merr ();
208: break;
209:
210: case MREF_RT_SSVN:
211: /* call into the SSVN code */
212: ssvn (set_sym, key, data);
213: ref->status = merr ();
214: break;
215:
216: }
217:
218: freem_release_io ();
219:
220:
221: return ref->status;
222: }
223:
224: short freem_kill(freem_ref_t *ref)
225: {
226: char key[256];
227: char result[256];
228:
229: mref2str (ref, key);
230:
231: freem_return_io ();
232:
233: switch (ref->reftype) {
234:
235: case MREF_RT_LOCAL:
236: /* call into the symbol table to kill the local var */
237: symtab (kill_sym, key, result);
238: ref->status = merr ();
239: break;
240:
241: case MREF_RT_GLOBAL:
242: /* call into the FreeM global handler; result in &result */
243: global (kill_sym, key, result);
244: ref->status = merr ();
245: break;
246:
247: case MREF_RT_SSVN:
248: /* call into the SSVN code */
249: ssvn (kill_sym, key, result);
250: ref->status = merr ();
251: break;
252:
253: }
254:
255: stcnv_m2c (result);
256:
257: strncpy (ref->value, result, sizeof (ref->value) - 1);
258:
259: freem_release_io ();
260:
261:
262: return ref->status;
263: }
264:
265: short freem_data(freem_ref_t *ref)
266: {
267: char key[256];
268: char result[256];
269:
270: mref2str (ref, key);
271:
272: freem_return_io ();
273:
274: switch (ref->reftype) {
275:
276: case MREF_RT_LOCAL:
277: /* call into the symbol table */
278: symtab (fra_dat, key, result);
279: ref->status = merr ();
280: break;
281:
282: case MREF_RT_GLOBAL:
283: /* call into the FreeM global handler; result in &result */
284: global (fra_dat, key, result);
285: ref->status = merr ();
286: break;
287:
288: case MREF_RT_SSVN:
289: /* call into the SSVN code */
290: ssvn (fra_dat, key, result);
291: ref->status = merr ();
292: break;
293:
294: }
295:
296: stcnv_m2c (result);
297:
298: strncpy (ref->value, result, 255);
299:
300: freem_release_io ();
301:
302: return ref->status;
303: }
304:
305: short freem_order(freem_ref_t *ref)
306: {
307: char key[256];
308: char result[256];
309:
310: mref2str (ref, key);
311:
312: freem_return_io ();
313:
314: switch (ref->reftype) {
315:
316: case MREF_RT_LOCAL:
317: /* call into the symbol table for $ORDER */
318: symtab (fra_order, key, result);
319: ref->status = merr ();
320: break;
321:
322: case MREF_RT_GLOBAL:
323: /* call into the FreeM global handler; result in &result */
324: global (fra_order, key, result);
325: ref->status = merr ();
326: break;
327:
328: case MREF_RT_SSVN:
329: /* call into the SSVN code */
330: ssvn (fra_order, key, result);
331: ref->status = merr ();
332: break;
333:
334: }
335:
336: stcnv_m2c (result);
337:
338: strncpy (ref->value, result, 255);
339: freem_release_io ();
340:
341: return ref->status;
342: }
343:
344: short freem_query(freem_ref_t *ref)
345: {
346: char key[256];
347: char result[256];
348:
349: mref2str (ref, key);
350:
351: freem_return_io ();
352:
353: switch (ref->reftype) {
354:
355: case MREF_RT_LOCAL:
356: /* call into the symbol table */
357: symtab (fra_query, key, result);
358: ref->status = merr ();
359: break;
360:
361: case MREF_RT_GLOBAL:
362: /* call into the FreeM global handler; result in &result */
363: global (fra_query, key, result);
364: ref->status = merr ();
365: break;
366:
367: case MREF_RT_SSVN:
368: /* call into the SSVN code */
369: ssvn (fra_query, key, result);
370: ref->status = merr ();
371: break;
372:
373: }
374:
375: stcnv_m2c (result);
376:
377: strncpy (ref->value, result, 255);
378:
379: freem_release_io ();
380:
381: return ref->status;
382: }
383:
384: short freem_lock(freem_ref_t *ref, long lck_timeout)
385: {
386: char key[256];
387: char buf[256];
388:
389: mref2str (ref, key);
390: snprintf (buf, sizeof (buf) - 1, "+%s\201", key);
391:
392: freem_return_io ();
393:
394: lock (buf, lck_timeout, 'l');
395: ref->status = merr ();
396:
397: freem_release_io ();
398:
399: return ref->status;
400: }
401:
402: short freem_unlock(freem_ref_t *ref, long lck_timeout)
403: {
404: char key[256];
405: char buf[256];
406:
407: mref2str (ref, key);
408: snprintf (buf, sizeof (buf) - 1, "-%s\201", key);
409:
410: freem_return_io ();
411:
412: lock (buf, lck_timeout, 'l');
413: ref->status = merr ();
414:
415: freem_release_io ();
416:
417: return ref->status;
418: }
419:
420: short freem_tstart(char *tp_id, short serial, short restartable, char **sym_save)
421: {
422: return tp_tstart (tp_id, serial, restartable, sym_save);
423: }
424:
425: short freem_trestart(void)
426: {
427: return tp_trestart ();
428: }
429:
430: short freem_trollback(int tp_levels)
431: {
432: return tp_trollback (tp_levels);
433: }
434:
435: short freem_tcommit(void)
436: {
437: return tp_tcommit ();
438: }
439:
440: int freem_tlevel(void)
441: {
442: return tp_level;
443: }
444:
445: short freem_function(freem_ent_t *ent)
446: {
447: register int i;
448: char buf[STRLEN] = {0};
449: char tmp[STRLEN] = {0};
450: char tmp1[STRLEN] = {0};
451:
452: freem_return_io ();
453:
454: if (ent->argument_count > 0) {
455: snprintf (buf, STRLEN - 1, "S %%ZFRMRTN=$$%s(", ent->name);
456:
457: for (i = 0; i < ent->argument_count; i++) {
458:
459: strncpy (tmp1, ent->arguments[i], STRLEN - 1);
460: stcnv_c2m (tmp1);
461:
462: if (znamenumeric (tmp1) == TRUE) {
463: /* arguments that are canonical MUMPS numbers don't get quoted */
464: snprintf (tmp, STRLEN - 1, "%s", ent->arguments[i]);
465: }
466: else {
467: /* string arguments do get quoted */
468: snprintf (tmp, STRLEN - 1, "\"%s\"", ent->arguments[i]);
469: }
470:
471: strcat (buf, tmp);
472:
473: if(i < ent->argument_count - 1) {
474: strcat (buf, ",");
475: }
476: }
477:
478: strcat (buf, ")");
479: }
480: else {
481: snprintf (buf, STRLEN - 1, "S %%ZFRMRTN=$$%s", ent->name);
482: }
483:
484: stcnv_c2m (buf);
485: sprintf (tmp, "%%ZFRMXEC\201");
486: symtab (set_sym, tmp, buf);
487: snprintf ((char *) ztrap, ZTLEN - 1, "^%%ZFRMXEC\201");
488:
489: xecline (3);
490: ent->status = merr ();
491:
492: tmp[0] = NUL;
493: ent->value[0] = NUL;
494:
495: snprintf (tmp, sizeof (tmp) - 1, "%%ZFRMRTN\201");
496: symtab (get_sym, tmp, ent->value);
497: stcnv_m2c (ent->value);
498:
499: freem_release_io ();
500:
501: return ent->status;
502: }
503:
504: short freem_procedure(freem_ent_t *ent)
505: {
506: register int i;
507: char buf[STRLEN] = {0};
508: char tmp[STRLEN] = {0};
509: char tmp1[STRLEN] = {0};
510:
511: freem_return_io ();
512:
513: if (ent->argument_count > 0) {
514: snprintf (buf, STRLEN - 1, "DO %s(", ent->name);
515:
516: for (i = 0; i < ent->argument_count; i++) {
517:
518: strncpy (tmp1, ent->arguments[i], STRLEN - 1);
519: stcnv_c2m (tmp1);
520:
521: if (znamenumeric (tmp1) == TRUE) {
522: /* arguments that are canonical MUMPS numbers don't get quoted */
523: snprintf (tmp, STRLEN - 1, "%s", ent->arguments[i]);
524: }
525: else {
526: /* string arguments do get quoted */
527: snprintf (tmp, STRLEN - 1, "\"%s\"", ent->arguments[i]);
528: }
529:
530: strcat (buf, tmp);
531:
532: if(i < ent->argument_count - 1) {
533: strcat (buf, ",");
534: }
535: }
536:
537: strcat (buf, ")");
538: }
539: else {
540: snprintf (buf, STRLEN - 1, "DO %s", ent->name);
541: }
542:
543: stcnv_c2m (buf);
544: sprintf (tmp, "%%ZFRMXEC\201");
545: symtab (set_sym, tmp, buf);
546:
547:
548: snprintf ((char *) ztrap, ZTLEN - 1, "^%%ZFRMXEC\201");
549:
550:
551: xecline (3);
552: ent->status = merr ();
553:
554: tmp[0] = NUL;
555: ent->value[0] = NUL;
556:
557: freem_release_io ();
558:
559: return ent->status;
560: }
561:
562: short freem_errmsg(int code, char *msg)
563: {
564: char emtmp[256];
565: char cvtmp[256];
566:
567: if (code > MAXERR || code < 0) {
568: return FALSE;
569: }
570:
571: stcpy (cvtmp, errmes[code]);
572: stcnv_m2c (cvtmp);
573:
574: merr_num_to_code (code, emtmp);
575:
576: sprintf (msg, "%s: %s", emtmp, cvtmp);
577:
578: return TRUE;
579: }
580:
581: void freem_release_io(void)
582: {
583: set_io (UNIX);
584: }
585:
586: void freem_return_io(void)
587: {
588: set_io (MUMPS);
589: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>