File:  [Coherent Logic Development] / freem / src / mlib.c
Revision 1.4: download - view: text, annotated - select for diffs
Mon Mar 24 04:13:11 2025 UTC (8 days, 19 hours ago) by snw
Branches: MAIN
CVS tags: v0-62-3, HEAD
Replace action macro dat with fra_dat to avoid symbol conflict on OS/2

/*
 *   $Id: mlib.c,v 1.4 2025/03/24 04:13:11 snw Exp $
 *    Function prototypes, structs, and macros for FreeM
 *    binding library
 *
 *  
 *   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: mlib.c,v $
 *   Revision 1.4  2025/03/24 04:13:11  snw
 *   Replace action macro dat with fra_dat to avoid symbol conflict on OS/2
 *
 *   Revision 1.3  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 <stdlib.h>

#include "mpsdef.h"
#include "freem.h"
#include "init.h"
#include "transact.h"
#include "version.h"

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>

/* the following function prototypes are not in freem.h, as they are intended to be
 * private and internal to mlib.c
 */
void mref2str(freem_ref_t *ref, char *key);
void freem_release_io(void);
void freem_return_io(void);

extern int xecline(int typ);

void mref2str(freem_ref_t *ref, char *key)
{
    register int i;

    for (i = 0; i < 256; i++) key[i] = NUL;

    switch (ref->reftype) {

        case MREF_RT_LOCAL: /* do nothing for locals, as they have no sigil */
            break;

        case MREF_RT_GLOBAL:
            strcat (key, "^");
            break;

        case MREF_RT_SSVN:
            strcat (key, "^$");
            break;

    }

    if (ref->subscript_count > 0) {
        strcat (key, ref->name);
        strcat (key, "\202");

    	for (i = 0; i < ref->subscript_count; i++) {
            strcat (key, ref->subscripts[i]);
    		
            if (i < ref->subscript_count - 1) strcat (key, "\202");
    	}
    }
    else {
        strcat (key, ref->name);
    }

    // ends with EOL
    strncat (key, "\201", 2);

}

pid_t freem_init(char *environment_name, char *namespace_name)
{
    int ierr_sav;
    int errno_sav;

    libflag = TRUE;
    noclear = TRUE;
    frm_filter = TRUE;
    direct_mode = FALSE;
    
    errno = 0;
    
    strcpy (shm_env, environment_name);
    snprintf (config_file, 4096, "%s/freem/%s/freem.conf", SYSCONFDIR, shm_env);
    
    init (namespace_name);
    ierr_sav = ierr;
    errno_sav = errno;
    
    freem_release_io ();


    if (ierr_sav > OK || errno_sav != 0) {
        return -1;
    }
    else {
        return pid;
    }
}

short freem_version(char *result)
{
    strncpy (result, FREEM_VERSION_ID, 255);

    return OK;
}

short freem_get(freem_ref_t *ref) 
{
    char key[256];
    char result[256];

    freem_return_io ();

    // set up the EOL-delimited string
    mref2str (ref, key);

    switch (ref->reftype) {
    	
    	case MREF_RT_LOCAL:
            // call into the symbol table to get the local var
            symtab (get_sym, key, result);
            ref->status = merr ();
            break;
    	
    	case MREF_RT_GLOBAL:
            // call into the FreeM global handler; result in &result
            global (get_sym, key, result);
            ref->status = merr ();
            break;

    	case MREF_RT_SSVN:
            // call into the SSVN code
            ssvn (get_sym, key, result);
            ref->status = merr ();
            break;

    }
    
    stcnv_m2c (result);

    strncpy (ref->value, result, 255);

    freem_release_io ();
    
    return ref->status;
}

short freem_set(freem_ref_t *ref) 
{
    char key[256];
    char data[256];

    freem_return_io ();

    mref2str (ref, key);

    snprintf (data, 254, "%s\201", ref->value);

    switch (ref->reftype) {

        case MREF_RT_LOCAL:
            // call into the symbol table to set the local var
            symtab (set_sym, key, data);
            ref->status = merr ();
            break;
    	
    	case MREF_RT_GLOBAL:
            // call into the FreeM global handler; data in &data
            global (set_sym, key, data);
            ref->status = merr ();
            break;

    	case MREF_RT_SSVN:
            // call into the SSVN code
            ssvn (set_sym, key, data);
            ref->status = merr ();
            break;

    }

    freem_release_io ();


    return ref->status;
}

short freem_kill(freem_ref_t *ref) 
{
    char key[256];
    char result[256];

    mref2str (ref, key);

    freem_return_io ();

    switch (ref->reftype) {
    	
    	case MREF_RT_LOCAL:
            // call into the symbol table to kill the local var
            symtab (kill_sym, key, result);
            ref->status = merr ();
            break;
    	
    	case MREF_RT_GLOBAL:
            // call into the FreeM global handler; result in &result
            global (kill_sym, key, result);
            ref->status = merr ();
            break;

    	case MREF_RT_SSVN:
            // call into the SSVN code
            ssvn (kill_sym, key, result);
            ref->status = merr ();
            break;

    }

    stcnv_m2c (result);

    strncpy (ref->value, result, 255);

    freem_release_io ();
    

    return ref->status;
}

short freem_data(freem_ref_t *ref) 
{
    char key[256];
    char result[256];

    mref2str (ref, key);

    freem_return_io ();

    switch (ref->reftype) {
        
        case MREF_RT_LOCAL:
            // call into the symbol table
            symtab (fra_dat, key, result);
            ref->status = merr ();
            break;
        
        case MREF_RT_GLOBAL:
            // call into the FreeM global handler; result in &result
            global (fra_dat, key, result);
            ref->status = merr ();
            break;

        case MREF_RT_SSVN:
            // call into the SSVN code
            ssvn (fra_dat, key, result);
            ref->status = merr ();
            break;

    }

    stcnv_m2c (result);

    strncpy (ref->value, result, 255);

    freem_release_io ();

    return ref->status;
}

short freem_order(freem_ref_t *ref) 
{
    char key[256];
    char result[256];

    mref2str (ref, key);

    freem_return_io ();

    switch (ref->reftype) {
        
        case MREF_RT_LOCAL:
            // call into the symbol table for $ORDER
            symtab (fra_order, key, result);
            ref->status = merr ();
            break;
        
        case MREF_RT_GLOBAL:
            // call into the FreeM global handler; result in &result
            global (fra_order, key, result);
            ref->status = merr ();
            break;

        case MREF_RT_SSVN:
            // call into the SSVN code
            ssvn (fra_order, key, result);
            ref->status = merr ();
            break;

    }

    stcnv_m2c (result);

    strncpy (ref->value, result, 255);
    freem_release_io ();

    return ref->status;
}

short freem_query(freem_ref_t *ref) 
{
    char key[256];
    char result[256];

    mref2str (ref, key);

    freem_return_io ();

    switch (ref->reftype) {
        
        case MREF_RT_LOCAL:
            // call into the symbol table
            symtab (fra_query, key, result);
            ref->status = merr ();
            break;
        
        case MREF_RT_GLOBAL:
            // call into the FreeM global handler; result in &result
            global (fra_query, key, result);
            ref->status = merr ();
            break;

        case MREF_RT_SSVN:
            // call into the SSVN code
            ssvn (fra_query, key, result);
            ref->status = merr ();
            break;

    }

    stcnv_m2c (result);

    strncpy (ref->value, result, 255);

    freem_release_io ();

    return ref->status;
}

short freem_lock(freem_ref_t *ref, long lck_timeout)
{
    char key[256];
    char buf[256];

    mref2str (ref, key);
    snprintf (buf, 255, "+%s\201", key);

    freem_return_io ();

    lock (buf, lck_timeout, 'l');
    ref->status = merr ();

    freem_release_io ();

    return ref->status;
}

short freem_unlock(freem_ref_t *ref, long lck_timeout) 
{
    char key[256];
    char buf[256];

    mref2str (ref, key);
    snprintf (buf, 255, "-%s\201", key);

    freem_return_io ();

    lock (buf, lck_timeout, 'l');
    ref->status = merr ();

    freem_release_io ();

    return ref->status;
}

short freem_tstart(char *tp_id, short serial, short restartable, char **sym_save)
{
    return tp_tstart (tp_id, serial, restartable, sym_save);
}

short freem_trestart(void)
{
    return tp_trestart ();
}

short freem_trollback(int tp_levels)
{
    return tp_trollback (tp_levels);
}

short freem_tcommit(void)
{
    return tp_tcommit ();
}

int freem_tlevel(void)
{
    return tp_level;
}

short freem_function(freem_ent_t *ent)
{
    register int i;
    char buf[STRLEN] = {0};
    char tmp[STRLEN] = {0};
    char tmp1[STRLEN] = {0};

    freem_return_io ();

    if (ent->argument_count > 0) {
        snprintf (buf, STRLEN - 1, "S %%ZFRMRTN=$$%s(", ent->name);

        for (i = 0; i < ent->argument_count; i++) {

            strncpy (tmp1, ent->arguments[i], STRLEN - 1);
            stcnv_c2m (tmp1);

            if (znamenumeric (tmp1) == TRUE) {
                /* arguments that are canonical MUMPS numbers don't get quoted */
                snprintf (tmp, STRLEN - 1, "%s", ent->arguments[i]);
            }
            else {
                /* string arguments do get quoted */
                snprintf (tmp, STRLEN - 1, "\"%s\"", ent->arguments[i]);
            }

            strcat (buf, tmp);

            if(i < ent->argument_count - 1) {
                strcat (buf, ",");
            }
        }

        strcat (buf, ")");
    }
    else {
        snprintf (buf, STRLEN - 1, "S %%ZFRMRTN=$$%s", ent->name);
    }

    stcnv_c2m (buf);
    sprintf (tmp, "%%ZFRMXEC\201");
    symtab (set_sym, tmp, buf);
    snprintf ((char *) ztrap, 12, "^%%ZFRMXEC\201");

    xecline (3);
    ent->status = merr ();

    tmp[0] = NUL;
    ent->value[0] = NUL;

    snprintf (tmp, 255, "%%ZFRMRTN\201");
    symtab (get_sym, tmp, ent->value);
    stcnv_m2c (ent->value);

    freem_release_io ();

    return ent->status;
}

short freem_procedure(freem_ent_t *ent)
{
    register int i;
    char buf[STRLEN] = {0};
    char tmp[STRLEN] = {0};
    char tmp1[STRLEN] = {0};

    freem_return_io ();

    if (ent->argument_count > 0) {
        snprintf (buf, STRLEN - 1, "DO %s(", ent->name);

        for (i = 0; i < ent->argument_count; i++) {

            strncpy (tmp1, ent->arguments[i], STRLEN - 1);
            stcnv_c2m (tmp1);

            if (znamenumeric (tmp1) == TRUE) {
                /* arguments that are canonical MUMPS numbers don't get quoted */
                snprintf (tmp, STRLEN - 1, "%s", ent->arguments[i]);
            }
            else {
                /* string arguments do get quoted */
                snprintf (tmp, STRLEN - 1, "\"%s\"", ent->arguments[i]);
            }

            strcat (buf, tmp);

            if(i < ent->argument_count - 1) {
                strcat (buf, ",");
            }
        }

        strcat (buf, ")");
    }
    else {
        snprintf (buf, STRLEN - 1, "DO %s", ent->name);
    }

    stcnv_c2m (buf);
    sprintf (tmp, "%%ZFRMXEC\201");
    symtab (set_sym, tmp, buf);
    

    snprintf ((char *) ztrap, 12, "^%%ZFRMXEC\201");


    xecline (3);
    ent->status = merr ();

    tmp[0] = NUL;
    ent->value[0] = NUL;

    freem_release_io ();

    return ent->status;
}

short freem_errmsg(int code, char *msg)
{
    char emtmp[256];
    char cvtmp[256];
    
    if (code > MAXERR || code < 0) {
        return FALSE;
    }

    stcpy (cvtmp, errmes[code]);
    stcnv_m2c (cvtmp);

    merr_num_to_code (code, emtmp);

    sprintf (msg, "%s: %s", emtmp, cvtmp); 
    
    return TRUE;
}

void freem_release_io(void)
{
    set_io (UNIX);
}

void freem_return_io(void)
{
    set_io (MUMPS);
}

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>