1: /*
2: * $Id: mref.c,v 1.7 2025/04/10 01:24:38 snw Exp $
3: * supporting functions for handling freem_ref_t structures
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: mref.c,v $
27: * Revision 1.7 2025/04/10 01:24:38 snw
28: * Remove C++ style comments
29: *
30: * Revision 1.6 2025/04/09 15:16:50 snw
31: * Fix buffer overruns in mref_to_external and ssvn.c
32: *
33: * Revision 1.5 2025/03/22 18:43:54 snw
34: * Make STRLEN 255 chars and add BIGSTR macro for larger buffers
35: *
36: * Revision 1.4 2025/03/09 19:50:47 snw
37: * Second phase of REUSE compliance and header reformat
38: *
39: *
40: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
41: * SPDX-License-Identifier: AGPL-3.0-or-later
42: **/
43:
44: #include <stdio.h>
45: #include <stdlib.h>
46: #include <string.h>
47: #include <mpsdef0.h>
48:
49: #include "freem.h"
50:
51: #define MREF_CHECK(ref,index,type) if (ref->status != MREF_ST_INIT || index > 255 || index < 0) return (type) NULL
52: #define MREF_CHECK_EXIT(ref,index,type) if (ref->status != MREF_ST_INIT || index > 255 || index < 0) exit (type) NULL
53:
54: extern short g_numeric (char *str);
55:
56: freem_ref_t *mref_init (freem_ref_t *ref, short ref_type, char *name)
57: {
58: if (strlen (name) > 255) {
59: ref->status = MREF_ST_ERR;
60: return ref;
61: }
62:
63: ref->reftype = ref_type;
64: ref->status = MREF_ST_INIT;
65: strncpy (ref->name, name, 255);
66: ref->subscript_count = 0;
67:
68: return ref;
69: }
70:
71: char *mref_get_name (freem_ref_t *ref)
72: {
73: MREF_CHECK (ref, 0, char *);
74:
75: return ref->name;
76: }
77:
78: char *mref_get_subscript (freem_ref_t *ref, int index)
79: {
80: /* ref must be initialized, and index within range */
81: MREF_CHECK (ref, index, char *);
82:
83: return ref->subscripts[index];
84: }
85:
86: freem_ref_t *mref_set_subscript (freem_ref_t *ref, int index, char *value)
87: {
88: MREF_CHECK (ref, index, freem_ref_t *);
89:
90: if (ref->subscript_count == 0 && index == 0) ref->subscript_count = 1;
91:
92: if (ref->subscript_count < (index + 1)) {
93: ref->subscript_count = index + 1;
94: }
95:
96: strncpy (ref->subscripts[index], value, 255);
97:
98: return ref;
99: }
100:
101: void mref_to_internal_prealloc (char *res, freem_ref_t *ref)
102: {
103: register int i;
104:
105: /* MREF_CHECK (ref, 0, char *); */
106:
107: strncpy (res, ref->name, STRLEN - 1);
108:
109: for (i = 0; i < ref->subscript_count; i++) {
110: strncat (res, "\202", STRLEN - 1);
111: strncat (res, ref->subscripts[i], STRLEN - 1);
112: }
113:
114: strncat (res, "\201", STRLEN - 1);
115: stcnv_c2m (res);
116:
117: }
118:
119: char *mref_to_internal (freem_ref_t *ref)
120: {
121:
122: char *tmp = (char *) malloc (STRLEN * sizeof(char));
123: register int i;
124:
125: MREF_CHECK (ref, 0, char *);
126:
127: strncpy (tmp, ref->name, STRLEN - 1);
128:
129: for (i = 0; i < ref->subscript_count; i++) {
130: strncat (tmp, "\202", STRLEN - 1);
131: strncat (tmp, ref->subscripts[i], STRLEN - 1);
132: }
133:
134: strncat (tmp, "\201", STRLEN - 1);
135: stcnv_c2m (tmp);
136:
137: return tmp;
138: }
139:
140: /* convert a DELIM-delimited, EOL-terminated key to a freem_ref_t* */
141: freem_ref_t *internal_to_mref (freem_ref_t *ref, char *key)
142: {
143: register int i;
144: register int j;
145: char *ptr = key;
146: char ch;
147: char *nam = (char *) malloc (STRLEN * sizeof(char));
148: char *tmp = (char *) malloc (STRLEN * sizeof(char));
149:
150: MREF_CHECK (ref, 0, freem_ref_t *);
151:
152: /* shunt the name into ref->name */
153: i = 0;
154: while ((ch = *(ptr++)) != DELIM && ch != EOL) {
155: nam[i++] = ch;
156: }
157:
158: nam[i] = '\0';
159:
160: if (nam[0] == '^') {
161:
162: if (nam[1] == '$') {
163: ref->reftype = MREF_RT_SSVN;
164: }
165: else {
166: ref->reftype = MREF_RT_GLOBAL;
167: }
168:
169: }
170: else {
171: ref->reftype = MREF_RT_LOCAL;
172: }
173:
174: strncpy (ref->name, nam, STRLEN);
175:
176: /* if no subscripts, return the ref */
177: if (*(ptr - 1) == EOL) {
178: ref->subscript_count = 0;
179:
180: free (nam);
181: free (tmp);
182:
183: return ref;
184: }
185:
186:
187: /* grab the subscripts */
188: i = 0;
189: j = 0;
190: while ((ch = *(ptr++)) != EOL) {
191:
192: switch (ch) {
193:
194: case '\001':
195: break;
196: case DELIM:
197:
198: tmp[j] = '\0';
199:
200: mref_set_subscript (ref, i++, tmp);
201: ref->subscript_count++;
202:
203: j = 0;
204: tmp[j] = '\0';
205:
206: break;
207:
208:
209: default:
210: tmp[j++] = ch;
211:
212: }
213:
214: }
215:
216: tmp[j] = '\0';
217:
218: /* grab the last one */
219: mref_set_subscript (ref, i, tmp);
220:
221: free (nam);
222: free (tmp);
223:
224: return ref;
225:
226: }
227:
228: void mref_to_external (freem_ref_t *ref, char *buf)
229: {
230: register int i;
231: register int j;
232: short is_numeric = FALSE;
233: short is_ref = FALSE;
234: char *t_buf = (char *) malloc (STRLEN * sizeof (char));
235: NULLPTRCHK(t_buf,"mref_to_external");
236:
237: strcpy (buf, ref->name);
238:
239: if (ref->subscript_count) {
240:
241: strcat (buf, "(");
242:
243:
244: for (i = 0; i < ref->subscript_count; i++) {
245:
246: if (ref->subscripts[i][0] == '.') {
247: is_ref = TRUE;
248: }
249: else {
250: is_ref = FALSE;
251: }
252:
253: strcpy (t_buf, ref->subscripts[i]);
254:
255: for (j = 0; j < strlen (t_buf); j++) {
256: if (t_buf[j] == '\001') t_buf[j] = '\201';
257: }
258:
259: stcnv_c2m (t_buf);
260:
261: is_numeric = numeric (t_buf);
262:
263:
264: if (!is_numeric && !is_ref) strcat (buf, "\"");
265:
266: for (j = 0; j < strlen (ref->subscripts[i]); j++) {
267: if (ref->subscripts[i][j] == '\001') ref->subscripts[i][j] = '\201';
268: }
269: strcat (buf, ref->subscripts[i]);
270: if (!is_numeric && !is_ref) strcat (buf, "\"");
271:
272: if (i < (ref->subscript_count - 1)) {
273: strcat (buf, ",");
274: }
275:
276: }
277: stncnv_m2c (buf, STRLEN);
278:
279: strcat (buf, ")");
280:
281: }
282:
283: free (t_buf);
284: return;
285:
286: }
287:
288: /* returns TRUE if b is a descendant of a */
289: short mref_is_descendant(freem_ref_t *a, freem_ref_t *b)
290: {
291: register int i;
292:
293: if (a->subscript_count > b->subscript_count) return FALSE;
294: if ((strcmp (a->name, b->name) == 0) && (a->subscript_count == 0)) return TRUE;
295:
296:
297: for (i = 0; i < a->subscript_count; i++) {
298: if (strcmp (b->subscripts[i], a->subscripts[i]) != 0 ) {
299:
300: return FALSE;
301: }
302: }
303:
304: return TRUE;
305: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>