@@ -32,14 +32,107 @@ static MCErrorRef s_out_of_memory_error = nil;
3232
3333// //////////////////////////////////////////////////////////////////////////////
3434
35+ static bool MCErrorFormatMessage (MCStringRef p_format, MCArrayRef p_info, MCStringRef& r_message)
36+ {
37+ MCAutoStringRef t_message;
38+ if (!MCStringCreateMutable (0 , &t_message))
39+ return false ;
40+
41+ uindex_t t_limit;
42+ t_limit = MCStringGetLength (p_format);
43+
44+ uindex_t t_index;
45+ t_index = 0 ;
46+ while (t_index < t_limit)
47+ {
48+ unichar_t t_char;
49+ t_char = MCStringGetCharAtIndex (p_format, t_index);
50+
51+ // If the sequence is '%{' and there is at least one more char after
52+ // the '%{' then assume it is a key index.
53+ if (t_char == ' %' &&
54+ t_index + 2 < t_limit &&
55+ MCStringGetCharAtIndex (p_format, t_index + 1 ) == ' {' )
56+ {
57+ MCAutoStringRef t_key_string;
58+ if (!MCStringCreateMutable (0 , &t_key_string))
59+ return false ;
60+
61+ t_index += 2 ;
62+ while (t_index < t_limit)
63+ {
64+ t_char = MCStringGetCharAtIndex (p_format, t_index);
65+ if (t_char == ' }' )
66+ break ;
67+
68+ if (!MCStringAppendChar (*t_key_string, t_char))
69+ return false ;
70+
71+ t_index += 1 ;
72+ }
73+
74+ // If it is a well-formed %{...} sequence then process it as a key
75+ // of the info array. Otherwise just append the accumulated string.
76+ if (t_char == ' }' )
77+ {
78+ MCNewAutoNameRef t_key;
79+ if (!MCNameCreate (*t_key_string, &t_key))
80+ return false ;
81+
82+ MCValueRef t_value;
83+ if (p_info != nil &&
84+ MCArrayFetchValue (p_info, false , *t_key, t_value))
85+ {
86+ MCAutoStringRef t_formatted_value;
87+ if (!MCStringFormat (&t_formatted_value, " %@" , t_value))
88+ return false ;
89+
90+ if (!MCStringAppend (*t_message, *t_formatted_value))
91+ return false ;
92+ }
93+ }
94+ else
95+ {
96+ if (!MCStringAppend (*t_message, *t_key_string))
97+ return false ;
98+ }
99+ }
100+ else if (t_char == ' %' &&
101+ t_index + 1 < t_limit &&
102+ MCStringGetCharAtIndex (p_format, t_index + 1 ) == ' %' )
103+ {
104+ if (!MCStringAppendChar (*t_message, ' %' ))
105+ return false ;
106+
107+ t_index += 1 ;
108+ }
109+ else
110+ {
111+ if (!MCStringAppendChar (*t_message, t_char))
112+ return false ;
113+ }
114+
115+ t_index += 1 ;
116+ }
117+
118+ r_message = MCValueRetain (*t_message);
119+
120+ return true ;
121+ }
122+
35123bool MCErrorCreate (MCTypeInfoRef p_typeinfo, MCArrayRef p_info, MCErrorRef& r_error)
36124{
37125 __MCError *self;
38126 if (!__MCValueCreate (kMCValueTypeCodeError , self))
39127 return false ;
40128
129+ if (!MCErrorFormatMessage (MCErrorTypeInfoGetMessage (p_typeinfo), p_info, self -> message))
130+ {
131+ MCValueRelease (self);
132+ return false ;
133+ }
134+
41135 self -> typeinfo = MCValueRetain (p_typeinfo);
42- self -> message = MCValueRetain (MCErrorTypeInfoGetMessage (p_typeinfo));
43136 if (p_info != nil)
44137 self -> info = MCValueRetain (p_info);
45138
@@ -134,6 +227,46 @@ bool MCErrorIsPending(void)
134227
135228// //////////////////////////////////////////////////////////////////////////////
136229
230+ bool MCErrorCreateAndThrow (MCTypeInfoRef p_error_type, ...)
231+ {
232+ MCAutoArrayRef t_info;
233+ if (!MCArrayCreateMutable (&t_info))
234+ return false ;
235+
236+ va_list t_args;
237+ va_start (t_args, p_error_type);
238+ for (;;)
239+ {
240+ const char *t_key;
241+ t_key = va_arg (t_args, const char *);
242+ if (t_key == nil)
243+ break ;
244+
245+ MCValueRef t_value;
246+ t_value = va_arg (t_args, MCValueRef);
247+
248+ // If a value is nil, then it means don't include it.
249+ if (t_value == nil)
250+ continue ;
251+
252+ MCNewAutoNameRef t_name;
253+ if (!MCNameCreateWithNativeChars ((const char_t *)t_key, strlen (t_key), &t_name))
254+ return false ;
255+
256+ if (!MCArrayStoreValue (*t_info, true , *t_name, t_value))
257+ return false ;
258+ }
259+ va_end (t_args);
260+
261+ MCAutoErrorRef t_error;
262+ if (!MCErrorCreate (p_error_type, *t_info, &t_error))
263+ return false ;
264+
265+ return MCErrorThrow (*t_error);
266+ }
267+
268+ // //////////////////////////////////////////////////////////////////////////////
269+
137270bool MCErrorThrowOutOfMemory (void )
138271{
139272 if (s_out_of_memory_error == nil &&
@@ -150,16 +283,9 @@ bool MCErrorThrowOutOfMemory(void)
150283 return false ;
151284}
152285
153- bool MCErrorThrowGeneric (void )
286+ bool MCErrorThrowGeneric (MCStringRef p_reason )
154287{
155- MCErrorRef t_error;
156- if (!MCErrorCreate (kMCGenericErrorTypeInfo , nil, t_error))
157- return false ;
158-
159- MCErrorThrow (t_error);
160- MCValueRelease (t_error);
161-
162- return false ;
288+ return MCErrorCreateAndThrow (kMCGenericErrorTypeInfo , " reason" , p_reason, nil);
163289}
164290
165291// //////////////////////////////////////////////////////////////////////////////
@@ -198,7 +324,7 @@ bool __MCErrorInitialize(void)
198324 return false ;
199325
200326 MCAutoTypeInfoRef t_ge_typeinfo;
201- if (!MCErrorTypeInfoCreate (MCNAME (" runtime" ), MCSTR (" unknown " ), &t_ge_typeinfo))
327+ if (!MCErrorTypeInfoCreate (MCNAME (" runtime" ), MCSTR (" %{reason} " ), &t_ge_typeinfo))
202328 return false ;
203329 if (!MCNamedTypeInfoCreate (MCNAME (" livecode.lang.GenericError" ), kMCGenericErrorTypeInfo ))
204330 return false ;
0 commit comments