/*
* $Id: merr.c,v 1.3 2025/03/09 19:50:47 snw Exp $
* stuff for handling program bogosity
*
*
* 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: merr.c,v $
* 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 <string.h>
#include <stdlib.h>
#include "mpsdef.h"
#include "merr.h"
#include "jobtab.h"
merr_stackent merr_stack[NESTLEVLS + 1];
char etrap[256];
char ecode[256];
char user_ecode[256];
int estack;
int etrap_lvl = 0;
int merr_topstk = 0;
typedef struct err_lut {
int ecode;
const char *canonical_name;
} err_lut;
err_lut errtab[] = {
{0, "ZOK"},
{1, "ZINRPT"},
{2, "ZBKERR"},
{3, "ZNOSTAND"},
{4, "ZUNDEF"},
{5, "ZLBLUNDEF"},
{6, "ZMISSOPD"},
{7, "ZMISSOP"},
{8, "ZILLOP"},
{9, "ZQUOTER"},
{10, "ZCOMMAER"},
{11, "ZASSIGNER"},
{12, "ZARGER"},
{13, "ZSPACER"},
{14, "ZBRAER"},
{15, "ZLVLERR"},
{16, "ZDIVER"},
{17, "ZILLFUN"},
{18, "ZFUNARG"},
{19, "ZZTERR"},
{20, "ZNEXTER"},
{21, "ZSELER"},
{22, "ZCMMND"},
{23, "ZARGLIST"},
{24, "ZINVEXPR"},
{25, "ZINVREF"},
{26, "ZMXSTR"},
{27, "ZTOOPARA"},
{28, "ZNOPEN"},
{29, "ZNODEVICE"},
{30, "ZPROTECT"},
{31, "ZGLOBER"},
{32, "ZFILERR"},
{33, "ZPGMOV"},
{34, "ZSTKOV"},
{35, "ZSTORE"},
{36, "ZNOREAD"},
{37, "ZNOWRITE"},
{38, "ZNOPGM"},
{39, "ZNAKED"},
{40, "ZSBSCR"},
{41, "ZISYNTX"},
{42, "ZDBDGD"},
{43, "ZKILLER"},
{44, "ZHUPER"},
{45, "ZMXNUM"},
{46, "ZNOVAL"},
{47, "ZTYPEMISMATCH"},
{48, "ZMEMOV"},
{49, "ZNAMERES"},
{50, "ZSCKCREAT"},
{51, "ZSCKIFAM"},
{52, "ZSCKITYP"},
{53, "ZSCKIPRT"},
{54, "ZSCKCERR"},
{55, "ZSCKAERR"},
{56, "ZSCKACON"},
{57, "ZSCKNCON"},
{58, "ZSCKEOPT"},
{59, "ZSCKERCV"},
{60, "ZSCKESND"},
{61, "ZNORPI"},
{62, "ZCREDEF"},
{63, "ZCMODIFY"},
{64, "ZFILEXWR"},
{65, "ZINEWMUL"},
{66, "ZINVHORO"},
{67, "ZTYPMISMATCH"},
{68, "ZINVTYPE"},
{69, "ZINVLIBOPT"},
{80, "ZECODEINV"},
{81, "ZASSERT"},
{82, "ZUSERERR"},
{83, "ZOBJFLDACCV"},
{84, "ZOBJCONFLICT"},
{85, "ZOBJPRIVOVFL"},
{86, "ZOBJACINVALID"},
{128, "ZSYNTERR"},
{140, "M1"},
{141, "M2"},
{142, "M3"},
{143, "M4"},
{144, "M5"},
{145, "M6"},
{146, "M7"},
{147, "M8"},
{148, "M9"},
{149, "M10"},
{150, "M11"},
{151, "M12"},
{152, "M13"},
{153, "M14"},
{154, "M15"},
{155, "M16"},
{156, "M17"},
{157, "M18"},
{158, "M19"},
{159, "M20"},
{160, "M21"},
{161, "M22"},
{162, "M23"},
{163, "M24"},
{164, "M25"},
{165, "M26"},
{166, "M27"},
{167, "M28"},
{168, "M29"},
{169, "M30"},
{170, "M31"},
{171, "M32"},
{172, "M33"},
{173, "M34"},
{174, "M35"},
{175, "M36"},
{176, "M37"},
{177, "M38"},
{178, "M39"},
{179, "M40"},
{180, "M41"},
{181, "M42"},
{182, "M43"},
{183, "M44"},
{184, "M45"},
{185, "M46"},
{186, "M47"},
{187, "M48"},
{188, "M49"},
{189, "M50"},
{190, "M51"},
{191, "M52"},
{192, "M53"},
{193, "M54"},
{194, "M55"},
{195, "M56"},
{196, "M57"},
{197, "M58"},
{198, "M59"},
{199, "M60"},
{214, "M75"},
{240, "M101"},
{241, "M102"},
{242, "M103"},
{243, "M104"},
{254, "ZASYNC"},
{255, "ZCTRLB"},
{-1, NULL}
};
inline int merr_raise(int num)
{
char place[256];
char cod[256];
if (merr_in_break ()) {
ierr = num - CTRLB;
}
else {
ierr = num;
}
if (num != OK) {
merr_set_ecode_ierr ();
stcpy (merr_stack[nstx].MCODE, code);
stcpy (merr_stack[nstx].ECODE, ecode);
if (direct_mode == 1 && nstx == 0) {
stcpy (merr_stack[nstx].PLACE, "@\201\0");
}
else {
if (!rtn_get_offset (merr_stack[nstx].PLACE)) {
stcpy (merr_stack[nstx].PLACE, "???\201");
}
}
if (nstx > merr_topstk) merr_topstk = nstx;
}
return ierr;
}
inline int merr(void)
{
return ierr < OK ? ierr + CTRLB : ierr;
}
short merr_in_break(void)
{
if (ierr < OK) {
return TRUE;
}
else {
return FALSE;
}
}
void merr_set_break(void)
{
if (!merr_in_break ()) {
ierr = ierr - CTRLB;
}
}
void merr_clear_break(void)
{
if (merr_in_break ()) {
ierr = ierr + CTRLB;
}
}
int merr_num_to_code (int num, char *code)
{
err_lut *p;
for (p = errtab; p->canonical_name != NULL; ++p) {
if (p->ecode == num) {
strcpy (code, p->canonical_name);
return 1;
}
}
return -1;
}
int merr_code_to_num (char *code)
{
err_lut *p;
for (p = errtab; p->canonical_name != NULL; ++p) {
if (strcmp (p->canonical_name, code) == 0) {
return p->ecode;
}
}
return -1;
}
void merr_set_ecode_ierr (void)
{
char *cod;
char *t;
cod = (char *) malloc (256 * sizeof (char));
NULLPTRCHK(cod,"merr_set_ecode_ierr");
t = (char *) malloc (256 * sizeof (char));
NULLPTRCHK(t,"merr_set_ecode_ierr");
if ((merr_num_to_code (merr (), cod)) == -1) goto done;
snprintf (t, 255, ",%s,\201", cod);
merr_set_ecode (t);
job_set_ecode (pid, cod);
done:
free (cod);
free (t);
return;
}
int merr_set_ecode (char *t_code)
{
int ec;
char *tmp;
if (t_code[0] == '\201') {
stcpy (ecode, "\201");
return 0;
}
if (t_code[1] != 'M' && t_code[1] != 'Z' && t_code[1] != 'U') {
return M101;
}
stcpy (ecode, t_code);
if (stcmp (t_code, "") == 0) {
merr_clear ();
stcpy (t_code, ",ZOK,");
stcpy (user_ecode, t_code);
}
tmp = strtok (t_code, ",");
/* caller may set ierr with return value */
if (ecode[1] == 'U') {
stcpy (user_ecode, ecode);
return USERERR;
}
else {
ec = merr_code_to_num (tmp);
return (ec);
}
}
void merr_dump (int num, char *rtn, char *nsn, char *tcod, int tpos)
{
char *tbuf;
char *dbuf;
char *nem;
char *nrt;
char *real_ecode;
err_lut *p;
tbuf = (char *) malloc (STRLEN * sizeof (char));
NULLPTRCHK(tbuf,"merr_dump");
dbuf = (char *) malloc (STRLEN * sizeof (char));
NULLPTRCHK(dbuf,"merr_dump");
nem = (char *) malloc (STRLEN * sizeof (char));
NULLPTRCHK(nem,"merr_dump");
nrt = (char *) malloc (STRLEN * sizeof (char));
NULLPTRCHK(nrt,"merr_dump");
real_ecode = (char *) malloc (STRLEN * sizeof (char));
NULLPTRCHK(real_ecode,"merr_dump");
stcpy (nrt, rtn);
stcnv_m2c (nrt);
stcpy (nem, errmes[num]);
stcnv_m2c (nem);
for (p = errtab; p->canonical_name != NULL; ++p) {
if (p->ecode == num) {
if (strcmp (p->canonical_name, "ZUSERERR") == 0) {
stcpy (real_ecode, &user_ecode[1]);
stcnv_m2c (real_ecode);
real_ecode [strlen (real_ecode) - 1] = NUL;
snprintf (tbuf, STRLEN - 1, "^$JOB\202%d\202USER_ERRORS\202%s\201", pid, &user_ecode[1]);
tbuf [stlen (tbuf) - 1] = '\201';
global (get_sym, tbuf, dbuf);
if (merr () == OK) {
stcpy (nem, dbuf);
stcnv_m2c (nem);
}
else {
merr_clear ();
}
}
else {
strcpy (real_ecode, p->canonical_name);
}
if (!stlen (err_suppl)) {
sprintf (tbuf, "\r\n>> Error %s: %s in %s.%s::%s [$STACK = %d]\r\n\201", real_ecode, nem, shm_env, nsn, nrt, nstx);
}
else {
stcnv_m2c (err_suppl);
sprintf (tbuf, "\r\n>> Error %s: %s (%s) in %s::%s [$STACK = %d]\r\n\201", real_ecode, nem, err_suppl, nsn, nrt, nstx);
err_suppl[0] = EOL;
}
write_m (tbuf);
write_m (">> \201");
write_m (tcod);
write_m ("\r\n\201");
write_t (tpos);
write_m ("^\201");
goto done;
}
}
done:
free (tbuf);
free (dbuf);
free (nem);
free (nrt);
free (real_ecode);
return;
}
void merr_set_iochan_err(int channel, short frm_err, char *err_text)
{
if (channel > MAXDEV || channel < 0) {
merr_raise (ARGLIST);
return;
}
devstat[channel].mdc_err = 1;
devstat[channel].frm_err = frm_err;
strncpy (devstat[channel].err_txt, err_text, 79);
return;
}
void merr_clear_iochan_err(int channel)
{
if (channel > MAXDEV || channel < 0) {
merr_raise (ARGLIST);
return;
}
devstat[channel].mdc_err = 1;
devstat[channel].frm_err = OK;
devstat[channel].err_txt[0] = '\0';
return;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>