/*
* $Id: mref.c,v 1.5 2025/03/22 18:43:54 snw Exp $
* supporting functions for handling freem_ref_t structures
*
*
* Author: Serena Willis <snw@coherent-logic.com>
* Copyright (C) 1998 MUG Deutschland
* Copyright (C) 2020, 2025 Coherent Logic Development LLC
*
*
* This file is part of FreeM.
*
* FreeM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FreeM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero Public License for more details.
*
* You should have received a copy of the GNU Affero Public License
* along with FreeM. If not, see <https://www.gnu.org/licenses/>.
*
* $Log: mref.c,v $
* Revision 1.5 2025/03/22 18:43:54 snw
* Make STRLEN 255 chars and add BIGSTR macro for larger buffers
*
* Revision 1.4 2025/03/09 19:50:47 snw
* Second phase of REUSE compliance and header reformat
*
*
* SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
* SPDX-License-Identifier: AGPL-3.0-or-later
**/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mpsdef0.h>
#include "freem.h"
#define MREF_CHECK(ref,index,type) if (ref->status != MREF_ST_INIT || index > 255 || index < 0) return (type) NULL
#define MREF_CHECK_EXIT(ref,index,type) if (ref->status != MREF_ST_INIT || index > 255 || index < 0) exit (type) NULL
extern short g_numeric (char *str);
freem_ref_t *mref_init (freem_ref_t *ref, short ref_type, char *name)
{
if (strlen (name) > 255) {
ref->status = MREF_ST_ERR;
return ref;
}
ref->reftype = ref_type;
ref->status = MREF_ST_INIT;
strncpy (ref->name, name, 255);
ref->subscript_count = 0;
return ref;
}
char *mref_get_name (freem_ref_t *ref)
{
MREF_CHECK (ref, 0, char *);
return ref->name;
}
char *mref_get_subscript (freem_ref_t *ref, int index)
{
/* ref must be initialized, and index within range */
MREF_CHECK (ref, index, char *);
return ref->subscripts[index];
}
freem_ref_t *mref_set_subscript (freem_ref_t *ref, int index, char *value)
{
MREF_CHECK (ref, index, freem_ref_t *);
if (ref->subscript_count == 0 && index == 0) ref->subscript_count = 1;
if (ref->subscript_count < (index + 1)) {
ref->subscript_count = index + 1;
}
strncpy (ref->subscripts[index], value, 255);
return ref;
}
void mref_to_internal_prealloc (char *res, freem_ref_t *ref)
{
register int i;
/* MREF_CHECK (ref, 0, char *); */
strncpy (res, ref->name, STRLEN - 1);
for (i = 0; i < ref->subscript_count; i++) {
strncat (res, "\202", STRLEN - 1);
strncat (res, ref->subscripts[i], STRLEN - 1);
}
strncat (res, "\201", STRLEN - 1);
stcnv_c2m (res);
}
char *mref_to_internal (freem_ref_t *ref)
{
char *tmp = (char *) malloc (STRLEN * sizeof(char));
register int i;
MREF_CHECK (ref, 0, char *);
strncpy (tmp, ref->name, STRLEN - 1);
for (i = 0; i < ref->subscript_count; i++) {
strncat (tmp, "\202", STRLEN - 1);
strncat (tmp, ref->subscripts[i], STRLEN - 1);
}
strncat (tmp, "\201", STRLEN - 1);
stcnv_c2m (tmp);
return tmp;
}
/* convert a DELIM-delimited, EOL-terminated key to a freem_ref_t* */
freem_ref_t *internal_to_mref (freem_ref_t *ref, char *key)
{
register int i;
register int j;
char *ptr = key;
char ch;
char *nam = (char *) malloc (STRLEN * sizeof(char));
char *tmp = (char *) malloc (STRLEN * sizeof(char));
MREF_CHECK (ref, 0, freem_ref_t *);
/* shunt the name into ref->name */
i = 0;
while ((ch = *(ptr++)) != DELIM && ch != EOL) {
nam[i++] = ch;
}
nam[i] = '\0';
if (nam[0] == '^') {
if (nam[1] == '$') {
ref->reftype = MREF_RT_SSVN;
}
else {
ref->reftype = MREF_RT_GLOBAL;
}
}
else {
ref->reftype = MREF_RT_LOCAL;
}
strncpy (ref->name, nam, STRLEN);
/* if no subscripts, return the ref */
if (*(ptr - 1) == EOL) {
ref->subscript_count = 0;
free (nam);
free (tmp);
return ref;
}
/* grab the subscripts */
i = 0;
j = 0;
while ((ch = *(ptr++)) != EOL) {
switch (ch) {
case '\001':
break;
case DELIM:
tmp[j] = '\0';
mref_set_subscript (ref, i++, tmp);
ref->subscript_count++;
j = 0;
tmp[j] = '\0';
break;
default:
tmp[j++] = ch;
}
}
tmp[j] = '\0';
/* grab the last one */
mref_set_subscript (ref, i, tmp);
free (nam);
free (tmp);
return ref;
}
void mref_to_external (freem_ref_t *ref, char *buf)
{
register int i;
register int j;
short is_numeric = FALSE;
short is_ref = FALSE;
char *t_buf = (char *) malloc (STRLEN * sizeof (char));
NULLPTRCHK(t_buf,"mref_to_external");
strcpy (buf, ref->name);
if (ref->subscript_count) {
strcat (buf, "(");
for (i = 0; i < ref->subscript_count; i++) {
if (ref->subscripts[i][0] == '.') {
is_ref = TRUE;
}
else {
is_ref = FALSE;
}
strcpy (t_buf, ref->subscripts[i]);
for (j = 0; j < strlen (t_buf); j++) {
if (t_buf[j] == '\001') t_buf[j] = '\201';
}
stcnv_c2m (t_buf);
is_numeric = numeric (t_buf);
if (!is_numeric && !is_ref) strcat (buf, "\"");
for (j = 0; j < strlen (ref->subscripts[i]); j++) {
if (ref->subscripts[i][j] == '\001') ref->subscripts[i][j] = '\201';
}
strcat (buf, ref->subscripts[i]);
if (!is_numeric && !is_ref) strcat (buf, "\"");
if (i < (ref->subscript_count - 1)) {
strcat (buf, ",");
}
}
stcnv_m2c (buf);
strcat (buf, ")");
}
free (t_buf);
return;
}
/* returns TRUE if b is a descendant of a */
short mref_is_descendant(freem_ref_t *a, freem_ref_t *b)
{
register int i;
//printf ("checking if %s is a descendant of %s\r\n", b->name, a->name);
//printf ("a: %d b: %d\r\n", a->subscript_count, b->subscript_count);
if (a->subscript_count > b->subscript_count) return FALSE;
if ((strcmp (a->name, b->name) == 0) && (a->subscript_count == 0)) return TRUE;
for (i = 0; i < a->subscript_count; i++) {
//printf("\ta[%d] = '%s'\r\n\tb[%d] = '%s'\r\n", i, a->subscripts[i], i, b->subscripts[i]);
if (strcmp (b->subscripts[i], a->subscripts[i]) != 0 ) {
//printf ("not descendant [%d]\r\n", strcmp (b->subscripts[i], a->subscripts[i]));
return FALSE;
}
}
//printf ("is descendant\r\n");
return TRUE;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>