File:  [Coherent Logic Development] / freem / src / mref.c
Revision 1.5: download - view: text, annotated - select for diffs
Sat Mar 22 18:43:54 2025 UTC (10 days, 5 hours ago) by snw
Branches: MAIN
CVS tags: v0-62-3, v0-62-2, HEAD
Make STRLEN 255 chars and add BIGSTR macro for larger buffers

/*
 *   $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>