Annotation of freem/src/merr.c, revision 1.9
1.1 snw 1: /*
1.9 ! snw 2: * $Id: merr.c,v 1.8 2025/05/03 04:12:34 snw Exp $
1.1 snw 3: * stuff for handling program bogosity
4: *
5: *
1.2 snw 6: * Author: Serena Willis <snw@coherent-logic.com>
1.1 snw 7: * Copyright (C) 1998 MUG Deutschland
1.3 snw 8: * Copyright (C) 2020, 2025 Coherent Logic Development LLC
1.1 snw 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: *
1.4 snw 26: * $Log: merr.c,v $
1.9 ! snw 27: * Revision 1.8 2025/05/03 04:12:34 snw
! 28: * Fix user-defined error codes
! 29: *
1.8 snw 30: * Revision 1.7 2025/05/01 03:56:29 snw
31: * -m
32: *
1.7 snw 33: * Revision 1.6 2025/04/30 17:19:16 snw
34: * Improve backtraces in debugger
35: *
1.6 snw 36: * Revision 1.5 2025/04/13 04:22:43 snw
37: * Fix snprintf calls
38: *
1.5 snw 39: * Revision 1.4 2025/04/09 19:52:02 snw
40: * Eliminate as many warnings as possible while building with -Wall
41: *
1.4 snw 42: * Revision 1.3 2025/03/09 19:50:47 snw
43: * Second phase of REUSE compliance and header reformat
44: *
1.3 snw 45: *
46: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
47: * SPDX-License-Identifier: AGPL-3.0-or-later
1.1 snw 48: **/
49:
50: #include <string.h>
51: #include <stdlib.h>
52:
53: #include "mpsdef.h"
54: #include "merr.h"
55: #include "jobtab.h"
56:
57: merr_stackent merr_stack[NESTLEVLS + 1];
58: char etrap[256];
59: char ecode[256];
60: char user_ecode[256];
61: int estack;
62: int etrap_lvl = 0;
63: int merr_topstk = 0;
64:
65: typedef struct err_lut {
66: int ecode;
67: const char *canonical_name;
68: } err_lut;
69:
70: err_lut errtab[] = {
71: {0, "ZOK"},
72: {1, "ZINRPT"},
73: {2, "ZBKERR"},
74: {3, "ZNOSTAND"},
75: {4, "ZUNDEF"},
76: {5, "ZLBLUNDEF"},
77: {6, "ZMISSOPD"},
78: {7, "ZMISSOP"},
79: {8, "ZILLOP"},
80: {9, "ZQUOTER"},
81: {10, "ZCOMMAER"},
82: {11, "ZASSIGNER"},
83: {12, "ZARGER"},
84: {13, "ZSPACER"},
85: {14, "ZBRAER"},
86: {15, "ZLVLERR"},
87: {16, "ZDIVER"},
88: {17, "ZILLFUN"},
89: {18, "ZFUNARG"},
90: {19, "ZZTERR"},
91: {20, "ZNEXTER"},
92: {21, "ZSELER"},
93: {22, "ZCMMND"},
94: {23, "ZARGLIST"},
95: {24, "ZINVEXPR"},
96: {25, "ZINVREF"},
97: {26, "ZMXSTR"},
98: {27, "ZTOOPARA"},
99: {28, "ZNOPEN"},
100: {29, "ZNODEVICE"},
101: {30, "ZPROTECT"},
102: {31, "ZGLOBER"},
103: {32, "ZFILERR"},
104: {33, "ZPGMOV"},
105: {34, "ZSTKOV"},
106: {35, "ZSTORE"},
107: {36, "ZNOREAD"},
108: {37, "ZNOWRITE"},
109: {38, "ZNOPGM"},
110: {39, "ZNAKED"},
111: {40, "ZSBSCR"},
112: {41, "ZISYNTX"},
113: {42, "ZDBDGD"},
114: {43, "ZKILLER"},
115: {44, "ZHUPER"},
116: {45, "ZMXNUM"},
117: {46, "ZNOVAL"},
118: {47, "ZTYPEMISMATCH"},
119: {48, "ZMEMOV"},
120: {49, "ZNAMERES"},
121: {50, "ZSCKCREAT"},
122: {51, "ZSCKIFAM"},
123: {52, "ZSCKITYP"},
124: {53, "ZSCKIPRT"},
125: {54, "ZSCKCERR"},
126: {55, "ZSCKAERR"},
127: {56, "ZSCKACON"},
128: {57, "ZSCKNCON"},
129: {58, "ZSCKEOPT"},
130: {59, "ZSCKERCV"},
131: {60, "ZSCKESND"},
132: {61, "ZNORPI"},
133: {62, "ZCREDEF"},
134: {63, "ZCMODIFY"},
135: {64, "ZFILEXWR"},
136: {65, "ZINEWMUL"},
137: {66, "ZINVHORO"},
138: {67, "ZTYPMISMATCH"},
139: {68, "ZINVTYPE"},
140: {69, "ZINVLIBOPT"},
141: {80, "ZECODEINV"},
142: {81, "ZASSERT"},
143: {82, "ZUSERERR"},
144: {83, "ZOBJFLDACCV"},
145: {84, "ZOBJCONFLICT"},
146: {85, "ZOBJPRIVOVFL"},
147: {86, "ZOBJACINVALID"},
148: {128, "ZSYNTERR"},
149: {140, "M1"},
150: {141, "M2"},
151: {142, "M3"},
152: {143, "M4"},
153: {144, "M5"},
154: {145, "M6"},
155: {146, "M7"},
156: {147, "M8"},
157: {148, "M9"},
158: {149, "M10"},
159: {150, "M11"},
160: {151, "M12"},
161: {152, "M13"},
162: {153, "M14"},
163: {154, "M15"},
164: {155, "M16"},
165: {156, "M17"},
166: {157, "M18"},
167: {158, "M19"},
168: {159, "M20"},
169: {160, "M21"},
170: {161, "M22"},
171: {162, "M23"},
172: {163, "M24"},
173: {164, "M25"},
174: {165, "M26"},
175: {166, "M27"},
176: {167, "M28"},
177: {168, "M29"},
178: {169, "M30"},
179: {170, "M31"},
180: {171, "M32"},
181: {172, "M33"},
182: {173, "M34"},
183: {174, "M35"},
184: {175, "M36"},
185: {176, "M37"},
186: {177, "M38"},
187: {178, "M39"},
188: {179, "M40"},
189: {180, "M41"},
190: {181, "M42"},
191: {182, "M43"},
192: {183, "M44"},
193: {184, "M45"},
194: {185, "M46"},
195: {186, "M47"},
196: {187, "M48"},
197: {188, "M49"},
198: {189, "M50"},
199: {190, "M51"},
200: {191, "M52"},
201: {192, "M53"},
202: {193, "M54"},
203: {194, "M55"},
204: {195, "M56"},
205: {196, "M57"},
206: {197, "M58"},
207: {198, "M59"},
208: {199, "M60"},
209: {214, "M75"},
210: {240, "M101"},
211: {241, "M102"},
212: {242, "M103"},
213: {243, "M104"},
214: {254, "ZASYNC"},
215: {255, "ZCTRLB"},
216: {-1, NULL}
217: };
218:
219: inline int merr_raise(int num)
220: {
1.6 snw 221: char placebuf[256];
222: char lref[256];
223:
224: if (num != OK) {
225: lasterr[nstx] = ierr;
226: }
1.1 snw 227:
228: if (merr_in_break ()) {
229: ierr = num - CTRLB;
230: }
231: else {
232: ierr = num;
233: }
234:
235: if (num != OK) {
236: merr_set_ecode_ierr ();
237:
238: stcpy (merr_stack[nstx].ECODE, ecode);
239:
240: if (direct_mode == 1 && nstx == 0) {
241: stcpy (merr_stack[nstx].PLACE, "@\201\0");
1.6 snw 242: stcpy (merr_stack[nstx].MCODE, " \201\0");
1.1 snw 243: }
1.7 snw 244: else {
1.6 snw 245: getraddress (placebuf, nstx);
246: stcpy (merr_stack[nstx].PLACE, &(placebuf[3]));
247: stcpy (lref, merr_stack[nstx].PLACE);
248: stcnv_m2c (lref);
1.7 snw 249: if (routine_get_line (lref, merr_stack[nstx].MCODE) == NULL) {
1.6 snw 250: sprintf (merr_stack[nstx].MCODE, "???\201");
1.1 snw 251: }
1.7 snw 252: else {
253: stcnv_c2m (merr_stack[nstx].MCODE);
254: }
1.1 snw 255: }
1.6 snw 256:
1.1 snw 257: if (nstx > merr_topstk) merr_topstk = nstx;
1.6 snw 258: }
1.1 snw 259:
260: return ierr;
261: }
262:
263: inline int merr(void)
264: {
265: return ierr < OK ? ierr + CTRLB : ierr;
266: }
267:
268: short merr_in_break(void)
269: {
270: if (ierr < OK) {
271: return TRUE;
272: }
273: else {
274: return FALSE;
275: }
276: }
277:
278: void merr_set_break(void)
279: {
280: if (!merr_in_break ()) {
281: ierr = ierr - CTRLB;
282: }
283: }
284:
285: void merr_clear_break(void)
286: {
287: if (merr_in_break ()) {
288: ierr = ierr + CTRLB;
289: }
290: }
291:
292: int merr_num_to_code (int num, char *code)
293: {
294:
295: err_lut *p;
296:
297: for (p = errtab; p->canonical_name != NULL; ++p) {
298:
299: if (p->ecode == num) {
300: strcpy (code, p->canonical_name);
301: return 1;
302: }
303:
304: }
305:
306: return -1;
307:
308: }
309:
310: int merr_code_to_num (char *code)
311: {
312:
313: err_lut *p;
314:
315: for (p = errtab; p->canonical_name != NULL; ++p) {
316:
317: if (strcmp (p->canonical_name, code) == 0) {
318: return p->ecode;
319: }
320:
321: }
322:
323: return -1;
324:
325: }
326:
327: void merr_set_ecode_ierr (void)
328: {
329: char *cod;
330: char *t;
331:
1.5 snw 332: cod = (char *) malloc (MERR_COD_LENGTH * sizeof (char));
1.1 snw 333: NULLPTRCHK(cod,"merr_set_ecode_ierr");
334:
1.5 snw 335: t = (char *) malloc (MERR_COD_LENGTH * sizeof (char));
1.1 snw 336: NULLPTRCHK(t,"merr_set_ecode_ierr");
337:
338: if ((merr_num_to_code (merr (), cod)) == -1) goto done;
339:
1.5 snw 340: snprintf (t, MERR_COD_LENGTH - 1, ",%s,\201", cod);
1.1 snw 341: merr_set_ecode (t);
342:
343: job_set_ecode (pid, cod);
344:
345: done:
346:
347: free (cod);
348: free (t);
349: return;
350:
351: }
352:
353: int merr_set_ecode (char *t_code)
354: {
355: int ec;
356: char *tmp;
357:
358: if (t_code[0] == '\201') {
359: stcpy (ecode, "\201");
360: return 0;
361: }
362:
363: if (t_code[1] != 'M' && t_code[1] != 'Z' && t_code[1] != 'U') {
364: return M101;
365: }
366:
367: stcpy (ecode, t_code);
368:
369: if (stcmp (t_code, "") == 0) {
370: merr_clear ();
371: stcpy (t_code, ",ZOK,");
372: stcpy (user_ecode, t_code);
373: }
374:
375: tmp = strtok (t_code, ",");
376:
377: /* caller may set ierr with return value */
378: if (ecode[1] == 'U') {
379: stcpy (user_ecode, ecode);
380: return USERERR;
381: }
382: else {
383: ec = merr_code_to_num (tmp);
384: return (ec);
385: }
386: }
387:
388: void merr_dump (int num, char *rtn, char *nsn, char *tcod, int tpos)
389: {
390: char *tbuf;
391: char *dbuf;
392: char *nem;
393: char *nrt;
394: char *real_ecode;
395: err_lut *p;
396:
397: tbuf = (char *) malloc (STRLEN * sizeof (char));
398: NULLPTRCHK(tbuf,"merr_dump");
399:
400: dbuf = (char *) malloc (STRLEN * sizeof (char));
401: NULLPTRCHK(dbuf,"merr_dump");
402:
403: nem = (char *) malloc (STRLEN * sizeof (char));
404: NULLPTRCHK(nem,"merr_dump");
405:
406: nrt = (char *) malloc (STRLEN * sizeof (char));
407: NULLPTRCHK(nrt,"merr_dump");
408:
409: real_ecode = (char *) malloc (STRLEN * sizeof (char));
410: NULLPTRCHK(real_ecode,"merr_dump");
411:
412: stcpy (nrt, rtn);
413: stcnv_m2c (nrt);
414:
415: stcpy (nem, errmes[num]);
416: stcnv_m2c (nem);
417:
418: for (p = errtab; p->canonical_name != NULL; ++p) {
419:
420: if (p->ecode == num) {
421:
422: if (strcmp (p->canonical_name, "ZUSERERR") == 0) {
423: stcpy (real_ecode, &user_ecode[1]);
424: stcnv_m2c (real_ecode);
425: real_ecode [strlen (real_ecode) - 1] = NUL;
426:
1.5 snw 427: snprintf (tbuf, STRLEN - 1, "^$JOB\202%d\202USER_ERRORS\202%s\201", pid, &user_ecode[1]);
1.1 snw 428: tbuf [stlen (tbuf) - 1] = '\201';
429:
1.8 snw 430: ssvn (get_sym, tbuf, dbuf);
1.1 snw 431:
432: if (merr () == OK) {
433: stcpy (nem, dbuf);
434: stcnv_m2c (nem);
435: }
436: else {
1.9 ! snw 437: sprintf (nem, "user-defined error");
1.1 snw 438: merr_clear ();
439: }
1.9 ! snw 440:
! 441: if (strlen (nem) == 0) {
! 442: sprintf (nem, "user-defined error");
! 443: }
1.1 snw 444:
445: }
446: else {
447: strcpy (real_ecode, p->canonical_name);
448: }
449:
1.4 snw 450:
451:
1.1 snw 452: if (!stlen (err_suppl)) {
1.5 snw 453: snprintf (tbuf, STRLEN - 1, "\r\n>> Error %s: %s in %s.%s::%s [$STACK = %d]\r\n\201", real_ecode, nem, shm_env, nsn, nrt, nstx);
1.1 snw 454: }
455: else {
456: stcnv_m2c (err_suppl);
1.5 snw 457: snprintf (tbuf, STRLEN - 1, "\r\n>> Error %s: %s (%s) in %s::%s [$STACK = %d]\r\n\201", real_ecode, nem, err_suppl, nsn, nrt, nstx);
1.1 snw 458: err_suppl[0] = EOL;
459: }
460: write_m (tbuf);
461: write_m (">> \201");
462: write_m (tcod);
463: write_m ("\r\n\201");
464: write_t (tpos);
465: write_m ("^\201");
466:
467: goto done;
468: }
469:
470: }
471:
472:
473: done:
474:
475: free (tbuf);
476: free (dbuf);
477: free (nem);
478: free (nrt);
479: free (real_ecode);
480:
481: return;
482: }
483:
484:
485: void merr_set_iochan_err(int channel, short frm_err, char *err_text)
486: {
487: if (channel > MAXDEV || channel < 0) {
488: merr_raise (ARGLIST);
489: return;
490: }
491:
492: devstat[channel].mdc_err = 1;
493: devstat[channel].frm_err = frm_err;
494:
495: strncpy (devstat[channel].err_txt, err_text, 79);
496:
497: return;
498: }
499:
500: void merr_clear_iochan_err(int channel)
501: {
502: if (channel > MAXDEV || channel < 0) {
503: merr_raise (ARGLIST);
504: return;
505: }
506:
507: devstat[channel].mdc_err = 1;
508: devstat[channel].frm_err = OK;
509: devstat[channel].err_txt[0] = '\0';
510:
511: return;
512:
513: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>