From 229a60e4d58c6d82f5c56fe97b7477b4ddae99ac Mon Sep 17 00:00:00 2001 From: Landon Curt Noll Date: Tue, 12 Sep 2023 16:06:27 -0700 Subject: [PATCH] improve calc error code system Changed calc_errno a global int variable so that is may be directly accessed by libcalc users. Further improve help files for help/errno, help/error, help/newerror, help/stoponerror and help/strerror by adding to documentation of the calc error code system as well as libcalc interface where applicable. --- CHANGES | 8 +++++ calc.h | 1 + help/errno | 50 ++++++++++++++++++--------- help/error | 68 +++++++++++++++++++++--------------- help/newerror | 10 ++++-- help/stoponerror | 5 ++- help/strerror | 90 +++++++++++++++++++++++++++++++++--------------- opcodes.c | 10 +++--- 8 files changed, 162 insertions(+), 80 deletions(-) diff --git a/CHANGES b/CHANGES index 302a959..30aab81 100644 --- a/CHANGES +++ b/CHANGES @@ -221,6 +221,14 @@ The following are the changes from calc version 2.14.3.5 to date: Improve help/error. Added text about error code ranges and range symbols. + Changed calc_errno a global int variable so that is may be directly + accessed by libcalc users. + + Further improve help files for help/errno, help/error, help/newerror, + help/stoponerror and help/strerror by adding to documentation + of the calc error code system as well as libcalc interface + where applicable. + The following are the changes from calc version 2.14.3.4 to 2.14.3.5: diff --git a/calc.h b/calc.h index eb186b8..1ba2241 100644 --- a/calc.h +++ b/calc.h @@ -222,6 +222,7 @@ EXTERN int abortlevel; /* current level of aborts */ EXTERN bool inputwait; /* true if in a terminal input wait */ EXTERN VALUE *stack; /* execution stack */ EXTERN int dumpnames; /* true => dump names rather than indices */ +EXTERN int calc_errno; /* global calc_errno value */ EXTERN char *calcpath; /* $CALCPATH or default */ EXTERN char *calcrc; /* $CALCRC or default */ diff --git a/help/errno b/help/errno index 084de17..0156782 100644 --- a/help/errno +++ b/help/errno @@ -5,19 +5,35 @@ SYNOPSIS errno([errnum]) TYPES - errnum integer, 0 <= errnum <= 32767 + errnum integer return integer DESCRIPTION - Whenever an operation or evaluation of function returns an error-value, - the numerical code for that value is stored as calc_errno. + the numerical code for that value is stored as "global calc_errno value". - errno() returns the current value of calc_errno. + The term "global calc_errno value" is an internal calc state. + This is NOT a calc variable called calc_errno. - errno(errnum) sets calc_errno to the value errnum and returns its - previous value. + NOTE: + + The errno() builtin should not be confused with the errno + used by libc in C. The range of errnum extend beyond the + C's libc errno. See help error for information on the mean + of various errnum ranges. + + Unlike error() calling errno() does NOT increment the global + calc error count (see help errcount). + + errno() returns the current value of "global calc_errno value". + Unlike error() calling errno() does NOT increment the global + calc error count (see help errcount). + + errno(errnum) sets "global calc_errno value" to the value errnum + and returns its previous value. Unlike error(errnum) calling + errno(errnum) does NOT increment the global calc error count + (see help errcount). To detect whether an error occurs during some sequence of operations, one may immediately before that sequence set the stored error-number @@ -34,29 +50,29 @@ DESCRIPTION EXAMPLE ; ## Assuming there is no file with name "not_a_file" - ; errno(0) - 0 - ; errmax(errcount()+4) - 20 + ; errcount(0),; errmax(20),; + ; print errcount(), errmax() + 0 20 + ; badfile = fopen("not_a_file", "r") - ; print errno(), error(), strerror() - 2 System error 2 No such file or directory + ; print errcount(), errno(), strerror() + 1 2 No such file or directory ; a = 1/0 - ; print errno(), error(), strerror() - 10001 Error 10001 Division by zero + ; print errcount(), errno(), strerror() + 2 10001 Division by zero LIMITS - none + 0 <= errnum <= 32767 LINK LIBRARY - none + int calc_errno; /* global calc_errno value */ SEE ALSO errmax, errcount, error, strerror, iserror, newerror, errorcodes, stoponerror -## Copyright (C) 1999-2006,2021 Landon Curt Noll +## Copyright (C) 1999-2006,2021,2023 Landon Curt Noll ## ## Calc is open software; you can redistribute it and/or modify it under ## the terms of the version 2.1 of the GNU Lesser General Public License diff --git a/help/error b/help/error index b914f55..b13a351 100644 --- a/help/error +++ b/help/error @@ -2,72 +2,82 @@ NAME error - generate a value of specified error type SYNOPSIS - error([n]) + error([errnum]) TYPES - n integer, defaults to errno() + errnum integer, defaults to errno() return null value or error value DESCRIPTION - If n == 0: + If errnum == 0: - error(n) returns the null value. + error(errnum) returns the null value. The "global calc_errno value" is set to 0. The global calc error count is not changed. - For 0 < n <= 32767: + For 0 < errnum <= 32767: - error(n) returns a value that is of a special type called + error(errnum) returns a value that is of a special type called "error". The "error" return value, when given to iserror() will cause that function to return a true value that happens to match the "global calc_errno value". - The "global calc_errno value" is then set to n. + The "global calc_errno value" is then set to errnum. The global calc error count (see help errcount) is incremented. If the global calc error count exceeds the maximum count (see help errmax), any ongoing calc execution is aborted. - All other values of n are reserved for future use and currently + All other values of errnum are reserved for future use and currently will generate an error. + NOTE: + + Calling error() without an argument will return the current + "global calc_errno value" AND will also increment the + global calc error count. + + Use errno() instead of error() to return the "global calc_errno + value" without incrementing the global calc error count. + The term "global calc_errno value" is an internal calc state. - This is NOT a calc variable called calc_errno. + This is NOT a calc variable called calc_errno. The value of the + "global calc_errno value" may be returned by errno() (see help errno). The "global calc_errno value" be set to some other non-zero value by other builtin functions and calculations, especially - if they result in an error. Thus, while calling errno(n) may + if they result in an error. Thus, while calling errno(errnum) may set calc_errno, some other error may later overwrite the "global calc_errno value". By convention, the "global calc_errno value" has the following ranges: - n < 0 Reserved for future use + errnum < 0 Reserved for future use - n == 0 calc_errno cleared: libc errno codes above here + errnum == 0 calc_errno cleared: libc errno codes above here - 1 <= n <= 9999 system error and libc errno codes + 1 <= errnum <= 9999 system error and libc errno codes - n == 10000 Reserved for "No error" calc internal state + errnum == 10000 Reserved for "No error" calc internal state - 10001 <= n <= E__HIGHEST calc computation error codes + 10001 <= errnum <= E__HIGHEST calc computation error codes - E__HIGHEST < n < 20000 Reserved for future calc error codes + E__HIGHEST < errnum < 20000 Reserved for future calc error codes - 20000 < n <= 32767 User defined error codes start here + 20000 < errnum <= 32767 User defined error codes start here - n >= 32768 Reserved for future use + errnum >= 32768 Reserved for future use The following constants are part of the calc error code mechanism: - E__BASE == 10000 - E_USERDEF == 20000 - E_USERMAX == 32767 - E__BASE < E__HIGHEST < E_USERDEF - E__COUNT == E__HIGHEST - E__BASE + E__BASE == 10000 # 1 less than the 1st calc computation error code + E_USERDEF == 20000 # User defined error codes start + E_USERMAX == 32767 # maximum user defined error code + E__BASE < E__HIGHEST < E_USERDEF # How E__HIGHEST is bounded + E__COUNT == E__HIGHEST - E__BASE # Number of calc computation error codes See help errorcodes for the actual values of the above constants. @@ -84,8 +94,10 @@ EXAMPLE Error 10009 ; print iserror(a) 10009 - ; strerror(a) - "Bad argument for inverse" + ; print strerror(a) + "Bad argument for inverse" + ; print errno() + 10009 ; b = error(0) @@ -93,12 +105,14 @@ EXAMPLE 1 20 ; print isnull(b) 1 + ; print errno() + 0 LIMITS - 0 <= n <= 32767 + 0 <= errnum <= 32767 LINK LIBRARY - none + int calc_errno; /* global calc_errno value */ SEE ALSO errcount, errmax, errorcodes, iserror, errno, strerror, newerror, diff --git a/help/newerror b/help/newerror index c834f64..4e9ec7b 100644 --- a/help/newerror +++ b/help/newerror @@ -15,6 +15,11 @@ DESCRIPTION that any future use of newerror(str) with the same str will return the same error-value. + When this function is called, the global calc error count (see + help errcount) is incremented. If the global calc error count + exceeds the maximum count (see help errmax), any ongoing calc + execution is aborted. + If x = newerror(str), both strerror(x) and strerror(iserro(x)) will return str and iserror(x) will return the error code value of the new error. @@ -61,7 +66,8 @@ EXAMPLE triangle side length <= 0: 20000 LIMITS - The number of new described error-values is not to exceed 12767. + The number of new described error-values is not to exceed E_USERMAX-E_USERDEF + (which is usually 12767 calls to the newerror function). LINK LIBRARY none @@ -70,7 +76,7 @@ SEE ALSO errmax, errcount, error, strerror, iserror, errno, errorcodes, stoponerror -## Copyright (C) 1999-2006 Landon Curt Noll +## Copyright (C) 1999-2006,2023 Landon Curt Noll ## ## Calc is open software; you can redistribute it and/or modify it under ## the terms of the version 2.1 of the GNU Lesser General Public License diff --git a/help/stoponerror b/help/stoponerror index a3dc3c4..23f9406 100644 --- a/help/stoponerror +++ b/help/stoponerror @@ -22,6 +22,9 @@ DESCRIPTION stoponerror value. When 1 argument is given, stoponerror() returns the previous stoponerror value. + See help errcount for information on the current error count. + See help errmax for the maximum error-count before execution stops. + EXAMPLE ; stoponerror() 0 @@ -35,7 +38,7 @@ LINK LIBRARY SEE ALSO errcount, errmax, errorcodes, iserror, errno, strerror, newerror -## Copyright (C) 2006,2021 Landon Curt Noll +## Copyright (C) 2006,2021,2023 Landon Curt Noll ## ## Calc is open software; you can redistribute it and/or modify it under ## the terms of the version 2.1 of the GNU Lesser General Public License diff --git a/help/strerror b/help/strerror index 1b262f7..c4d1e0a 100644 --- a/help/strerror +++ b/help/strerror @@ -2,51 +2,85 @@ NAME strerror - returns a string describing an error value SYNOPSIS - strerror([x]) + strerror([errnum]) TYPES - x error-value or integer in [0, 32767], defaults to errno() + errnum integer return string DESCRIPTION - If x is the error-value with index n, strerror(x) and strerror(n) - return one of: + If 0 <= errnum <= 32767 then strerror(errnum) will return one of: - a system-generated message, - a calc-generated description, - a user-defined description created by newerror(str), - the string "Error n", + * system error and libc errno value related string + * calc computation error code string + * user-defined description string created by newerror(str) + * "Unknown error errnum" (where errnum is in decimal) - where, in the last form, n is represented decimally. + Without a argument, strerror() returns as if it were called with: + + strerror(errno()) + + That is, the string associated with the "global calc_errno value" + is returned. + + The term "global calc_errno value" is an internal calc state. + This is NOT a calc variable called calc_errno. + + The system error and libc errno value related string may be + different for different systems. + + For users of libcalc: + + The libcalc array error_table[] contains the hard coded + calc-generated error array of E__COUNT+2 pointers to strings + starting with E__BASE, ending with E__HIGHEST and terminated + by a NULL pointer. + + The error_table[0] is for errnum of E__BASE, and is the + string "No error". + + The error_table[E__COUNT] is string associated with the + highest calc-generated error message. + + The error_table[E__COUNT+1] is a NULL pointer. + + See help error for more information on the ranges of errnum and + the meaning of the above mentioned constants. EXAMPLE - System error messages may be different for different systems. - ; errmax(errcount()+3) - 0 - ; strerror(2) - "No such file or directory" + ; errcount(0),; errmax(20),; + ; print errcount(), errmax() + 0 20 - ; x = 3 * ("a" + "b") - ; print strerror(x) - Bad arguments for + + ; print strerror(2) + No such file or directory + ; print errcount(), errmax() + 0 20 - ; a = newerror("alpha") - ; print strerror(a) - alpha - - ; print strerror(999) - Error 999 - - ; a = 1/0 + ; x = 3 / 0; + ; print errcount(), errmax() + 1 20 ; print strerror() Division by zero + ; a = newerror("alpha") + ; print errcount(), errmax() + 2 20 + ; print strerror() + alpha + + ; print strerror(999) + Unknown error: 999 + ; print errcount(), errmax() + 2 20 + LIMITS - none + 0 <= errnum <= 32767 LINK LIBRARY - none + int calc_errno; /* global calc_errno value */ + CONST char *error_table[E__COUNT+2]; /* calc coded error messages */ SEE ALSO strcat, strcpy, strlen, strncmp, strncpy, strpos, @@ -55,7 +89,7 @@ SEE ALSO errcount, errmax, error, iserror, errno, newerror, errorcodes, stoponerror -## Copyright (C) 1999-2006 Landon Curt Noll +## Copyright (C) 1999-2006,2023 Landon Curt Noll ## ## Calc is open software; you can redistribute it and/or modify it under ## the terms of the version 2.1 of the GNU Lesser General Public License diff --git a/opcodes.c b/opcodes.c index 05601f4..c9332a1 100644 --- a/opcodes.c +++ b/opcodes.c @@ -57,7 +57,6 @@ STATIC VALUE stackarray[MAXSTACK]; /* storage for stack */ STATIC VALUE oldvalue; /* previous calculation value */ STATIC bool saveval = true; /* to enable or disable saving */ -STATIC int calc_errno; /* most recent error-number */ STATIC int errcount; /* counts calls to error_value */ STATIC bool go; STATIC long calc_depth; @@ -65,10 +64,11 @@ STATIC long calc_depth; /* * global symbols */ -VALUE *stack; /* current location of top of stack */ -int dumpnames; /* names if true, otherwise indices */ -char *funcname; /* function being executed */ -long funcline; /* function line being executed */ +VALUE *stack = NULL; /* current location of top of stack */ +int dumpnames = false; /* names if true, otherwise indices */ +char *funcname = NULL; /* function being executed */ +long funcline = 0; /* function line being executed */ +int calc_errno = 0; /* global calc_errno value */ /*