1 /* 2 This file is part of GNU APL, a free implementation of the 3 ISO/IEC Standard 13751, "Programming Language APL, Extended" 4 5 Copyright (C) 2008-2019 Dr. Jürgen Sauermann 6 7 This program is free software: you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation, either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #ifndef __ERROR_HH_DEFINED__ 22 #define __ERROR_HH_DEFINED__ 23 24 #include "Backtrace.hh" 25 #include "Common.hh" 26 #include "ErrorCode.hh" 27 #include "UCS_string.hh" 28 #include <cstring> 29 #ifdef __GNUC__ 30 #define GNUC__noreturn __attribute__ ((noreturn)) 31 #else 32 #define GNUC__noreturn 33 #endif 34 35 class StateIndicator; 36 37 /** 38 ** The exception that is thrown when errors occur. 39 ** The primary item is the error_code; the other items are only valid if 40 ** error_code != NO_ERROR 41 **/ 42 /// An APL error and information related to it 43 class Error 44 { 45 public: 46 /// constructor: error with error code ec 47 Error(ErrorCode ec, const char * loc); 48 49 /// return true iff error_code is known (as opposed to an arbitrary 50 /// error code constructed by ⎕ES) 51 bool is_known() const; 52 53 /// return true iff error_code is some SYNTAX ERROR or VALUE ERROR 54 bool is_syntax_or_value_error() const; 55 56 /// return the error code of \b this error get_error_code() const57 const ErrorCode get_error_code() const 58 { return error_code; } 59 60 /// return ⎕EM[1;]. This is the first of 3 error lines. It contains the 61 /// error name (like SYNTAX ERROR, DOMAIN ERROR, etc) and is subject 62 /// to translation get_error_line_1() const63 const char * get_error_line_1() const 64 { return error_message_1; } 65 66 /// clear error line 1 clear_error_line_1()67 void clear_error_line_1() 68 { *error_message_1 = 0; } 69 70 /// return error_message_2. This is the second of 3 error lines. 71 /// It contains the failed statement and is NOT subject to translation. get_error_line_2() const72 const char * get_error_line_2() const 73 { return error_message_2; } 74 75 /// return the major class (⎕ET) of the error error_major(ErrorCode err)76 static int error_major(ErrorCode err) 77 { return err >> 16; } 78 79 /// return the category (⎕ET) of the error error_minor(ErrorCode err)80 static int error_minor(ErrorCode err) 81 { return err & 0xFFFF; } 82 83 /// return source file location where this error was printed (0 if not) get_print_loc() const84 const char * get_print_loc() const 85 { return print_loc; } 86 87 /// compute the caret line. This is the third of the 3 error lines. 88 /// It contains the failure position the statement and is NOT subject 89 /// to translation. 90 UCS_string get_error_line_3() const; 91 92 /// return the source code location where the error was thrown get_throw_loc() const93 const char * get_throw_loc() const 94 { return throw_loc; } 95 96 /// return the left caret (^) position in the third error line get_left_caret() const97 int get_left_caret() const 98 { return left_caret; } 99 100 /// return the right caret (^) position in the third error line get_right_caret() const101 int get_right_caret() const 102 { return right_caret; } 103 104 /// return the show_locked flag get_show_locked() const105 bool get_show_locked() const 106 { return show_locked; } 107 108 /// print the error and its related information 109 void print(ostream & out, const char * loc) const; 110 111 /// set the first error line set_error_line_1(const char * msg_1)112 void set_error_line_1(const char * msg_1) 113 { strncpy(error_message_1, msg_1, sizeof(error_message_1) - 1); 114 error_message_1[sizeof(error_message_1) - 1] = 0; } 115 116 /// set the second error line set_error_line_2(const char * msg_2)117 void set_error_line_2(const char * msg_2) 118 { strncpy(error_message_2, msg_2, sizeof(error_message_2) - 1); 119 error_message_2[sizeof(error_message_2) - 1] = 0; } 120 121 /// set error line 2, left caret, and right caret 122 void set_error_line_2(const UCS_string & ucs, int lcaret, int rcaret); 123 124 /// print the 3 error message lines as per ⎕EM 125 void print_em(ostream & out, const char * loc); 126 127 /// set the error code clear_error_code()128 void clear_error_code() 129 { error_code = E_NO_ERROR; } 130 131 /// set the show_locked flag set_show_locked(bool on)132 void set_show_locked(bool on) 133 { show_locked = on; } 134 135 /// set the left caret (^) position in the third error line set_left_caret(int col)136 void set_left_caret(int col) 137 { left_caret = col; } 138 139 /// set the right caret (^) position in the third error line set_right_caret(int col)140 void set_right_caret(int col) 141 { right_caret = col; } 142 143 /// set the source code line where a parse error was thrown set_parser_loc(const char * loc)144 void set_parser_loc(const char * loc) 145 { parser_loc = loc; } 146 147 /// update error information in \b this and copy it to si 148 void update_error_info(StateIndicator * si); 149 150 /// throw an Error related to \b Symbol \b symbol 151 static void throw_symbol_error(const UCS_string & symbol, 152 const char * loc) GNUC__noreturn; 153 154 /// throw a error with a parser location 155 static void throw_parse_error(ErrorCode code, const char * par_loc, 156 const char * loc) GNUC__noreturn; 157 158 /// throw a DEFN ERROR for function \b fun 159 static void throw_define_error(const UCS_string & fun, 160 const UCS_string & cmd, 161 const char * loc) GNUC__noreturn; 162 163 /// return a string describing the error 164 static const char * error_name(ErrorCode err); 165 166 protected: 167 /// the error code 168 ErrorCode error_code; 169 170 /// the mandatory source file location where the error was thrown 171 const char * throw_loc; 172 173 /// an optional symbol related to (i.e. triggering) the error 174 char symbol_name[60]; 175 176 /// an optional source file location (for parse errors) 177 const char * parser_loc; 178 179 /// an optional error text. this text is provided for non-APL errors, 180 // for example in ⎕ES 181 char error_message_1[60]; 182 183 /// second line of error message (only valid if error_code != _NO_ERROR) 184 char error_message_2[60]; 185 186 /// display user function and line rather than ⎕ES instruction 187 bool show_locked; 188 189 /// the left caret position (-1 if none) for the error display 190 int left_caret; 191 192 /// the right caret position (-1 if none) for the error display 193 int right_caret; 194 195 /// where this error was printed (0 if not) 196 const char * print_loc; 197 198 private: 199 /// constructor (not implemented): prevent construction without error code 200 Error(); 201 }; 202 #endif // __ERROR_HH_DEFINED__ 203