2 * The Regina Rexx Interpreter
3 * Copyright (C) 1992-1994 Anders Christensen <anders@pvv.unit.no>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 typedef struct /* err_tsd: static variables of this module (thread-safe) */
38 struct textindex nls_tmi
[NUMBER_ERROR_MESSAGES
]; /* indexes for native language messages */
41 } err_tsd_t
; /* thread-specific but only needed by this module. see init_error */
51 * English message text - generated by makeerror.rexx
53 static const errtext_t errtext
[NUMBER_ERROR_MESSAGES
] =
55 { 0, 1,"Error %s running %s, line %d:|<value>,<source>,<linenumber>" },
56 { 0, 2,"Error %s in interactive trace:|<value>" },
57 { 0, 3,"Interactive trace. \"Trace Off\" to end debug. ENTER to continue." },
58 { 2, 0,"Failure during finalization" },
59 { 2, 1,"Failure during finalization: %s|<description>" },
60 { 3, 0,"Failure during initialization" },
61 { 3, 1,"Failure during initialization: %s|<description>" },
62 { 4, 0,"Program interrupted" },
63 { 4, 1,"Program interrupted with HALT condition: %s|<description>" },
64 { 5, 0,"System resources exhausted" },
65 { 5, 1,"System resources exhausted: %s|<description>" },
66 { 6, 0,"Unmatched \"/*\" or quote" },
67 { 6, 1,"Unmatched comment delimiter (\"/*\")" },
68 { 6, 2,"Unmatched single quote (')" },
69 { 6, 3,"Unmatched double quote (\")" },
70 { 7, 0,"WHEN or OTHERWISE expected" },
71 { 7, 1,"SELECT on line %d requires WHEN; found \"%s\"|<linenumber>,<token>" },
72 { 7, 2,"SELECT on line %d requires WHEN, OTHERWISE, or END; found \"%s\"|<linenumber>,<token>" },
73 { 7, 3,"All WHEN expressions of SELECT on line %d are false; OTHERWISE expected|<linenumber>" },
74 { 8, 0,"Unexpected THEN or ELSE" },
75 { 8, 1,"THEN has no corresponding IF or WHEN clause" },
76 { 8, 2,"ELSE has no corresponding THEN clause" },
77 { 9, 0,"Unexpected WHEN or OTHERWISE" },
78 { 9, 1,"WHEN has no corresponding SELECT" },
79 { 9, 2,"OTHERWISE has no corresponding SELECT" },
80 { 10, 0,"Unexpected or unmatched END" },
81 { 10, 1,"END has no corresponding DO or SELECT" },
82 { 10, 2,"END corresponding to DO on line %d must have a symbol following that matches the control variable (or no symbol); found \"%s\"|<linenumber>,<token>" },
83 { 10, 3,"END corresponding to DO on line %d must not have a symbol following it because there is no control variable; found \"%s\"|<linenumber>,<token>" },
84 { 10, 4,"END corresponding to SELECT on line %d must not have a symbol following; found \"%s\"|<linenumber>,<token>" },
85 { 10, 5,"END must not immediately follow THEN" },
86 { 10, 6,"END must not immediately follow ELSE" },
87 { 11, 0,"[Control stack full]" },
88 { 12, 0,"[Clause > 1024 characters]" },
89 { 13, 0,"Invalid character in program" },
90 { 13, 1,"Invalid character in program \"('%x'X)\"|<hex-encoding>" },
91 { 14, 0,"Incomplete DO/SELECT/IF" },
92 { 14, 1,"DO instruction requires a matching END" },
93 { 14, 2,"SELECT instruction requires a matching END" },
94 { 14, 3,"THEN requires a following instruction" },
95 { 14, 4,"ELSE requires a following instruction" },
96 { 15, 0,"Invalid hexadecimal or binary string" },
97 { 15, 1,"Invalid location of blank in position %d in hexadecimal string|<position>" },
98 { 15, 2,"Invalid location of blank in position %d in binary string|<position>" },
99 { 15, 3,"Only 0-9, a-f, A-F, and blank are valid in a hexadecimal string; found \"%c\"|<char>" },
100 { 15, 4,"Only 0, 1, and blank are valid in a binary string; found \"%c\"|<char>" },
101 { 16, 0,"Label not found" },
102 { 16, 1,"Label \"%s\" not found|<name>" },
103 { 16, 2,"Cannot SIGNAL to label \"%s\" because it is inside an IF, SELECT or DO group|<name>" },
104 { 16, 3,"Cannot invoke label \"%s\" because it is inside an IF, SELECT or DO group|<name>" },
105 { 17, 0,"Unexpected PROCEDURE" },
106 { 17, 1,"PROCEDURE is valid only when it is the first instruction executed after an internal CALL or function invocation" },
107 { 18, 0,"THEN expected" },
108 { 18, 1,"IF keyword on line %d requires matching THEN clause; found \"%s\"|<linenumber>,<token>" },
109 { 18, 2,"WHEN keyword on line %d requires matching THEN clause; found \"%s\"|<linenumber>,<token>" },
110 { 19, 0,"String or symbol expected" },
111 { 19, 1,"String or symbol expected after ADDRESS keyword; found \"%s\"|<token>" },
112 { 19, 2,"String or symbol expected after CALL keyword; found \"%s\"|<token>" },
113 { 19, 3,"String or symbol expected after NAME keyword; found \"%s\"|<token>" },
114 { 19, 4,"String or symbol expected after SIGNAL keyword; found \"%s\"|<token>" },
115 { 19, 6,"String or symbol expected after TRACE keyword; found \"%s\"|<token>" },
116 { 19, 7,"Symbol expected in parsing pattern; found \"%s\"|<token>" },
117 { 20, 0,"Name expected" },
118 { 20, 1,"Name required; found \"%s\"|<token>" },
119 { 20, 2,"Found \"%s\" where only a name is valid|<token>" },
120 { 21, 0,"Invalid data on end of clause" },
121 { 21, 1,"The clause ended at an unexpected token; found \"%s\"|<token>" },
122 { 22, 0,"Invalid character string" },
123 { 22, 1,"Invalid character string '%s'X|<hex-encoding>" },
124 { 23, 0,"Invalid data string" },
125 { 23, 1,"Invalid data string '%s'X|<hex-encoding>" },
126 { 24, 0,"Invalid TRACE request" },
127 { 24, 1,"TRACE request letter must be one of \"%s\"; found \"%c\"|ACEFILNOR,<value>" },
128 { 25, 0,"Invalid sub-keyword found" },
129 { 25, 1,"CALL ON must be followed by one of the keywords %s; found \"%s\"|<keywords>,<token>" },
130 { 25, 2,"CALL OFF must be followed by one of the keywords %s; found \"%s\"|<keywords>,<token>" },
131 { 25, 3,"SIGNAL ON must be followed by one of the keywords %s; found \"%s\"|<keywords>,<token>" },
132 { 25, 4,"SIGNAL OFF must be followed by one of the keywords %s; found \"%s\"|<keywords>,<token>" },
133 { 25, 5,"ADDRESS WITH must be followed by one of the keywords INPUT, OUTPUT or ERROR; found \"%s\"|<token>" },
134 { 25, 6,"INPUT must be followed by one of the keywords STREAM, STEM, LIFO, FIFO or NORMAL; found \"%s\"|<token>" },
135 { 25, 7,"OUTPUT must be followed by one of the keywords STREAM, STEM, LIFO, FIFO, APPEND, REPLACE or NORMAL; found \"%s\"|<token>" },
136 { 25, 8,"APPEND must be followed by one of the keywords STREAM, STEM, LIFO or FIFO; found \"%s\"|<token>" },
137 { 25, 9,"REPLACE must be followed by one of the keywords STREAM, STEM, LIFO or FIFO; found \"%s\"|<token>" },
138 { 25, 11,"NUMERIC FORM must be followed by one of the keywords %s; found \"%s\"|<keywords>,<token>" },
139 { 25, 12,"PARSE must be followed by one of the keywords %s; found \"%s\"|<keywords>,<token>" },
140 { 25, 13,"UPPER must be followed by one of the keywords %s; found \"%s\"|<keywords>,<token>" },
141 { 25, 14,"ERROR must be followed by one of the keywords STREAM, STEM, LIFO, FIFO, APPEND, REPLACE or NORMAL; found \"%s\"|<token>" },
142 { 25, 15,"NUMERIC must be followed by one of the keywords %s; found \"%s\"|<keywords>,<token>" },
143 { 25, 16,"FOREVER must be followed by one of the keywords %s; found \"%s\"|<keywords>,<token>" },
144 { 25, 17,"PROCEDURE must be followed by the keyword EXPOSE or nothing; found \"%s\"|<token>" },
145 { 26, 0,"Invalid whole number" },
146 { 26, 1,"Whole numbers must fit within current DIGITS setting(%d); found \"%s\"|<value>,<value>" },
147 { 26, 2,"Value of repetition count expression in DO instruction must be zero or a positive whole number; found \"%s\"|<value>" },
148 { 26, 3,"Value of FOR expression in DO instruction must be zero or a positive whole number; found \"%s\"|<value>" },
149 { 26, 4,"Positional parameter of parsing template must be a whole number; found \"%s\"|<value>" },
150 { 26, 5,"NUMERIC DIGITS value must be zero or a positive whole number; found \"%s\"|<value>" },
151 { 26, 6,"NUMERIC FUZZ value must be zero or a positive whole number; found \"%s\"|<value>" },
152 { 26, 7,"Number used in TRACE setting must be a whole number; found \"%s\"|<value>" },
153 { 26, 8,"Operand to right of power operator (\"**\") must be a whole number; found \"%s\"|<value>" },
154 { 26, 11,"Result of %s %% %s operation would need exponential notation at current NUMERIC DIGITS %d|<value>,<value>,<value>" },
155 { 26, 12,"Result of %% operation used for %s // %s operation would need exponential notation at current NUMERIC DIGITS %d|<value>,<value>,<value>" },
156 { 27, 0,"Invalid DO syntax" },
157 { 27, 1,"Invalid use of keyword \"%s\" in DO clause|<token>" },
158 { 28, 0,"Invalid LEAVE or ITERATE" },
159 { 28, 1,"LEAVE is valid only within a repetitive DO loop" },
160 { 28, 2,"ITERATE is valid only within a repetitive DO loop" },
161 { 28, 3,"Symbol following LEAVE (\"%s\") must either match control variable of a current DO loop or be omitted|<token>" },
162 { 28, 4,"Symbol following ITERATE (\"%s\") must either match control variable of a current DO loop or be omitted|<token>" },
163 { 29, 0,"Environment name too long" },
164 { 29, 1,"Environment name exceeds %d characters; found \"%s\"|#Limit_EnvironmentName,<name>" },
165 { 30, 0,"Name or string too long" },
166 { 30, 1,"Name exceeds %d characters|#Limit_Name" },
167 { 30, 2,"Literal string exceeds %d characters|#Limit_Literal" },
168 { 31, 0,"Name starts with number or \".\"" },
169 { 31, 1,"A value cannot be assigned to a number; found \"%s\"|<token>" },
170 { 31, 2,"Variable symbol must not start with a number; found \"%s\"|<token>" },
171 { 31, 3,"Variable symbol must not start with a \".\"; found \"%s\"|<token>" },
172 { 32, 0,"[Invalid use of stem]" },
173 { 33, 0,"Invalid expression result" },
174 { 33, 1,"Value of NUMERIC DIGITS \"%d\" must exceed value of NUMERIC FUZZ \"(%d)\"|<value>,<value>" },
175 { 33, 2,"Value of NUMERIC DIGITS \"%d\" must not exceed %d|<value>,#Limit_Digits" },
176 { 33, 3,"Result of expression following NUMERIC FORM must start with \"E\" or \"S\"; found \"%s\"|<value>" },
177 { 34, 0,"Logical value not \"0\" or \"1\"" },
178 { 34, 1,"Value of expression following IF keyword must be exactly \"0\" or \"1\"; found \"%s\"|<value>" },
179 { 34, 2,"Value of expression following WHEN keyword must be exactly \"0\" or \"1\"; found \"%s\"|<value>" },
180 { 34, 3,"Value of expression following WHILE keyword must be exactly \"0\" or \"1\"; found \"%s\"|<value>" },
181 { 34, 4,"Value of expression following UNTIL keyword must be exactly \"0\" or \"1\"; found \"%s\"|<value>" },
182 { 34, 5,"Value of expression to left of logical operator \"%s\" must be exactly \"0\" or \"1\"; found \"%s\"|<operator>,<value>" },
183 { 34, 6,"Value of expression to right of logical operator \"%s\" must be exactly \"0\" or \"1\"; found \"%s\"|<operator>,<value>" },
184 { 35, 0,"Invalid expression" },
185 { 35, 1,"Invalid expression detected at \"%s\"|<token>" },
186 { 36, 0,"Unmatched \"(\" in expression" },
187 { 37, 0,"Unexpected \",\" or \")\"" },
188 { 37, 1,"Unexpected \",\"" },
189 { 37, 2,"Unmatched \")\" in expression" },
190 { 38, 0,"Invalid template or pattern" },
191 { 38, 1,"Invalid parsing template detected at \"%s\"|<token>" },
192 { 38, 2,"Invalid parsing position detected at \"%s\"|<token>" },
193 { 38, 3,"PARSE VALUE instruction requires WITH keyword" },
194 { 39, 0,"[Evaluation stack overflow]" },
195 { 40, 0,"Incorrect call to routine" },
196 { 40, 1,"External routine \"%s\" failed|<name>" },
197 { 40, 3,"Not enough arguments in invocation of \"%s\"; minimum expected is %d|<bif>,<argnumber>" },
198 { 40, 4,"Too many arguments in invocation of \"%s\"; maximum expected is %d|<bif>,<argnumber>" },
199 { 40, 5,"Missing argument in invocation of \"%s\"; argument %d is required|<bif>,<argnumber>" },
200 { 40, 9,"%s argument %d exponent exceeds %d digits; found \"%s\"|<bif>,<argnumber>,#Limit_ExponentDigits,<value>" },
201 { 40, 11,"%s argument %d must be a number; found \"%s\"|<bif>,<argnumber>,<value>" },
202 { 40, 12,"%s argument %d must be a whole number; found \"%s\"|<bif>,<argnumber>,<value>" },
203 { 40, 13,"%s argument %d must be zero or positive; found \"%s\"|<bif>,<argnumber>,<value>" },
204 { 40, 14,"%s argument %d must be positive; found \"%s\"|<bif>,<argnumber>,<value>" },
205 { 40, 17,"%s argument 1, must have an integer part in the range 0:90 and a decimal part no larger than .9; found \"%s\"|<bif>,<value>" },
206 { 40, 18,"%s conversion must have a year in the range 0001 to 9999|<bif>" },
207 { 40, 19,"%s argument 2, \"%s\", is not in the format described by argument 3, \"%s\"|<bif>,<value>,<value>" },
208 { 40, 21,"%s argument %d must not be null|<bif>,<argnumber>" },
209 { 40, 23,"%s argument %d must be a single character; found \"%s\"|<bif>,<argnumber>,<value>" },
210 { 40, 24,"%s argument 1 must be a binary string; found \"%s\"|<bif>,<value>" },
211 { 40, 25,"%s argument 1 must be a hexadecimal string; found \"%s\"|<bif>,<value>" },
212 { 40, 26,"%s argument 1 must be a valid symbol; found \"%s\"|<bif>,<value>" },
213 { 40, 27,"%s argument 1, must be a valid stream name; found \"%s\"|<bif>,<value>" },
214 { 40, 28,"%s argument %d, option must start with one of \"%s\"; found \"%s\"|<bif>,<argnumber>,<optionslist>,<value>" },
215 { 40, 29,"%s conversion to format \"%s\" is not allowed|<bif>,<value>" },
216 { 40, 31,"%s argument 1 (\"%d\") must not exceed 100000|<bif>,<value>" },
217 { 40, 32,"%s the difference between argument 1 (\"%d\") and argument 2 (\"%d\") must not exceed 100000|<bif>,<value>,<value>" },
218 { 40, 33,"%s argument 1 (\"%d\") must be less than or equal to argument 2 (\"%d\")|<bif>,<value>,<value>" },
219 { 40, 34,"%s argument 1 (\"%d\") must be less than or equal to the number of lines in the program (%d)|<bif>,<value>,<sourceline()>" },
220 { 40, 35,"%s argument 1 cannot be expressed as a whole number; found \"%s\"|<bif>,<value>" },
221 { 40, 36,"%s argument 1 must be a name of a variable in the pool; found \"%s\"|<bif>,<value>" },
222 { 40, 37,"%s argument 3 must be the name of a pool; found \"%s\"|<bif>,<value>" },
223 { 40, 38,"%s argument %d is not large enough to format \"%s\"|<bif>,<argnumber>,<value>" },
224 { 40, 39,"%s argument 3 is not zero or one; found \"%s\"|<bif>,<value>" },
225 { 40, 41,"%s argument %d must be within the bounds of the stream; found \"%s\"|<bif>,<argnumber>,<value>" },
226 { 40, 42,"%s argument 1; cannot position on this stream; found \"%s\"|<bif>,<value>" },
227 { 40,914,"[%s argument %d, must be one of \"%s\"; found \"%s\"]|<bif>,<argnumber>,<optionslist>,<value>" },
228 { 40,920,"[%s: low-level stream I/O error; %s]|<bif>,<description>" },
229 { 40,921,"[%s argument %d, stream positioning mode \"%s\"; incompatible with stream open mode]|<bif>,<argnumber>,<value>" },
230 { 40,922,"[%s argument %d, too few sub-commands; minimum expected is %d; found %d]|<bif>,<argnumber>,<value>,<value>" },
231 { 40,923,"[%s argument %d, too many sub-commands; maximum expected is %d; found %d]|<bif>,<argnumber>,<value>,<value>" },
232 { 40,924,"[%s argument %d, invalid positional specification; expecting one of \"%s\"; found \"%s\"]|<bif>,<argnumber>,<value>,<value>" },
233 { 40,930,"[RXQUEUE, function TIMEOUT, expecting a whole number between 0 and %d; found \"%s\"]|<value>,<value>" },
234 { 40,980,"Unexpected input, either unknown type or illegal data%s%s|: ,<location>" },
235 { 40,981,"Number out of the allowed range%s%s|: ,<location>" },
236 { 40,982,"String too big for the defined buffer%s%s|: ,<location>" },
237 { 40,983,"Illegal combination of type/size%s%s|: ,<location>" },
238 { 40,984,"Unsupported number like NAN, +INF, -INF%s%s|: ,<location>" },
239 { 40,985,"Structure too complex for static internal buffer%s%s|: ,<location>" },
240 { 40,986,"An element of the structure is missing%s%s|: ,<location>" },
241 { 40,987,"A value of the structure is missing%s%s|: ,<location>" },
242 { 40,988,"The name or part of the name is illegal for the interpreter%s%s|: ,<location>" },
243 { 40,989,"A problem raises at the interface between Regina and GCI%s%s|: ,<location>" },
244 { 40,990,"The type won't fit the requirements for basic types (arguments/return value)%s%s|: ,<location>" },
245 { 40,991,"The number of arguments is wrong or an argument is missing%s%s|: ,<location>" },
246 { 40,992,"GCI's internal stack for arguments got an overflow%s%s|: ,<location>" },
247 { 40,993,"GCI counted too many nested LIKE containers%s%s|: ,<location>" },
248 { 41, 0,"Bad arithmetic conversion" },
249 { 41, 1,"Non-numeric value (\"%s\") to left of arithmetic operation \"%s\"|<value>,<operator>" },
250 { 41, 2,"Non-numeric value (\"%s\") to right of arithmetic operation \"%s\"|<value>,<operator>" },
251 { 41, 3,"Non-numeric value (\"%s\") used with prefix operator \"%s\"|<value>,<operator>" },
252 { 41, 4,"Value of TO expression in DO instruction must be numeric; found \"%s\"|<value>" },
253 { 41, 5,"Value of BY expression in DO instruction must be numeric; found \"%s\"|<value>" },
254 { 41, 6,"Value of control variable expression of DO instruction must be numeric; found \"%s\"|<value>" },
255 { 41, 7,"Exponent exceeds %d digits; found \"%s\"|#Limit_ExponentDigits,<value>" },
256 { 42, 0,"Arithmetic overflow/underflow" },
257 { 42, 1,"Arithmetic overflow detected at \"%s %s %s\"; exponent of result requires more than %d digits|<value>,<operator>,<value>,#Limit_ExponentDigits" },
258 { 42, 2,"Arithmetic underflow detected at \"%s %s %s\"; exponent of result requires more than %d digits|<value>,<operator>,<value>,#Limit_ExponentDigits" },
259 { 42, 3,"Arithmetic overflow; divisor must not be zero" },
260 { 43, 0,"Routine not found" },
261 { 43, 1,"Could not find routine \"%s\"|<name>" },
262 { 44, 0,"Function did not return data" },
263 { 44, 1,"No data returned from function \"%s\"|<name>" },
264 { 45, 0,"No data specified on function RETURN" },
265 { 45, 1,"Data expected on RETURN instruction because routine \"%s\" was called as a function|<name>" },
266 { 46, 0,"Invalid variable reference" },
267 { 46, 1,"Extra token (\"%s\") found in variable reference; \")\" expected|<token>" },
268 { 47, 0,"Unexpected label" },
269 { 47, 1,"INTERPRET data must not contain labels; found \"%s\"|<name>" },
270 { 48, 0,"Failure in system service" },
271 { 48, 1,"Failure in system service: %s|<description>" },
272 { 48,920,"Low-level stream I/O error: %s %s: %s|<description>,<stream>,<description>" },
273 { 49, 0,"Interpretation Error" },
274 { 49, 1,"Interpretation Error: Failed in %s, line %d: \"%s\". Please report error!|<module>,<linenumber>,<description>" },
275 { 50, 0,"Unrecognized reserved symbol" },
276 { 50, 1,"Unrecognized reserved symbol \"%s\"|<token>" },
277 { 51, 0,"Invalid function name" },
278 { 51, 1,"Unquoted function names must not end in a period; found \"%s\"|<token>" },
279 { 52, 0,"Result returned by \"%s\" is longer than %d characters|<name>,#Limit_String" },
280 { 53, 0,"Invalid option" },
281 { 53, 1,"String or symbol expected after STREAM keyword; found \"%s\"|<token>" },
282 { 53, 2,"Variable reference expected after STEM keyword; found \"%s\"|<token>" },
283 { 53, 3,"Argument to STEM must have one period, as its last character; found \"%s\"|<name>" },
284 { 53,100,"String or symbol expected after LIFO keyword; found \"%s\"|<token>" },
285 { 53,101,"String or symbol expected after FIFO keyword; found \"%s\"|<token>" },
286 { 54, 0,"Invalid STEM value" },
287 { 54, 1,"For this STEM APPEND, the value of \"%s\" must be a count of lines; found \"%s\"|<name>,<value>" },
288 { 60, 0,"[Can't rewind transient file]" },
289 { 61, 0,"[Improper seek operation on file]" },
290 { 64, 0,"[Syntax error while parsing]" },
291 { 64, 1,"[Syntax error at line %d]" },
292 { 64, 2,"[General syntax error at line %d, column %d]|<linenumber>,<columnnumber>" },
293 { 90, 0,"[Non-ANSI feature used with \"OPTIONS STRICT_ANSI\"]" },
294 { 90, 1,"[%s is a Regina extension BIF]|<bif>" },
295 { 90, 2,"[%s is a Regina extension instruction]|<token>" },
296 { 90, 3,"[%s argument %d, option must start with one of \"%s\" with \"OPTIONS STRICT_ANSI\"; found \"%s\"; a Regina extension]|<bif>,<argnumber>,<optionslist>,<value>" },
297 { 93, 0,"[Incorrect call to routine]" },
298 { 93, 1,"[STREAM command %s must be followed by one of \"%s\"; found \"%s\"]|<token>,<value>,<value>" },
299 { 93, 3,"[STREAM command must be one of \"%s\"; found \"%s\"]|<value>,<value>" },
300 { 94, 0,"[External queue interface error]" },
301 { 94, 1,"[External queue timed out]" },
302 { 94, 99,"[Internal error with external queue interface: %d \"%s\"]|<description>,<systemerror>" },
303 { 94,100,"[General system error with external queue interface. %s. %s]|<description>,<systemerror>" },
304 { 94,101,"[Error connecting to %s on port %d: \"%s\"]|<machine>,<portnumber>,<systemerror>" },
305 { 94,102,"[Unable to obtain IP address for %s]|<machine>" },
306 { 94,103,"[Invalid format for server in specified queue name: \"%s\"]|<queuename>" },
307 { 94,104,"[Invalid format for queue name: \"%s\"]|<queuename>" },
308 { 94,105,"[Unable to start Windows Socket interface: %s]|<systemerror>" },
309 { 94,106,"[Maximum number of external queues exceeded: %d]|<maxqueues>" },
310 { 94,107,"[Error occured reading socket: %s]|<systemerror>" },
311 { 94,108,"[Invalid switch passed. Must be one of \"%s\"]|<switch>" },
312 { 94,109,"[Queue \"%s\" not found]|<queuename>" },
313 { 94,110,"[%s invalid for external queues]|<bif>" },
314 { 94,111,"[RXQUEUE function %s invalid for internal queues]|<functionname>" },
315 { 95, 0,"[Restricted feature used in \"safe\" mode]" },
316 { 95, 1,"[%s invalid in \"safe\" mode]|<token>" },
317 { 95, 2,"[%s argument %d invalid in \"safe\" mode]|<bif>,<argnumber>" },
318 { 95, 3,"[%s argument %d: \"%s\", invalid in \"safe\" mode]|<bif>,<argnumber>,<token>" },
319 { 95, 4,"[STREAM argument 3: Opening files for WRITE access invalid in \"safe\" mode]" },
320 { 95, 5,"[Running external commands invalid in \"safe\" mode]" },
321 { 100, 0,"[Unknown filesystem error]" },
325 * Static pointers to language-specific error messages
326 * IF THIS EVER CHANGES, ALSO CHANGE THE SAME TABLE IN msgcmp.c
328 static const char *errlang
[] =
333 "no", /* norwegian */
334 "pt", /* portuguese */
341 static const char *err1prefix
[] =
343 /*en*/ "Error %d running \"%.*s\", line %d: %.*s",
344 /*de*/ "Fehler %d während des Ausführens von \"%.*s\", Zeile %d: %.*s",
345 /*es*/ "Error %d ejecutando \"%.*s\" línea %d: %.*s",
346 /*no*/ "Feil %d under kjøring av \"%.*s\" linje %d: %.*s",
347 /*pt*/ "Erro %d ao executar \"%.*s\", linha %d: %.*s",
348 /*pl*/ "Bˆ¥d %d podczas dziaˆania \"%.*s\", linia %d: %.*s",
349 /*sv*/ "Fel %d under k”rning av \"%.*s\", rad %d: %.*s",
350 /*tr*/ "%d hatasi \"%.*s\" calisiyorken %d numarali satirda olustu: %.*s",
353 static const char *suberrprefix
[] =
355 /*en*/ "Error %d.%d: %.*s",
356 /*de*/ "Fehler %d.%d: %.*s",
357 /*es*/ "Error %d.%d: %.*s",
358 /*no*/ "Feil %d.%d: %.*s",
359 /*pt*/ "Erro %d.%d: %.*s",
360 /*pl*/ "Bˆ¥d %d.%d: %.*s",
361 /*sv*/ "Fel %d.%d: %.*s",
362 /*tr*/ "Hata %d.%d: %.*s",
365 static const char *err2prefix
[] =
367 /*en*/ "Error %d running \"%.*s\": %.*s",
368 /*de*/ "Fehler %d während des Ausführens von \"%.*s\": %.*s",
369 /*es*/ "Error %d ejecutando \"%.*s\": %.*s",
370 /*no*/ "Feil %d under kjøring av \"%.*s\": %.*s",
371 /*pt*/ "Erro %d ao executar \"%.*s\": %.*s",
372 /*pl*/ "Bˆ¥d %d podczas dziaˆania \"%.*s\": %.*s",
373 /*sv*/ "Fel %d under k”rning av \"%.*s\": %.*s",
374 /*tr*/ "%d hatasi \"%.*s\" calisiyorken olustu: %.*s",
377 static const char *erropen
[] =
379 /*en*/ "Unable to open language file: %s",
380 /*de*/ "Kann die sprachspezifische Datei nicht öffnen: %s",
381 /*es*/ "Incapaz de abrir el fichero de lenguaje: %s",
382 /*no*/ "Ikke i stand til å åpne språkfil: %s",
383 /*pt*/ "nao eh possivel abrir arquivo de linguagem: %s",
384 /*pl*/ "Nie mo¾na otworzy† pliku j©zyka: %s",
385 /*sv*/ "Kan inte ”ppna spr†kfilen: %s",
386 /*tr*/ "Dil dosyasinin acilmasinda hata ile karsilasildi: %s",
389 static const char *errcount
[] =
391 /*en*/ "Incorrect number of messages in language file: %s",
392 /*de*/ "Ungültige Anzahl von Meldungen in der sprachspezifischen Datei: %s",
393 /*es*/ "Número incorrecto de mensajes en el fichero de lenguaje: %s",
394 /*no*/ "Uriktig antall meldinger i språkfil: %s",
395 /*pt*/ "numero incorreto de mensagens no arquivo de linguagem: %s",
396 /*pl*/ "Niepoprawna liczba komunikat¢w w pliku j©zyka: %s",
397 /*sv*/ "Felaktigt antal meddelanden i spr†kfilen: %s",
398 /*tr*/ "Dil dosyasindaki iletilerin sayisinda yanlislik var: %s",
401 static const char *errread
[] =
403 /*en*/ "Unable to read from language file: %s",
404 /*de*/ "Kann von der sprachspezifischen Datei nicht lesen: %s",
405 /*es*/ "Incapaz de leer el fichero de lenguaje: %s",
406 /*no*/ "Ikke i stand til å lese fra språkfil: %s",
407 /*pt*/ "nao eh possivel ler o arquivo de linguagem: %s",
408 /*pl*/ "Nie mo¾na czyta† z pliku j©zyka: %s",
409 /*sv*/ "Kan inte l„sa fr†n spr†kfilen: %s",
410 /*tr*/ "Dil dosyasinin okunmasinda hata ile karsilasildi: %s",
413 static const char *errmissing
[] =
415 /*en*/ "Text missing from language file: %s.mtb",
416 /*de*/ "Text fehlt in der sprachspezifischen Datei: %s.mtb",
417 /*es*/ "Falta el texto del fichero de lenguaje: %s.mtb",
418 /*no*/ "tekst mangler i språkfil: %s.mtb",
419 /*pt*/ "falta texto no arquivo de linguagem: %s.mtb",
420 /*pl*/ "Brakuje tekstu w pliku j©zyka: %s.mtb",
421 /*sv*/ "Text saknas i spr†kfilen: %s.mtb",
422 /*tr*/ "Dil dosyasinda eksik metin var: %s.mtb",
425 static const char *errcorrupt
[] =
427 /*en*/ "Language file: %s.mtb is corrupt",
428 /*de*/ "Sprachspezifische Datei %s.mtb ist beschädigt",
429 /*es*/ "Fichero de lenguaje: %s.mtb está corrupto",
430 /*no*/ "språkfil: %s.mtb er ødelagt",
431 /*pt*/ "arquivo de linguagem: %s.mtb estah corrompido",
432 /*pl*/ "Plik j©zyka: %s.mtb jest znieksztaˆcony",
433 /*sv*/ "Spr†kfilen: %s.mtb „r skadad",
434 /*tr*/ "%s.mtb ismindeki dil dosyasinda kirilma hatasi var",
437 static const char *get_embedded_text_message( int errorno
, int suberrorno
);
439 /* init_error initializes the module.
440 * Currently, we set up the thread specific data.
441 * The function returns 1 on success, 0 if memory is short.
443 int init_error( tsd_t
*TSD
)
447 if (TSD
->err_tsd
!= NULL
)
450 if ( ( TSD
->err_tsd
= MallocTSD( sizeof(err_tsd_t
) ) ) == NULL
)
452 et
= (err_tsd_t
*)TSD
->err_tsd
;
453 memset( et
, 0, sizeof(err_tsd_t
) );
454 et
->errornum
= Str_makeTSD( 3 * sizeof( int ) );
459 * get_buffer returns one buffer of those from the err_tsd_t. If not_this
460 * is set, that buffer will never be used. The buffer will have a size of
461 * at least minsize byte.
462 * A buffer is reallocated if there is no sufficient space in the best
464 * A returned buffer will always have a size of 0.
466 static streng
*get_buffer( const tsd_t
*TSD
, const streng
*not_this
,
469 err_tsd_t
*et
= (err_tsd_t
*)TSD
->err_tsd
;
476 if ( et
->buffer
[0] != NULL
)
477 l
[0] = Str_max( et
->buffer
[0] );
480 if ( et
->buffer
[1] != NULL
)
481 l
[1] = Str_max( et
->buffer
[1] );
485 if ( ( unsigned ) l
[1] >= minsize
)
488 if ( ( ( unsigned ) l
[0] >= minsize
) && ( l
[0] < l
[1] ) )
494 if ( ( not_this
!= NULL
) && ( et
->buffer
[idx
] == not_this
) )
495 idx
= ( idx
== 0 ) ? 1 : 0;
497 if ( ( unsigned ) l
[idx
] < minsize
)
500 * assigning very late prevents race conditions in case of errors.
502 p
= Str_makeTSD( minsize
);
503 if ( et
->buffer
[idx
] != NULL
)
504 Free_stringTSD( et
->buffer
[idx
] );
507 Str_len(et
->buffer
[idx
]) = 0;
509 return et
->buffer
[idx
];
512 int lineno_of( cnodeptr node
)
515 return (node
->lineno
>=0) ? node
->lineno
: 0 ;
520 /* only to be used by syntax and runtime errors, and the halt condition
521 * FIXME: FGC: This function is used while initializing the runtime system.
522 * Maybe, we don't have a functional tsd_t!
525 void exiterror( int errorno
, int suberrorno
, ... )
527 staticstreng( nofile
, "<name>" );
531 streng
*suberror_streng
=NULL
;
534 const streng
*fmt
, *etext
;
537 tsd_t
*TSD
= __regina_get_tsd(); /* The TSD should be fetched directly. This
538 * will help if someone corrupted a TSD as
540 * A "fresh" value is always better for
541 * tracking down ugly errors.
542 * Speed advantage is no reason here! */
543 et
= (err_tsd_t
*)TSD
->err_tsd
;
546 || ( ( errorno
== ERR_STORAGE_EXHAUSTED
) && ( et
->conditions
> 10 ) ) )
548 const char *out
= get_embedded_text_message( errorno
, 0 );
552 * We allow 10 pending errors only before doing a hard cleanup.
553 * You can use any fixed limit as far as we stop at some time when
554 * having a permanent memory allocation error.
555 * Just write a description end exit. DON'T DO USE A ROUTINE CALLING A
556 * MEMORY ALLOCATION ROUTINE!
558 if ( ( TSD
->currlevel
!= NULL
)
559 && get_options_flag( TSD
->currlevel
, EXT_STDOUT_FOR_STDERR
) )
562 fwrite( out
, len
, 1, fp
);
563 #if defined(DOS) || defined(OS2) || defined(WIN32)
565 * stdout is open in binary mode, so we need to add the
566 * extra CR to the end of the line.
568 fputc( REGINA_CR
, fp
);
570 fputc( REGINA_EOL
, fp
);
575 if ( TSD
->currentnode
)
577 lineno
= lineno_of( TSD
->currentnode
);
581 lineno
= parser_data
.tline
;
584 signtype
= SIGNAL_SYNTAX
;
585 if ( errorno
== ERR_PROG_INTERRUPT
)
586 signtype
= SIGNAL_HALT
;
589 * Expanded the sub-error text and pass this to condition_hook for
590 * condition('D') to return the expanded string.
592 if ( ( errorno
<= ERR_MAX_NUMBER
) && ( suberrorno
!= 0 ) )
594 fmt
= errortext( TSD
, errorno
, suberrorno
, 0, 0 );
595 len
= Str_len( fmt
);
596 len
+= strlen( suberrprefix
[et
->native_language
] );
597 len
+= 2 * ( ( sizeof(unsigned) * 8 ) / 3 + 2 );
598 errmsg
= get_buffer( TSD
, fmt
, len
+ 3 );
599 len
= sprintf( errmsg
->value
, suberrprefix
[et
->native_language
],
600 errorno
, suberrorno
, Str_len( fmt
), fmt
->value
);
602 va_start( argptr
, suberrorno
);
603 for ( i
= 0; i
< Str_len( fmt
); i
++ )
605 if ( fmt
->value
[i
] == '%' )
607 switch ( fmt
->value
[i
+1] )
610 len
+= strlen( va_arg( argptr
, char * ) );
614 /* assignment to anything inhibits compiler warnings */
615 ok
= (int) va_arg( argptr
, int );
618 case '%': /* Fixes 1107759 */
623 len
+= ( sizeof( unsigned ) * 8 ) / 3 + 2;
624 /* assignment to anything inhibits compiler warnings */
625 ok
= (int) va_arg( argptr
, unsigned );
632 suberror_streng
= Str_makeTSD( len
+ 1 );
633 if ( suberror_streng
)
635 va_start( argptr
, suberrorno
);
636 Str_len( suberror_streng
) = vsprintf( suberror_streng
->value
,
637 errmsg
->value
, argptr
);
643 /* Here we should set sigtype to SIGNAL_FATAL for some 'errno's */
645 /* Get the text for the base errorno */
646 etext
= errortext( TSD
, errorno
, 0, 0, 0 );
649 * Only in case of a SYNTAX error set .MN, ANSI 8.4.1
650 * Keep care of 64 bit machines. A huge number may contain 80 characters
651 * and we are not allowed to use ints, we have to use unsigneds.
653 if ( signtype
== SIGNAL_SYNTAX
)
655 char num
[2 * ( ( sizeof(unsigned) * 8 ) / 3 + 2 )];
659 sprintf( num
, "%u.%u", (unsigned) errorno
, (unsigned) suberrorno
);
660 set_reserved_value( TSD
, POOL0_MN
, Str_creTSD( num
), 0, VFLAG_STR
);
663 set_reserved_value( TSD
, POOL0_MN
, NULL
, errorno
, VFLAG_NUM
);
666 /* enable a hook into the condition system */
668 if ( condition_hook( TSD
, signtype
, errorno
, suberrorno
, lineno
,
669 Str_dupTSD( etext
), suberror_streng
) )
671 if ( suberror_streng
)
672 Free_stringTSD( suberror_streng
);
673 suberror_streng
= NULL
;
674 return ; /* if CALL ON */
678 if ( ( inputfile
= TSD
->systeminfo
->input_file
) == NULL
)
679 inputfile
= (streng
*) nofile
;
684 errmsg
= Str_makeTSD( 80 + Str_len( etext
) + Str_len( inputfile
) +
685 strlen( err1prefix
[et
->native_language
] ) );
686 sprintf( errmsg
->value
, err1prefix
[et
->native_language
],
687 errorno
, Str_len( inputfile
), inputfile
->value
, lineno
,
688 Str_len( etext
), etext
->value
);
692 errmsg
= Str_makeTSD( 80 + Str_len( etext
) + Str_len( inputfile
) +
693 strlen( err2prefix
[et
->native_language
] ) );
694 sprintf( errmsg
->value
, err2prefix
[et
->native_language
],
695 errorno
, Str_len( inputfile
), inputfile
->value
,
696 Str_len( etext
), etext
->value
);
699 errmsg
->len
= strlen( errmsg
->value
);
700 assert( errmsg
->len
< errmsg
->max
);
702 * If we have a system exit installed to handle errors, call it here...
705 if ( TSD
->systeminfo
->hooks
& HOOK_MASK( HOOK_STDERR
) )
706 ok
= hookup_output( TSD
, HOOK_STDERR
, errmsg
) == HOOK_GO_ON
;
708 if ( ok
== HOOK_GO_ON
)
711 * To get here we either don't have an exit handler or the exit
712 * handler refused to handle the message, so write it to the
713 * error (or output) stream.
715 if ( get_options_flag( TSD
->currlevel
, EXT_STDOUT_FOR_STDERR
) )
717 fwrite( errmsg
->value
, Str_len(errmsg
), 1, fp
);
718 #if defined(DOS) || defined(OS2) || defined(WIN32)
720 * stdout is open in binary mode, so we need to add the
721 * extra CR to the end of the line.
723 fputc( REGINA_CR
, fp
);
725 fputc( REGINA_EOL
, fp
);
728 * Display the sub-error text if there is one.
730 if ( ( errorno
<= ERR_MAX_NUMBER
) && suberrorno
&& suberror_streng
)
732 if ( TSD
->systeminfo
->hooks
& HOOK_MASK( HOOK_STDERR
) )
733 ok
= hookup_output(TSD
, HOOK_STDERR
, suberror_streng
) == HOOK_GO_ON
;
734 if ( ok
== HOOK_GO_ON
)
736 fwrite( suberror_streng
->value
, Str_len(suberror_streng
), 1, fp
);
737 #if defined(DOS) || defined(OS2) || defined(WIN32)
739 * stdout is open in binary mode, so we need to add the
740 * extra CR to the end of the line.
742 fputc( REGINA_CR
, fp
);
744 fputc( REGINA_EOL
, fp
);
747 if ( ok
== HOOK_GO_ON
)
749 if ( suberror_streng
)
750 Free_stringTSD( suberror_streng
);
752 Free_stringTSD( errmsg
);
756 if ( TSD
->systeminfo
->script_exit
)
758 TSD
->instore_is_errorfree
= 0;
762 * The error handler must inhibit the cleanup of errornum.
764 et
->errornum
->len
= sprintf( et
->errornum
->value
, "%d", -errorno
);
765 jump_script_exit( TSD
, et
->errornum
);
768 CloseOpenFiles( TSD
, fpdRETAIN
);
769 free_orphaned_libs( TSD
);
772 jump_interpreter_exit( TSD
, EXIT_SUCCESS
);
774 jump_interpreter_exit( TSD
, errorno
);
778 /* This function is called by the parser (syntactical interpreter) if an error
781 void __reginaerror(char *dummy
)
783 /* We ignore the message although it may contain useful informations. */
784 dummy
= dummy
; /* keep compiler happy */
789 * Returns a 0-terminated string in a streng which will be formatted by a
790 * "string formatter" which argument is arg. not_this will not be returned.
792 static streng
*simple_msg( const tsd_t
*TSD
, const char *fmt
,
793 const char *arg
, const streng
*not_this
)
795 int lf
= strlen( fmt
);
796 int la
= strlen( arg
);
799 retval
= get_buffer( TSD
, not_this
, lf
+ la
);
800 Str_len( retval
) = sprintf( retval
->value
, fmt
, arg
);
805 static streng
*read_index_header( const tsd_t
*TSD
, char *errfn
,
806 int native_language
, FILE **fp
,
807 int *number_messages
, int *file_lang
,
808 const streng
*not_this
)
812 et
= (err_tsd_t
*)TSD
->err_tsd
;
814 * Read the language file header...
816 *fp
= fopen( errfn
, "rb" );
819 return simple_msg( TSD
, erropen
[native_language
], errfn
, not_this
);
821 if ( fread( &et
->number_messages
, sizeof(unsigned int), 1, *fp
) != 1 )
824 return simple_msg( TSD
, errread
[native_language
], errfn
, not_this
);
826 if ( fread( file_lang
, sizeof(unsigned int), 1, *fp
) != 1 )
829 return simple_msg( TSD
, errread
[native_language
], errfn
, not_this
);
834 static streng
*read_index_file( const tsd_t
*TSD
, char *errfn
,
835 int native_language
, int language_file
,
836 FILE **fp
, struct textindex
*tmi
,
837 const streng
*not_this
)
843 et
= (err_tsd_t
*)TSD
->err_tsd
;
845 * Read the language file header...
847 if ( ( ptr
= read_index_header( TSD
, errfn
, native_language
, fp
, &et
->number_messages
, &file_lang
, not_this
) ) != NULL
)
849 et
->number_messages
= 0;
853 * Eunsure that the number of messages in the file matches the number defined as
854 * NUMBER_ERROR_MESSAGE in rexxmsg.h
856 if ( et
->number_messages
!= NUMBER_ERROR_MESSAGES
)
859 et
->number_messages
= 0;
860 return simple_msg( TSD
, errcount
[native_language
], errfn
, not_this
);
862 if ( fread( tmi
, sizeof(struct textindex
), NUMBER_ERROR_MESSAGES
, *fp
) != NUMBER_ERROR_MESSAGES
)
865 et
->number_messages
= 0;
866 return simple_msg( TSD
, errread
[native_language
], errfn
, not_this
);
872 * Called the first time we need to access an error message
873 * Determines which language file to open and read (always does English as well)
874 * Returns NULL on success, otherwise a pointer to an error message
876 static streng
*get_message_indexes( const tsd_t
*TSD
, const streng
*not_this
)
880 char fn
[REXX_PATH_MAX
+20];
883 #if defined(__EPOC32__) || defined(__WINS__)
885 int number_messages
, file_lang
;
891 et
= (err_tsd_t
*)TSD
->err_tsd
;
893 #if defined(__EPOC32__) || defined(__WINS__)
895 * Open the default.mtb and read the language type from it.
897 errpath
= "c:\\system\\apps\\reginarexx";
898 sprintf( fn
, "%s\\default.mtb", errpath
);
900 * If there is no default.mtb file, then default to English
902 if ( stat( fn
, &buffer
) != 0 )
904 et
->native_language
= LANGUAGE_ENGLISH
;
908 * We do have a default.mtb file, so read it to determine the language
910 if ( ( err
= read_index_header( TSD
, fn
, LANGUAGE_ENGLISH
, &fp
, &number_messages
, &file_lang
, not_this
) ) != NULL
)
912 et
->number_messages
= 0;
917 et
->native_language
= file_lang
;
919 ptr
= getenv( "REGINA_LANG" );
920 if ( ptr
== NULL
|| strlen( ptr
) == 0 )
922 et
->native_language
= LANGUAGE_ENGLISH
;
927 * REGINA_LANG may have a comma separated default locale appended.
929 int len
= strcspn( ptr
, "," );
930 for ( i
= 0; errlang
[i
] != NULL
; i
++ )
932 if ( ( (int) strlen( errlang
[i
] ) == len
)
933 && ( memcmp( ptr
, errlang
[i
], len
) == 0 ) )
935 et
->native_language
= i
;
942 err
= get_buffer( TSD
, not_this
, 40 + len
);
943 Str_len( err
) = sprintf( err
->value
, "Unsupported native language \"%.*s\"",
948 if ( et
->native_language
!= LANGUAGE_ENGLISH
)
950 errpath
= getenv( "REGINA_LANG_DIR" );
951 if ( errpath
== NULL
)
953 # if defined(REGINA_SHARE_DIRECTORY)
954 errpath
= REGINA_SHARE_DIRECTORY
;
956 return simple_msg( TSD
, "%s", "Unable to determine where Regina language files (*.mtb) are located. Set REGINA_LANG_DIR.", not_this
);
959 else if ( strlen( errpath
) > REXX_PATH_MAX
)
960 return simple_msg( TSD
, "Length of \"%s\" exceeds the path's maximum", errpath
, not_this
);
964 * Now read the native language file. If the native language is
965 * English, don't do anything.
967 if ( et
->native_language
!= LANGUAGE_ENGLISH
)
969 #if defined(__EPOC32__) || defined(__WINS__)
970 sprintf( fn
, "%s\\default.mtb", errpath
);
972 sprintf( fn
, "%s%c%s.mtb", errpath
, FILE_SEPARATOR
, errlang
[et
->native_language
] );
974 if ( ( err
= read_index_file( TSD
, fn
, et
->native_language
, et
->native_language
, &et
->nls_fp
, (struct textindex
*)&et
->nls_tmi
, not_this
) ) != NULL
)
980 static streng
*get_text_message( const tsd_t
*TSD
, FILE *fp
,
981 unsigned fileoffset
, unsigned textlength
,
982 int errorno
, int suberrorno
, int *is_fmt
,
983 const streng
*not_this
)
989 et
= (err_tsd_t
*)TSD
->err_tsd
;
991 #if defined(__EPOC32__) || defined(__WINS__)
994 errfn
=errlang
[et
->native_language
];
996 if ( fseek( fp
, fileoffset
, SEEK_SET
) == -1 )
999 return simple_msg( TSD
, errcorrupt
[et
->native_language
], errfn
, not_this
);
1002 retval
= get_buffer( TSD
, not_this
, textlength
+ 1 );
1003 if ( fread( retval
->value
, 1, textlength
, fp
) != textlength
)
1006 return simple_msg( TSD
, errcorrupt
[et
->native_language
], errfn
, not_this
);
1008 retval
->value
[textlength
] = '\0';
1009 Str_len(retval
) = textlength
;
1014 static const char *get_embedded_text_message( int errorno
, int suberrorno
)
1018 for ( i
= 0; i
< NUMBER_ERROR_MESSAGES
; i
++ )
1020 if ( errtext
[i
].errnum
== errorno
1021 && errtext
[i
].suberrnum
== suberrorno
)
1023 return errtext
[i
].text
;
1030 const streng
*errortext( const tsd_t
*TSD
, int errorno
, int suberrorno
, int request_english
, int apply_inserts
)
1032 int low
=0, mid
=0, end
=1, up
, have_inserts
=0, num_inserts
=0;
1033 int this_errorno
, this_suberrorno
;
1035 streng
*ptr
=NULL
,*h
;
1036 const char *errfn
,*embedded
;
1038 char *insert
[5]; /* maximum of 5 inserts allowed for any one message */
1042 * If the supplied errorno is > 100 (the internal limit for interpreter
1043 * errors), assume that a system error message is required.
1047 return simple_msg( TSD
, "%s", strerror(errorno
-100), NULL
);
1050 et
= (err_tsd_t
*)TSD
->err_tsd
;
1052 #if defined(__EPOC32__) || defined(__WINS__)
1055 errfn
=errlang
[et
->native_language
];
1058 * The first time this is called, determine the language and read the message file
1059 * indexes into memory from the message file.
1061 if ( et
->number_messages
== 0 )
1063 if ( ( ptr
= get_message_indexes( TSD
, NULL
) ) != NULL
)
1066 * Corrupt or missing language file. Prepend the returned message to the
1067 * embedded error message format.
1070 embedded
= get_embedded_text_message( errorno
, suberrorno
);
1071 h
= get_buffer( TSD
, ptr
, Str_len( ptr
) + strlen( embedded
) + 6 );
1072 Str_catstrTSD( h
, "(" );
1073 Str_catTSD( h
, ptr
);
1074 Str_catstrTSD( h
, ") " );
1075 Str_catstrTSD( h
, embedded
);
1076 h
->value
[Str_len( h
)] = '\0';
1081 * If we don't already have an error message,
1082 * and we are explicitly requesting an english message, or the native
1083 * language is English, then simply get the message from the internal
1088 if ( request_english
1089 || et
->native_language
== LANGUAGE_ENGLISH
)
1091 ptr
= simple_msg( TSD
, "%s", get_embedded_text_message( errorno
, suberrorno
), NULL
);
1095 up
= et
->number_messages
-1;
1097 while ((end
)&&(up
>=low
))
1100 this_errorno
= et
->nls_tmi
[mid
].errorno
;
1101 this_suberrorno
= et
->nls_tmi
[mid
].suberrorno
;
1102 if ( errorno
== this_errorno
1103 && suberrorno
== this_suberrorno
)
1108 if ( ( errorno
> this_errorno
)
1109 || ( errorno
== this_errorno
1110 && suberrorno
> this_suberrorno
) )
1118 * We couldn't find our message...
1120 embedded
= get_embedded_text_message( errorno
, suberrorno
);
1121 ptr
= simple_msg( TSD
, errmissing
[et
->native_language
], errfn
, NULL
);
1122 h
= get_buffer( TSD
, ptr
, Str_len( ptr
) + strlen( embedded
) + 6 );
1123 Str_catstrTSD( h
, "(" );
1124 Str_catTSD( h
, ptr
);
1125 Str_catstrTSD( h
, ") " );
1126 Str_catstrTSD( h
, embedded
);
1127 h
->value
[Str_len( h
)] = '\0';
1132 ptr
= get_text_message( TSD
, et
->nls_fp
, et
->nls_tmi
[mid
].fileoffset
, et
->nls_tmi
[mid
].textlength
, errorno
, suberrorno
, &is_fmt
, NULL
);
1135 embedded
= get_embedded_text_message( errorno
, suberrorno
);
1136 h
= get_buffer( TSD
, ptr
, Str_len( ptr
) + strlen( embedded
) + 6 );
1137 Str_catstrTSD( h
, "(" );
1138 Str_catTSD( h
, ptr
);
1139 Str_catstrTSD( h
, ") " );
1140 Str_catstrTSD( h
, embedded
);
1141 h
->value
[Str_len( h
)] = '\0';
1147 for ( low
= 0; low
< (int) Str_len( ptr
); low
++ )
1149 if ( ptr
->value
[low
] == '|' )
1151 ptr
->value
[low
] = '\0';
1152 Str_len( ptr
) = low
;
1158 * If we need to apply insert, then:
1159 * - adjust the returned fmt string replacing %c, %d, %x with %s
1160 * - iterate through the inserts ( ptr+low+1 )
1166 * The code below makes several assumptions about the format
1167 * of each message. All assumptions are based on having checked
1168 * the format of the messages using the checkmts.rexx script.
1170 for ( end
= 0; end
< Str_len( ptr
); end
++ )
1172 if ( ptr
->value
[end
] == '%' )
1174 switch( ptr
->value
[end
+1] ) /* assumes no message ends in % */
1182 ptr
->value
[end
+1] = 's';
1190 ins
= ptr
->value
+low
+1;
1192 low
= strlen( ins
);
1193 for ( mid
= 0,end
= 0; end
< low
; end
++ )
1195 if ( ins
[end
] == ',' )
1198 insert
[++mid
] = ins
+end
+1;
1201 h
= get_buffer( TSD
, ptr
, Str_len( ptr
) + low
+ 1 );
1202 switch( num_inserts
)
1205 Str_len( h
) = sprintf( h
->value
, ptr
->value
, insert
[0] );
1208 Str_len( h
) = sprintf( h
->value
, ptr
->value
, insert
[0], insert
[1] );
1211 Str_len( h
) = sprintf( h
->value
, ptr
->value
, insert
[0], insert
[1], insert
[2] );
1214 Str_len( h
) = sprintf( h
->value
, ptr
->value
, insert
[0], insert
[1], insert
[2], insert
[3] );
1217 Str_len( h
) = sprintf( h
->value
, ptr
->value
, insert
[0], insert
[1], insert
[2], insert
[3], insert
[4] );
1228 const char *getsym( int numb
)
1234 case X_NULL
: symb
="Null statement" ; break ;
1235 case X_PROGRAM
: symb
="Program" ; break ;
1236 case X_STATS
: symb
="Statements" ; break ;
1237 case X_COMMAND
: symb
="External command" ; break ;
1238 case X_ADDR_V
: symb
="ADDRESS (value) statement" ; break ;
1239 case X_ADDR_S
: symb
="ADDRESS" ; break ;
1240 case X_ADDR_N
: symb
="ADDRESS (normal) statement" ; break ;
1241 case X_CALL
: symb
="CALL statement" ; break ;
1242 case X_DO
: symb
="DO statement" ; break ;
1243 case X_REP
: symb
="Repetitor in DO" ; break ;
1244 case X_REP_FOREVER
: symb
="Forever in DO" ; break ;
1245 case X_DO_TO
: symb
="Upper limit in DO" ; break ;
1246 case X_DO_BY
: symb
="Step-size in DO" ; break ;
1247 case X_DO_FOR
: symb
="Max number in DO" ; break ;
1248 case X_WHILE
: symb
="WHILE expr in DO" ; break ;
1249 case X_UNTIL
: symb
="UNTIL expr in DO" ; break ;
1250 case X_DROP
: symb
="DROP statement" ; break ;
1251 case X_EXIT
: symb
="EXIT statement" ; break ;
1252 case X_IF
: symb
="IF statement" ; break ;
1253 case X_IPRET
: symb
="INTERPRET statement" ; break ;
1254 case X_ITERATE
: symb
="ITERATE statement" ; break ;
1255 case X_LABEL
: symb
="Label specification" ; break ;
1256 case X_LEAVE
: symb
="LEAVE statement" ; break ;
1257 case X_NUM_D
: symb
="NUMERIC DIGIT statement" ; break ;
1258 case X_NUM_F
: symb
="NUMERIC FORM statement" ; break ;
1259 case X_NUM_FUZZ
: symb
="NUMERIC FUZZ statement" ; break ;
1260 case X_NUM_SCI
: symb
="Scientific numeric form" ; break ;
1261 case X_NUM_ENG
: symb
="Engeenering scientific form" ; break ;
1262 case X_PARSE
: symb
="PARSE statement" ; break ;
1263 case X_PARSE_ARG
: symb
="PARSE ARG atatement" ; break ;
1264 case X_PARSE_EXT
: symb
="External parsing" ; break ;
1265 case X_PARSE_PULL
: symb
="Parse pull" ; break ;
1266 case X_PARSE_SRC
: symb
="Parse source" ; break ;
1267 case X_PARSE_VAR
: symb
="Parse variable" ; break ;
1268 case X_PARSE_VAL
: symb
="Parse value" ; break ;
1269 case X_PARSE_VER
: symb
="Parse version" ; break ;
1270 case X_PROC
: symb
="PROCEDURE statement" ; break ;
1271 case X_PULL
: symb
="PULL statement" ; break ;
1272 case X_PUSH
: symb
="PUSH statement" ; break ;
1273 case X_QUEUE
: symb
="QUEUE statement" ; break ;
1274 case X_RETURN
: symb
="RETURN statement" ; break ;
1275 case X_SAY
: symb
="SAY statement" ; break ;
1276 case X_SELECT
: symb
="SELECT statement" ; break ;
1277 case X_WHENS
: symb
="WHEN connector" ; break ;
1278 case X_WHEN
: symb
="WHEN clause" ; break ;
1279 case X_OTHERWISE
: symb
="OTHERWISE clause" ; break ;
1280 case X_SIG_VAL
: symb
="SIGNAL VALUE statement" ; break ;
1281 case X_SIG_LAB
: symb
="SIGNAL (label) statement" ; break ;
1282 case X_SIG_SET
: symb
="SIGNAL (setting) statement" ; break ;
1283 case X_ON
: symb
="Setting is ON" ; break ;
1284 case X_OFF
: symb
="Setting is OFF" ; break ;
1285 case X_S_ERROR
: symb
="ERROR option" ; break ;
1286 case X_S_HALT
: symb
="HALT option" ; break ;
1287 case X_S_NOVALUE
: symb
="NOVALUE option" ; break ;
1288 case X_S_SYNTAX
: symb
="SYNTAX option" ; break ;
1289 case X_TRACE
: symb
="TRACE statement" ; break ;
1290 case X_UPPER_VAR
: symb
="UPPER statement" ; break ;
1291 case X_ASSIGN
: symb
="Assignment" ; break ;
1292 case X_LOG_NOT
: symb
="Logical NOT" ; break ;
1293 case X_PLUSS
: symb
="Plus operator" ; break ;
1294 case X_EQUAL
: symb
="Equal operator" ; break ;
1295 case X_MINUS
: symb
="Minus operator" ; break ;
1296 case X_MULT
: symb
="Multiplication operator" ; break ;
1297 case X_DEVIDE
: symb
="Division operator" ; break ;
1298 case X_MODULUS
: symb
="Modulus operator" ; break ;
1299 case X_LOG_OR
: symb
="Logical or" ; break ;
1300 case X_LOG_AND
: symb
="Logical and" ; break ;
1301 case X_LOG_XOR
: symb
="Logical xor" ; break ;
1302 case X_EXP
: symb
="Exponent operator" ; break ;
1303 case X_CONCAT
: symb
="String concatenation" ; break ;
1304 case X_SPACE
: symb
="Space separator" ; break ;
1305 case X_GTE
: symb
="Greater than or equal operator" ; break ;
1306 case X_LTE
: symb
="Less than or equal operator" ; break ;
1307 case X_GT
: symb
="Greater than operator" ; break ;
1308 case X_LT
: symb
="Less than operator" ; break ;
1309 case X_DIFF
: symb
="Different operator" ; break ;
1310 case X_SIM_SYMBOL
: symb
="Simple symbol" ; break ;
1311 case X_CON_SYMBOL
: symb
="Constant symbol" ; break ;
1312 case X_STRING
: symb
="Constant string" ; break ;
1313 case X_U_MINUS
: symb
="Unary minus" ; break ;
1314 case X_S_EQUAL
: symb
="String equal operator" ; break ;
1315 case X_S_DIFF
: symb
="String different operator" ; break ;
1316 case X_INTDIV
: symb
="Integer division" ; break ;
1317 case X_EX_FUNC
: symb
="External function call" ; break ;
1318 case X_IN_FUNC
: symb
="Internal function call" ; break ;
1319 case X_TPL_SOLID
: symb
="Solid point in template" ; break ;
1320 case X_TPL_MVE
: symb
="Constant pattern" ; break ;
1321 case X_TPL_VAR
: symb
="Variable pattern" ; break ;
1322 case X_TPL_SYMBOL
: symb
="Variable in template" ; break ;
1323 case X_TPL_POINT
: symb
="Placeholder in template" ; break ;
1324 case X_NEG_OFFS
: symb
="Negative offset" ; break ;
1325 case X_POS_OFFS
: symb
="Positive offset" ; break ;
1326 case X_ABS_OFFS
: symb
="Absolute offset" ; break ;
1327 case X_EXPRLIST
: symb
="Expression connector" ; break ;
1328 case X_S_NOTREADY
: symb
="NOTREADY option" ; break ;
1329 case X_S_FAILURE
: symb
="FAILURE option" ; break ;
1330 case X_END
: symb
="End statement" ; break ;
1331 case X_CALL_SET
: symb
="CALL specification" ; break ;
1332 case X_NO_OTHERWISE
: symb
="No otherwise statement" ; break ;
1333 case X_IND_SYMBOL
: symb
="Indirect symbol" ; break ;
1334 case X_IS_INTERNAL
: symb
="Internal function" ; break ;
1335 case X_IS_BUILTIN
: symb
="Builtin function" ; break ;
1336 case X_IS_EXTERNAL
: symb
="External function" ; break ;
1337 case X_CTAIL_SYMBOL
: symb
="Constant tail symbol" ; break ;
1338 case X_VTAIL_SYMBOL
: symb
="Variable tail symbol" ; break ;
1339 case X_HEAD_SYMBOL
: symb
="Compound variable symbol" ; break ;
1340 case X_STEM_SYMBOL
: symb
="Stem variable symbol" ; break ;
1341 case X_SEQUAL
: symb
="Strictly equal operator" ; break ;
1342 case X_SDIFF
: symb
="Strictly different operator" ; break ;
1343 case X_SGT
: symb
="Strictly greater than operator" ; break ;
1344 case X_SGTE
: symb
="Strictly greater than or equal operator" ; break ;
1345 case X_SLT
: symb
="Strictly less than operator" ; break ;
1346 case X_SLTE
: symb
="Strictly less than or equal operator" ; break ;
1347 case X_NEQUAL
: symb
="Not equal operator" ; break ;
1348 case X_NDIFF
: symb
="Not different operator" ; break ;
1349 case X_NGT
: symb
="Not greater than operator" ; break ;
1350 case X_NGTE
: symb
="Not greater than or equal operator" ; break ;
1351 case X_NLT
: symb
="Not less than operator" ; break ;
1352 case X_NLTE
: symb
="Not less than or equal operator" ; break ;
1353 case X_NASSIGN
: symb
="Numeric Assignment" ; break ;
1354 case X_CEXPRLIST
: symb
="Expression list" ; break ;
1355 case X_U_PLUSS
: symb
="Unary Plus" ; break ;
1356 case X_OPTIONS
: symb
="OPTIONS statement" ; break ;
1357 case X_NUM_V
: symb
="NUMERIC FORM VALUE statement" ; break ;
1358 case X_NUM_DDEF
: symb
="NUMERIC DIGITS statement" ; break ;
1359 case X_NUM_FDEF
: symb
="NUMERIC FUZZ statement" ; break ;
1360 case X_NUM_FRMDEF
: symb
="NUMERIC FORM statement" ; break ;
1361 case X_S_NGT
: symb
="Strictly not greater than operator" ; break ;
1362 case X_S_NLT
: symb
="Strictly not less than operator" ; break ;
1363 case X_S_GT
: symb
="Strictly greater than operator" ; break ;
1364 case X_S_GTE
: symb
="Strictly greater than or equal operator" ; break ;
1365 case X_S_LT
: symb
="Strictly less than operator" ; break ;
1366 case X_S_LTE
: symb
="Strictly less than or equal operator" ; break ;
1367 case X_ADDR_WITH
: symb
="ADDRESS WITH option list" ; break ;
1368 case X_S_LOSTDIGITS
: symb
="LOSTDIGITS option" ; break ;
1369 case X_DO_EXPR
: symb
="Upper limit in DO" ; break ;
1370 default: symb
="Unrecognized value" ;
1376 #endif /* !NDEBUG */