aslerror.c revision 1.8 1 1.1 jruoho /******************************************************************************
2 1.1 jruoho *
3 1.1 jruoho * Module Name: aslerror - Error handling and statistics
4 1.1 jruoho *
5 1.1 jruoho *****************************************************************************/
6 1.1 jruoho
7 1.2 christos /*
8 1.7 christos * Copyright (C) 2000 - 2017, Intel Corp.
9 1.1 jruoho * All rights reserved.
10 1.1 jruoho *
11 1.2 christos * Redistribution and use in source and binary forms, with or without
12 1.2 christos * modification, are permitted provided that the following conditions
13 1.2 christos * are met:
14 1.2 christos * 1. Redistributions of source code must retain the above copyright
15 1.2 christos * notice, this list of conditions, and the following disclaimer,
16 1.2 christos * without modification.
17 1.2 christos * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 1.2 christos * substantially similar to the "NO WARRANTY" disclaimer below
19 1.2 christos * ("Disclaimer") and any redistribution must be conditioned upon
20 1.2 christos * including a substantially similar Disclaimer requirement for further
21 1.2 christos * binary redistribution.
22 1.2 christos * 3. Neither the names of the above-listed copyright holders nor the names
23 1.2 christos * of any contributors may be used to endorse or promote products derived
24 1.2 christos * from this software without specific prior written permission.
25 1.2 christos *
26 1.2 christos * Alternatively, this software may be distributed under the terms of the
27 1.2 christos * GNU General Public License ("GPL") version 2 as published by the Free
28 1.2 christos * Software Foundation.
29 1.2 christos *
30 1.2 christos * NO WARRANTY
31 1.2 christos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 1.2 christos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 1.2 christos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 1.2 christos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 1.2 christos * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 1.2 christos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 1.2 christos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 1.2 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 1.2 christos * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 1.2 christos * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 1.2 christos * POSSIBILITY OF SUCH DAMAGES.
42 1.2 christos */
43 1.1 jruoho
44 1.1 jruoho #include "aslcompiler.h"
45 1.1 jruoho
46 1.1 jruoho #define _COMPONENT ACPI_COMPILER
47 1.1 jruoho ACPI_MODULE_NAME ("aslerror")
48 1.1 jruoho
49 1.1 jruoho /* Local prototypes */
50 1.1 jruoho
51 1.1 jruoho static void
52 1.1 jruoho AeAddToErrorLog (
53 1.1 jruoho ASL_ERROR_MSG *Enode);
54 1.1 jruoho
55 1.8 christos static BOOLEAN
56 1.8 christos AslIsExceptionExpected (
57 1.8 christos UINT8 Level,
58 1.8 christos UINT16 MessageId);
59 1.8 christos
60 1.8 christos static BOOLEAN
61 1.8 christos AslIsExceptionDisabled (
62 1.8 christos UINT8 Level,
63 1.8 christos UINT16 MessageId);
64 1.8 christos
65 1.1 jruoho
66 1.2 christos /*******************************************************************************
67 1.2 christos *
68 1.3 christos * FUNCTION: AslAbort
69 1.3 christos *
70 1.3 christos * PARAMETERS: None
71 1.3 christos *
72 1.3 christos * RETURN: None
73 1.3 christos *
74 1.3 christos * DESCRIPTION: Dump the error log and abort the compiler. Used for serious
75 1.3 christos * I/O errors.
76 1.3 christos *
77 1.3 christos ******************************************************************************/
78 1.3 christos
79 1.3 christos void
80 1.3 christos AslAbort (
81 1.3 christos void)
82 1.3 christos {
83 1.3 christos
84 1.3 christos AePrintErrorLog (ASL_FILE_STDERR);
85 1.3 christos if (Gbl_DebugFlag)
86 1.3 christos {
87 1.3 christos /* Print error summary to stdout also */
88 1.3 christos
89 1.3 christos AePrintErrorLog (ASL_FILE_STDOUT);
90 1.3 christos }
91 1.3 christos
92 1.3 christos exit (1);
93 1.3 christos }
94 1.3 christos
95 1.3 christos
96 1.3 christos /*******************************************************************************
97 1.3 christos *
98 1.2 christos * FUNCTION: AeClearErrorLog
99 1.2 christos *
100 1.2 christos * PARAMETERS: None
101 1.2 christos *
102 1.2 christos * RETURN: None
103 1.2 christos *
104 1.2 christos * DESCRIPTION: Empty the error list
105 1.2 christos *
106 1.2 christos ******************************************************************************/
107 1.2 christos
108 1.1 jruoho void
109 1.1 jruoho AeClearErrorLog (
110 1.1 jruoho void)
111 1.1 jruoho {
112 1.1 jruoho ASL_ERROR_MSG *Enode = Gbl_ErrorLog;
113 1.1 jruoho ASL_ERROR_MSG *Next;
114 1.1 jruoho
115 1.1 jruoho /* Walk the error node list */
116 1.1 jruoho
117 1.1 jruoho while (Enode)
118 1.1 jruoho {
119 1.1 jruoho Next = Enode->Next;
120 1.1 jruoho ACPI_FREE (Enode);
121 1.1 jruoho Enode = Next;
122 1.1 jruoho }
123 1.1 jruoho
124 1.1 jruoho Gbl_ErrorLog = NULL;
125 1.1 jruoho }
126 1.1 jruoho
127 1.1 jruoho
128 1.1 jruoho /*******************************************************************************
129 1.1 jruoho *
130 1.1 jruoho * FUNCTION: AeAddToErrorLog
131 1.1 jruoho *
132 1.1 jruoho * PARAMETERS: Enode - An error node to add to the log
133 1.1 jruoho *
134 1.1 jruoho * RETURN: None
135 1.1 jruoho *
136 1.2 christos * DESCRIPTION: Add a new error node to the error log. The error log is
137 1.1 jruoho * ordered by the "logical" line number (cumulative line number
138 1.1 jruoho * including all include files.)
139 1.1 jruoho *
140 1.1 jruoho ******************************************************************************/
141 1.1 jruoho
142 1.1 jruoho static void
143 1.1 jruoho AeAddToErrorLog (
144 1.1 jruoho ASL_ERROR_MSG *Enode)
145 1.1 jruoho {
146 1.1 jruoho ASL_ERROR_MSG *Next;
147 1.1 jruoho ASL_ERROR_MSG *Prev;
148 1.1 jruoho
149 1.1 jruoho
150 1.1 jruoho /* If Gbl_ErrorLog is null, this is the first error node */
151 1.1 jruoho
152 1.1 jruoho if (!Gbl_ErrorLog)
153 1.1 jruoho {
154 1.1 jruoho Gbl_ErrorLog = Enode;
155 1.1 jruoho return;
156 1.1 jruoho }
157 1.1 jruoho
158 1.1 jruoho /*
159 1.1 jruoho * Walk error list until we find a line number greater than ours.
160 1.1 jruoho * List is sorted according to line number.
161 1.1 jruoho */
162 1.1 jruoho Prev = NULL;
163 1.1 jruoho Next = Gbl_ErrorLog;
164 1.1 jruoho
165 1.1 jruoho while ((Next) &&
166 1.1 jruoho (Next->LogicalLineNumber <= Enode->LogicalLineNumber))
167 1.1 jruoho {
168 1.1 jruoho Prev = Next;
169 1.1 jruoho Next = Next->Next;
170 1.1 jruoho }
171 1.1 jruoho
172 1.1 jruoho /* Found our place in the list */
173 1.1 jruoho
174 1.1 jruoho Enode->Next = Next;
175 1.1 jruoho
176 1.1 jruoho if (Prev)
177 1.1 jruoho {
178 1.1 jruoho Prev->Next = Enode;
179 1.1 jruoho }
180 1.1 jruoho else
181 1.1 jruoho {
182 1.1 jruoho Gbl_ErrorLog = Enode;
183 1.1 jruoho }
184 1.1 jruoho }
185 1.1 jruoho
186 1.1 jruoho
187 1.1 jruoho /*******************************************************************************
188 1.1 jruoho *
189 1.1 jruoho * FUNCTION: AePrintException
190 1.1 jruoho *
191 1.1 jruoho * PARAMETERS: FileId - ID of output file
192 1.1 jruoho * Enode - Error node to print
193 1.1 jruoho * Header - Additional text before each message
194 1.1 jruoho *
195 1.1 jruoho * RETURN: None
196 1.1 jruoho *
197 1.1 jruoho * DESCRIPTION: Print the contents of an error node.
198 1.1 jruoho *
199 1.1 jruoho * NOTE: We don't use the FlxxxFile I/O functions here because on error
200 1.1 jruoho * they abort the compiler and call this function! Since we
201 1.1 jruoho * are reporting errors here, we ignore most output errors and
202 1.1 jruoho * just try to get out as much as we can.
203 1.1 jruoho *
204 1.1 jruoho ******************************************************************************/
205 1.1 jruoho
206 1.1 jruoho void
207 1.1 jruoho AePrintException (
208 1.1 jruoho UINT32 FileId,
209 1.1 jruoho ASL_ERROR_MSG *Enode,
210 1.1 jruoho char *Header)
211 1.1 jruoho {
212 1.1 jruoho UINT8 SourceByte;
213 1.1 jruoho int Actual;
214 1.1 jruoho size_t RActual;
215 1.1 jruoho UINT32 MsgLength;
216 1.3 christos const char *MainMessage;
217 1.1 jruoho char *ExtraMessage;
218 1.1 jruoho UINT32 SourceColumn;
219 1.1 jruoho UINT32 ErrorColumn;
220 1.1 jruoho FILE *OutputFile;
221 1.2 christos FILE *SourceFile = NULL;
222 1.2 christos long FileSize;
223 1.2 christos BOOLEAN PrematureEOF = FALSE;
224 1.2 christos UINT32 Total = 0;
225 1.1 jruoho
226 1.1 jruoho
227 1.1 jruoho if (Gbl_NoErrors)
228 1.1 jruoho {
229 1.1 jruoho return;
230 1.1 jruoho }
231 1.1 jruoho
232 1.1 jruoho /*
233 1.1 jruoho * Only listing files have a header, and remarks/optimizations
234 1.1 jruoho * are always output
235 1.1 jruoho */
236 1.1 jruoho if (!Header)
237 1.1 jruoho {
238 1.1 jruoho /* Ignore remarks if requested */
239 1.1 jruoho
240 1.1 jruoho switch (Enode->Level)
241 1.1 jruoho {
242 1.2 christos case ASL_WARNING:
243 1.2 christos case ASL_WARNING2:
244 1.2 christos case ASL_WARNING3:
245 1.2 christos
246 1.2 christos if (!Gbl_DisplayWarnings)
247 1.2 christos {
248 1.2 christos return;
249 1.2 christos }
250 1.2 christos break;
251 1.2 christos
252 1.1 jruoho case ASL_REMARK:
253 1.2 christos
254 1.1 jruoho if (!Gbl_DisplayRemarks)
255 1.1 jruoho {
256 1.1 jruoho return;
257 1.1 jruoho }
258 1.1 jruoho break;
259 1.1 jruoho
260 1.1 jruoho case ASL_OPTIMIZATION:
261 1.2 christos
262 1.1 jruoho if (!Gbl_DisplayOptimizations)
263 1.1 jruoho {
264 1.1 jruoho return;
265 1.1 jruoho }
266 1.1 jruoho break;
267 1.1 jruoho
268 1.1 jruoho default:
269 1.2 christos
270 1.1 jruoho break;
271 1.1 jruoho }
272 1.1 jruoho }
273 1.1 jruoho
274 1.2 christos /* Get the various required file handles */
275 1.1 jruoho
276 1.1 jruoho OutputFile = Gbl_Files[FileId].Handle;
277 1.2 christos
278 1.2 christos if (!Enode->SourceLine)
279 1.2 christos {
280 1.6 christos /*
281 1.6 christos * Use the merged header/source file if present, otherwise
282 1.6 christos * use input file
283 1.6 christos */
284 1.2 christos SourceFile = Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Handle;
285 1.2 christos if (!SourceFile)
286 1.2 christos {
287 1.2 christos SourceFile = Gbl_Files[ASL_FILE_INPUT].Handle;
288 1.2 christos }
289 1.2 christos
290 1.2 christos if (SourceFile)
291 1.2 christos {
292 1.2 christos /* Determine if the error occurred at source file EOF */
293 1.2 christos
294 1.2 christos fseek (SourceFile, 0, SEEK_END);
295 1.2 christos FileSize = ftell (SourceFile);
296 1.2 christos
297 1.2 christos if ((long) Enode->LogicalByteOffset >= FileSize)
298 1.2 christos {
299 1.2 christos PrematureEOF = TRUE;
300 1.2 christos }
301 1.2 christos }
302 1.2 christos }
303 1.1 jruoho
304 1.1 jruoho if (Header)
305 1.1 jruoho {
306 1.1 jruoho fprintf (OutputFile, "%s", Header);
307 1.1 jruoho }
308 1.1 jruoho
309 1.1 jruoho /* Print filename and line number if present and valid */
310 1.1 jruoho
311 1.1 jruoho if (Enode->Filename)
312 1.1 jruoho {
313 1.1 jruoho if (Gbl_VerboseErrors)
314 1.1 jruoho {
315 1.2 christos fprintf (OutputFile, "%-8s", Enode->Filename);
316 1.1 jruoho
317 1.1 jruoho if (Enode->LineNumber)
318 1.1 jruoho {
319 1.2 christos if (Enode->SourceLine)
320 1.1 jruoho {
321 1.2 christos fprintf (OutputFile, " %6u: %s",
322 1.2 christos Enode->LineNumber, Enode->SourceLine);
323 1.1 jruoho }
324 1.1 jruoho else
325 1.1 jruoho {
326 1.2 christos fprintf (OutputFile, " %6u: ", Enode->LineNumber);
327 1.2 christos
328 1.2 christos /*
329 1.6 christos * If not at EOF, get the corresponding source code line
330 1.6 christos * and display it. Don't attempt this if we have a
331 1.6 christos * premature EOF condition.
332 1.2 christos */
333 1.2 christos if (!PrematureEOF)
334 1.1 jruoho {
335 1.2 christos /*
336 1.6 christos * Seek to the offset in the combined source file,
337 1.6 christos * read the source line, and write it to the output.
338 1.2 christos */
339 1.6 christos Actual = fseek (SourceFile,
340 1.6 christos (long) Enode->LogicalByteOffset, (int) SEEK_SET);
341 1.2 christos if (Actual)
342 1.2 christos {
343 1.2 christos fprintf (OutputFile,
344 1.2 christos "[*** iASL: Seek error on source code temp file %s ***]",
345 1.2 christos Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename);
346 1.2 christos }
347 1.2 christos else
348 1.2 christos {
349 1.2 christos RActual = fread (&SourceByte, 1, 1, SourceFile);
350 1.2 christos if (RActual != 1)
351 1.2 christos {
352 1.2 christos fprintf (OutputFile,
353 1.2 christos "[*** iASL: Read error on source code temp file %s ***]",
354 1.2 christos Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename);
355 1.2 christos }
356 1.2 christos else
357 1.2 christos {
358 1.2 christos /* Read/write the source line, up to the maximum line length */
359 1.2 christos
360 1.2 christos while (RActual && SourceByte && (SourceByte != '\n'))
361 1.2 christos {
362 1.2 christos if (Total < 256)
363 1.2 christos {
364 1.2 christos /* After the max line length, we will just read the line, no write */
365 1.2 christos
366 1.2 christos if (fwrite (&SourceByte, 1, 1, OutputFile) != 1)
367 1.2 christos {
368 1.2 christos printf ("[*** iASL: Write error on output file ***]\n");
369 1.2 christos return;
370 1.2 christos }
371 1.2 christos }
372 1.2 christos else if (Total == 256)
373 1.2 christos {
374 1.2 christos fprintf (OutputFile,
375 1.2 christos "\n[*** iASL: Very long input line, message below refers to column %u ***]",
376 1.2 christos Enode->Column);
377 1.2 christos }
378 1.2 christos
379 1.2 christos RActual = fread (&SourceByte, 1, 1, SourceFile);
380 1.2 christos if (RActual != 1)
381 1.2 christos {
382 1.2 christos fprintf (OutputFile,
383 1.2 christos "[*** iASL: Read error on source code temp file %s ***]",
384 1.2 christos Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename);
385 1.2 christos return;
386 1.2 christos }
387 1.2 christos Total++;
388 1.2 christos }
389 1.2 christos }
390 1.2 christos }
391 1.1 jruoho }
392 1.1 jruoho
393 1.2 christos fprintf (OutputFile, "\n");
394 1.1 jruoho }
395 1.1 jruoho }
396 1.1 jruoho }
397 1.1 jruoho else
398 1.1 jruoho {
399 1.2 christos /*
400 1.2 christos * Less verbose version of the error message, enabled via the
401 1.2 christos * -vi switch. The format is compatible with MS Visual Studio.
402 1.2 christos */
403 1.1 jruoho fprintf (OutputFile, "%s", Enode->Filename);
404 1.1 jruoho
405 1.1 jruoho if (Enode->LineNumber)
406 1.1 jruoho {
407 1.2 christos fprintf (OutputFile, "(%u) : ",
408 1.2 christos Enode->LineNumber);
409 1.1 jruoho }
410 1.1 jruoho }
411 1.1 jruoho }
412 1.1 jruoho
413 1.3 christos /* If a NULL message ID, just print the raw message */
414 1.1 jruoho
415 1.1 jruoho if (Enode->MessageId == 0)
416 1.1 jruoho {
417 1.1 jruoho fprintf (OutputFile, "%s\n", Enode->Message);
418 1.3 christos return;
419 1.3 christos }
420 1.3 christos
421 1.3 christos /* Decode the message ID */
422 1.3 christos
423 1.3 christos fprintf (OutputFile, "%s %4.4d -",
424 1.3 christos AeDecodeExceptionLevel (Enode->Level),
425 1.3 christos AeBuildFullExceptionCode (Enode->Level, Enode->MessageId));
426 1.3 christos
427 1.3 christos MainMessage = AeDecodeMessageId (Enode->MessageId);
428 1.3 christos ExtraMessage = Enode->Message;
429 1.3 christos
430 1.3 christos /* If a NULL line number, just print the decoded message */
431 1.3 christos
432 1.3 christos if (!Enode->LineNumber)
433 1.3 christos {
434 1.3 christos fprintf (OutputFile, " %s %s\n\n", MainMessage, ExtraMessage);
435 1.3 christos return;
436 1.1 jruoho }
437 1.3 christos
438 1.3 christos MsgLength = strlen (MainMessage);
439 1.3 christos if (MsgLength == 0)
440 1.1 jruoho {
441 1.3 christos /* Use the secondary/extra message as main message */
442 1.1 jruoho
443 1.3 christos MainMessage = Enode->Message;
444 1.3 christos if (!MainMessage)
445 1.2 christos {
446 1.3 christos MainMessage = "";
447 1.2 christos }
448 1.3 christos
449 1.3 christos MsgLength = strlen (MainMessage);
450 1.3 christos ExtraMessage = NULL;
451 1.3 christos }
452 1.3 christos
453 1.3 christos if (Gbl_VerboseErrors && !PrematureEOF)
454 1.3 christos {
455 1.3 christos if (Total >= 256)
456 1.2 christos {
457 1.3 christos fprintf (OutputFile, " %s",
458 1.3 christos MainMessage);
459 1.2 christos }
460 1.3 christos else
461 1.1 jruoho {
462 1.3 christos SourceColumn = Enode->Column + Enode->FilenameLength + 6 + 2;
463 1.3 christos ErrorColumn = ASL_ERROR_LEVEL_LENGTH + 5 + 2 + 1;
464 1.2 christos
465 1.3 christos if ((MsgLength + ErrorColumn) < (SourceColumn - 1))
466 1.2 christos {
467 1.3 christos fprintf (OutputFile, "%*s%s",
468 1.3 christos (int) ((SourceColumn - 1) - ErrorColumn),
469 1.3 christos MainMessage, " ^ ");
470 1.1 jruoho }
471 1.1 jruoho else
472 1.1 jruoho {
473 1.3 christos fprintf (OutputFile, "%*s %s",
474 1.3 christos (int) ((SourceColumn - ErrorColumn) + 1), "^",
475 1.3 christos MainMessage);
476 1.1 jruoho }
477 1.3 christos }
478 1.3 christos }
479 1.3 christos else
480 1.3 christos {
481 1.3 christos fprintf (OutputFile, " %s", MainMessage);
482 1.3 christos }
483 1.1 jruoho
484 1.3 christos /* Print the extra info message if present */
485 1.1 jruoho
486 1.3 christos if (ExtraMessage)
487 1.3 christos {
488 1.3 christos fprintf (OutputFile, " (%s)", ExtraMessage);
489 1.3 christos }
490 1.1 jruoho
491 1.3 christos if (PrematureEOF)
492 1.3 christos {
493 1.3 christos fprintf (OutputFile, " and premature End-Of-File");
494 1.3 christos }
495 1.2 christos
496 1.3 christos fprintf (OutputFile, "\n");
497 1.3 christos if (Gbl_VerboseErrors)
498 1.3 christos {
499 1.3 christos fprintf (OutputFile, "\n");
500 1.1 jruoho }
501 1.1 jruoho }
502 1.1 jruoho
503 1.1 jruoho
504 1.1 jruoho /*******************************************************************************
505 1.1 jruoho *
506 1.1 jruoho * FUNCTION: AePrintErrorLog
507 1.1 jruoho *
508 1.1 jruoho * PARAMETERS: FileId - Where to output the error log
509 1.1 jruoho *
510 1.1 jruoho * RETURN: None
511 1.1 jruoho *
512 1.1 jruoho * DESCRIPTION: Print the entire contents of the error log
513 1.1 jruoho *
514 1.1 jruoho ******************************************************************************/
515 1.1 jruoho
516 1.1 jruoho void
517 1.1 jruoho AePrintErrorLog (
518 1.1 jruoho UINT32 FileId)
519 1.1 jruoho {
520 1.1 jruoho ASL_ERROR_MSG *Enode = Gbl_ErrorLog;
521 1.1 jruoho
522 1.1 jruoho
523 1.1 jruoho /* Walk the error node list */
524 1.1 jruoho
525 1.1 jruoho while (Enode)
526 1.1 jruoho {
527 1.1 jruoho AePrintException (FileId, Enode, NULL);
528 1.1 jruoho Enode = Enode->Next;
529 1.1 jruoho }
530 1.1 jruoho }
531 1.1 jruoho
532 1.1 jruoho
533 1.1 jruoho /*******************************************************************************
534 1.1 jruoho *
535 1.2 christos * FUNCTION: AslCommonError2
536 1.2 christos *
537 1.2 christos * PARAMETERS: Level - Seriousness (Warning/error, etc.)
538 1.2 christos * MessageId - Index into global message buffer
539 1.2 christos * LineNumber - Actual file line number
540 1.2 christos * Column - Column in current line
541 1.2 christos * SourceLine - Actual source code line
542 1.2 christos * Filename - source filename
543 1.2 christos * ExtraMessage - additional error message
544 1.2 christos *
545 1.2 christos * RETURN: None
546 1.2 christos *
547 1.2 christos * DESCRIPTION: Create a new error node and add it to the error log
548 1.2 christos *
549 1.2 christos ******************************************************************************/
550 1.2 christos
551 1.2 christos void
552 1.2 christos AslCommonError2 (
553 1.2 christos UINT8 Level,
554 1.3 christos UINT16 MessageId,
555 1.2 christos UINT32 LineNumber,
556 1.2 christos UINT32 Column,
557 1.2 christos char *SourceLine,
558 1.2 christos char *Filename,
559 1.2 christos char *ExtraMessage)
560 1.2 christos {
561 1.2 christos char *MessageBuffer = NULL;
562 1.2 christos char *LineBuffer;
563 1.2 christos ASL_ERROR_MSG *Enode;
564 1.2 christos
565 1.2 christos
566 1.2 christos Enode = UtLocalCalloc (sizeof (ASL_ERROR_MSG));
567 1.2 christos
568 1.2 christos if (ExtraMessage)
569 1.2 christos {
570 1.2 christos /* Allocate a buffer for the message and a new error node */
571 1.2 christos
572 1.3 christos MessageBuffer = UtStringCacheCalloc (strlen (ExtraMessage) + 1);
573 1.2 christos
574 1.2 christos /* Keep a copy of the extra message */
575 1.2 christos
576 1.5 christos strcpy (MessageBuffer, ExtraMessage);
577 1.2 christos }
578 1.2 christos
579 1.2 christos LineBuffer = UtLocalCalloc (strlen (SourceLine) + 1);
580 1.5 christos strcpy (LineBuffer, SourceLine);
581 1.2 christos
582 1.2 christos /* Initialize the error node */
583 1.2 christos
584 1.2 christos if (Filename)
585 1.2 christos {
586 1.3 christos Enode->Filename = Filename;
587 1.2 christos Enode->FilenameLength = strlen (Filename);
588 1.2 christos if (Enode->FilenameLength < 6)
589 1.2 christos {
590 1.2 christos Enode->FilenameLength = 6;
591 1.2 christos }
592 1.2 christos }
593 1.2 christos
594 1.2 christos Enode->MessageId = MessageId;
595 1.2 christos Enode->Level = Level;
596 1.2 christos Enode->LineNumber = LineNumber;
597 1.2 christos Enode->LogicalLineNumber = LineNumber;
598 1.2 christos Enode->LogicalByteOffset = 0;
599 1.2 christos Enode->Column = Column;
600 1.2 christos Enode->Message = MessageBuffer;
601 1.2 christos Enode->SourceLine = LineBuffer;
602 1.2 christos
603 1.2 christos /* Add the new node to the error node list */
604 1.2 christos
605 1.2 christos AeAddToErrorLog (Enode);
606 1.2 christos
607 1.2 christos if (Gbl_DebugFlag)
608 1.2 christos {
609 1.2 christos /* stderr is a file, send error to it immediately */
610 1.2 christos
611 1.2 christos AePrintException (ASL_FILE_STDERR, Enode, NULL);
612 1.2 christos }
613 1.2 christos
614 1.2 christos Gbl_ExceptionCount[Level]++;
615 1.2 christos }
616 1.2 christos
617 1.2 christos
618 1.2 christos /*******************************************************************************
619 1.2 christos *
620 1.1 jruoho * FUNCTION: AslCommonError
621 1.1 jruoho *
622 1.1 jruoho * PARAMETERS: Level - Seriousness (Warning/error, etc.)
623 1.1 jruoho * MessageId - Index into global message buffer
624 1.1 jruoho * CurrentLineNumber - Actual file line number
625 1.1 jruoho * LogicalLineNumber - Cumulative line number
626 1.1 jruoho * LogicalByteOffset - Byte offset in source file
627 1.1 jruoho * Column - Column in current line
628 1.1 jruoho * Filename - source filename
629 1.1 jruoho * ExtraMessage - additional error message
630 1.1 jruoho *
631 1.1 jruoho * RETURN: None
632 1.1 jruoho *
633 1.1 jruoho * DESCRIPTION: Create a new error node and add it to the error log
634 1.1 jruoho *
635 1.1 jruoho ******************************************************************************/
636 1.1 jruoho
637 1.1 jruoho void
638 1.1 jruoho AslCommonError (
639 1.1 jruoho UINT8 Level,
640 1.3 christos UINT16 MessageId,
641 1.1 jruoho UINT32 CurrentLineNumber,
642 1.1 jruoho UINT32 LogicalLineNumber,
643 1.1 jruoho UINT32 LogicalByteOffset,
644 1.1 jruoho UINT32 Column,
645 1.1 jruoho char *Filename,
646 1.1 jruoho char *ExtraMessage)
647 1.1 jruoho {
648 1.1 jruoho char *MessageBuffer = NULL;
649 1.1 jruoho ASL_ERROR_MSG *Enode;
650 1.1 jruoho
651 1.1 jruoho
652 1.8 christos if (AslIsExceptionIgnored (Level, MessageId))
653 1.8 christos {
654 1.8 christos return;
655 1.8 christos }
656 1.8 christos
657 1.1 jruoho Enode = UtLocalCalloc (sizeof (ASL_ERROR_MSG));
658 1.1 jruoho
659 1.1 jruoho if (ExtraMessage)
660 1.1 jruoho {
661 1.1 jruoho /* Allocate a buffer for the message and a new error node */
662 1.1 jruoho
663 1.3 christos MessageBuffer = UtStringCacheCalloc (strlen (ExtraMessage) + 1);
664 1.1 jruoho
665 1.1 jruoho /* Keep a copy of the extra message */
666 1.1 jruoho
667 1.5 christos strcpy (MessageBuffer, ExtraMessage);
668 1.1 jruoho }
669 1.1 jruoho
670 1.1 jruoho /* Initialize the error node */
671 1.1 jruoho
672 1.1 jruoho if (Filename)
673 1.1 jruoho {
674 1.3 christos Enode->Filename = Filename;
675 1.1 jruoho Enode->FilenameLength = strlen (Filename);
676 1.1 jruoho if (Enode->FilenameLength < 6)
677 1.1 jruoho {
678 1.1 jruoho Enode->FilenameLength = 6;
679 1.1 jruoho }
680 1.1 jruoho }
681 1.1 jruoho
682 1.1 jruoho Enode->MessageId = MessageId;
683 1.1 jruoho Enode->Level = Level;
684 1.1 jruoho Enode->LineNumber = CurrentLineNumber;
685 1.1 jruoho Enode->LogicalLineNumber = LogicalLineNumber;
686 1.1 jruoho Enode->LogicalByteOffset = LogicalByteOffset;
687 1.1 jruoho Enode->Column = Column;
688 1.1 jruoho Enode->Message = MessageBuffer;
689 1.2 christos Enode->SourceLine = NULL;
690 1.1 jruoho
691 1.1 jruoho /* Add the new node to the error node list */
692 1.1 jruoho
693 1.1 jruoho AeAddToErrorLog (Enode);
694 1.1 jruoho
695 1.1 jruoho if (Gbl_DebugFlag)
696 1.1 jruoho {
697 1.1 jruoho /* stderr is a file, send error to it immediately */
698 1.1 jruoho
699 1.1 jruoho AePrintException (ASL_FILE_STDERR, Enode, NULL);
700 1.1 jruoho }
701 1.1 jruoho
702 1.1 jruoho Gbl_ExceptionCount[Level]++;
703 1.1 jruoho if (Gbl_ExceptionCount[ASL_ERROR] > ASL_MAX_ERROR_COUNT)
704 1.1 jruoho {
705 1.1 jruoho printf ("\nMaximum error count (%u) exceeded\n", ASL_MAX_ERROR_COUNT);
706 1.1 jruoho
707 1.1 jruoho Gbl_SourceLine = 0;
708 1.1 jruoho Gbl_NextError = Gbl_ErrorLog;
709 1.1 jruoho CmCleanupAndExit ();
710 1.1 jruoho exit(1);
711 1.1 jruoho }
712 1.1 jruoho
713 1.1 jruoho return;
714 1.1 jruoho }
715 1.1 jruoho
716 1.8 christos /*******************************************************************************
717 1.8 christos *
718 1.8 christos * FUNCTION: AslIsExceptionIgnored
719 1.8 christos *
720 1.8 christos * PARAMETERS: Level - Seriousness (Warning/error, etc.)
721 1.8 christos * MessageId - Index into global message buffer
722 1.8 christos *
723 1.8 christos * RETURN: BOOLEAN
724 1.8 christos *
725 1.8 christos * DESCRIPTION: Check if a particular exception is ignored. In this case it
726 1.8 christos * means that the exception is (expected or disabled.
727 1.8 christos *
728 1.8 christos ******************************************************************************/
729 1.8 christos
730 1.8 christos BOOLEAN
731 1.8 christos AslIsExceptionIgnored (
732 1.8 christos UINT8 Level,
733 1.8 christos UINT16 MessageId)
734 1.8 christos {
735 1.8 christos BOOLEAN ExceptionIgnored;
736 1.8 christos
737 1.8 christos
738 1.8 christos /* Note: this allows exception to be disabled and expected */
739 1.8 christos
740 1.8 christos ExceptionIgnored = AslIsExceptionDisabled (Level, MessageId);
741 1.8 christos ExceptionIgnored |= AslIsExceptionExpected (Level, MessageId);
742 1.8 christos
743 1.8 christos return (Gbl_AllExceptionsDisabled || ExceptionIgnored);
744 1.8 christos }
745 1.8 christos
746 1.8 christos
747 1.8 christos /*******************************************************************************
748 1.8 christos *
749 1.8 christos * FUNCTION: AslCheckExpectException
750 1.8 christos *
751 1.8 christos * PARAMETERS: none
752 1.8 christos *
753 1.8 christos * RETURN: none
754 1.8 christos *
755 1.8 christos * DESCRIPTION: Check the global expected messages table and raise an error
756 1.8 christos * for each message that has not been received.
757 1.8 christos *
758 1.8 christos ******************************************************************************/
759 1.8 christos
760 1.8 christos void
761 1.8 christos AslCheckExpectedExceptions (
762 1.8 christos void)
763 1.8 christos {
764 1.8 christos UINT8 i;
765 1.8 christos
766 1.8 christos for (i = 0; i < Gbl_ExpectedMessagesIndex; ++i)
767 1.8 christos {
768 1.8 christos if (!Gbl_ExpectedMessages[i].MessageReceived)
769 1.8 christos {
770 1.8 christos AslError (ASL_ERROR, ASL_MSG_EXCEPTION_NOT_RECEIVED, NULL,
771 1.8 christos Gbl_ExpectedMessages[i].MessageIdStr);
772 1.8 christos }
773 1.8 christos }
774 1.8 christos }
775 1.8 christos
776 1.8 christos
777 1.8 christos /*******************************************************************************
778 1.8 christos *
779 1.8 christos * FUNCTION: AslExpectException
780 1.8 christos *
781 1.8 christos * PARAMETERS: MessageIdString - ID of excepted exception during compile
782 1.8 christos *
783 1.8 christos * RETURN: Status
784 1.8 christos *
785 1.8 christos * DESCRIPTION: Enter a message ID into the global expected messages table
786 1.8 christos * If these messages are not raised during the compilation, throw
787 1.8 christos * an error.
788 1.8 christos *
789 1.8 christos ******************************************************************************/
790 1.8 christos
791 1.8 christos ACPI_STATUS
792 1.8 christos AslExpectException (
793 1.8 christos char *MessageIdString)
794 1.8 christos {
795 1.8 christos UINT32 MessageId;
796 1.8 christos
797 1.8 christos
798 1.8 christos /* Convert argument to an integer and validate it */
799 1.8 christos
800 1.8 christos MessageId = (UINT32) strtoul (MessageIdString, NULL, 0);
801 1.8 christos
802 1.8 christos if (MessageId > 6999)
803 1.8 christos {
804 1.8 christos printf ("\"%s\" is not a valid warning/remark/erro ID\n",
805 1.8 christos MessageIdString);
806 1.8 christos return (AE_BAD_PARAMETER);
807 1.8 christos }
808 1.8 christos
809 1.8 christos /* Insert value into the global expected message array */
810 1.8 christos
811 1.8 christos if (Gbl_ExpectedMessagesIndex >= ASL_MAX_EXPECTED_MESSAGES)
812 1.8 christos {
813 1.8 christos printf ("Too many messages have been registered as expected (max %u)\n",
814 1.8 christos ASL_MAX_DISABLED_MESSAGES);
815 1.8 christos return (AE_LIMIT);
816 1.8 christos }
817 1.8 christos
818 1.8 christos Gbl_ExpectedMessages[Gbl_ExpectedMessagesIndex].MessageId = MessageId;
819 1.8 christos Gbl_ExpectedMessages[Gbl_ExpectedMessagesIndex].MessageIdStr = MessageIdString;
820 1.8 christos Gbl_ExpectedMessages[Gbl_ExpectedMessagesIndex].MessageReceived = FALSE;
821 1.8 christos Gbl_ExpectedMessagesIndex++;
822 1.8 christos return (AE_OK);
823 1.8 christos }
824 1.8 christos
825 1.1 jruoho
826 1.1 jruoho /*******************************************************************************
827 1.1 jruoho *
828 1.2 christos * FUNCTION: AslDisableException
829 1.2 christos *
830 1.2 christos * PARAMETERS: MessageIdString - ID to be disabled
831 1.2 christos *
832 1.2 christos * RETURN: Status
833 1.2 christos *
834 1.2 christos * DESCRIPTION: Enter a message ID into the global disabled messages table
835 1.2 christos *
836 1.2 christos ******************************************************************************/
837 1.2 christos
838 1.2 christos ACPI_STATUS
839 1.2 christos AslDisableException (
840 1.2 christos char *MessageIdString)
841 1.2 christos {
842 1.2 christos UINT32 MessageId;
843 1.2 christos
844 1.2 christos
845 1.2 christos /* Convert argument to an integer and validate it */
846 1.2 christos
847 1.2 christos MessageId = (UINT32) strtoul (MessageIdString, NULL, 0);
848 1.2 christos
849 1.8 christos if ((MessageId < 2000) || (MessageId > 6999))
850 1.2 christos {
851 1.8 christos printf ("\"%s\" is not a valid warning/remark/error ID\n",
852 1.2 christos MessageIdString);
853 1.2 christos return (AE_BAD_PARAMETER);
854 1.2 christos }
855 1.2 christos
856 1.2 christos /* Insert value into the global disabled message array */
857 1.2 christos
858 1.2 christos if (Gbl_DisabledMessagesIndex >= ASL_MAX_DISABLED_MESSAGES)
859 1.2 christos {
860 1.2 christos printf ("Too many messages have been disabled (max %u)\n",
861 1.2 christos ASL_MAX_DISABLED_MESSAGES);
862 1.2 christos return (AE_LIMIT);
863 1.2 christos }
864 1.2 christos
865 1.2 christos Gbl_DisabledMessages[Gbl_DisabledMessagesIndex] = MessageId;
866 1.2 christos Gbl_DisabledMessagesIndex++;
867 1.2 christos return (AE_OK);
868 1.2 christos }
869 1.2 christos
870 1.2 christos
871 1.2 christos /*******************************************************************************
872 1.2 christos *
873 1.2 christos * FUNCTION: AslIsExceptionDisabled
874 1.2 christos *
875 1.2 christos * PARAMETERS: Level - Seriousness (Warning/error, etc.)
876 1.2 christos * MessageId - Index into global message buffer
877 1.2 christos *
878 1.2 christos * RETURN: TRUE if exception/message should be ignored
879 1.2 christos *
880 1.2 christos * DESCRIPTION: Check if the user has specified options such that this
881 1.2 christos * exception should be ignored
882 1.2 christos *
883 1.2 christos ******************************************************************************/
884 1.2 christos
885 1.8 christos static BOOLEAN
886 1.8 christos AslIsExceptionExpected (
887 1.8 christos UINT8 Level,
888 1.8 christos UINT16 MessageId)
889 1.8 christos {
890 1.8 christos UINT32 EncodedMessageId;
891 1.8 christos UINT32 i;
892 1.8 christos
893 1.8 christos
894 1.8 christos /*
895 1.8 christos * Mark this exception as received
896 1.8 christos */
897 1.8 christos EncodedMessageId = AeBuildFullExceptionCode (Level, MessageId);
898 1.8 christos for (i = 0; i < Gbl_ExpectedMessagesIndex; i++)
899 1.8 christos {
900 1.8 christos /* Simple implementation via fixed array */
901 1.8 christos
902 1.8 christos if (EncodedMessageId == Gbl_ExpectedMessages[i].MessageId)
903 1.8 christos {
904 1.8 christos return (Gbl_ExpectedMessages[i].MessageReceived = TRUE);
905 1.8 christos }
906 1.8 christos }
907 1.8 christos
908 1.8 christos return (FALSE);
909 1.8 christos }
910 1.8 christos
911 1.8 christos
912 1.8 christos /*******************************************************************************
913 1.8 christos *
914 1.8 christos * FUNCTION: AslIsExceptionDisabled
915 1.8 christos *
916 1.8 christos * PARAMETERS: Level - Seriousness (Warning/error, etc.)
917 1.8 christos * MessageId - Index into global message buffer
918 1.8 christos *
919 1.8 christos * RETURN: TRUE if exception/message should be ignored
920 1.8 christos *
921 1.8 christos * DESCRIPTION: Check if the user has specified options such that this
922 1.8 christos * exception should be ignored
923 1.8 christos *
924 1.8 christos ******************************************************************************/
925 1.8 christos
926 1.8 christos static BOOLEAN
927 1.2 christos AslIsExceptionDisabled (
928 1.2 christos UINT8 Level,
929 1.3 christos UINT16 MessageId)
930 1.2 christos {
931 1.2 christos UINT32 EncodedMessageId;
932 1.2 christos UINT32 i;
933 1.2 christos
934 1.2 christos
935 1.2 christos switch (Level)
936 1.2 christos {
937 1.2 christos case ASL_WARNING2:
938 1.2 christos case ASL_WARNING3:
939 1.2 christos
940 1.2 christos /* Check for global disable via -w1/-w2/-w3 options */
941 1.2 christos
942 1.2 christos if (Level > Gbl_WarningLevel)
943 1.2 christos {
944 1.2 christos return (TRUE);
945 1.2 christos }
946 1.2 christos /* Fall through */
947 1.2 christos
948 1.2 christos case ASL_WARNING:
949 1.2 christos case ASL_REMARK:
950 1.8 christos case ASL_ERROR:
951 1.2 christos /*
952 1.8 christos * Ignore this error/warning/remark if it has been disabled by
953 1.2 christos * the user (-vw option)
954 1.2 christos */
955 1.3 christos EncodedMessageId = AeBuildFullExceptionCode (Level, MessageId);
956 1.2 christos for (i = 0; i < Gbl_DisabledMessagesIndex; i++)
957 1.2 christos {
958 1.2 christos /* Simple implementation via fixed array */
959 1.2 christos
960 1.2 christos if (EncodedMessageId == Gbl_DisabledMessages[i])
961 1.2 christos {
962 1.2 christos return (TRUE);
963 1.2 christos }
964 1.2 christos }
965 1.2 christos break;
966 1.2 christos
967 1.2 christos default:
968 1.2 christos break;
969 1.2 christos }
970 1.2 christos
971 1.2 christos return (FALSE);
972 1.2 christos }
973 1.2 christos
974 1.2 christos
975 1.2 christos /*******************************************************************************
976 1.2 christos *
977 1.1 jruoho * FUNCTION: AslError
978 1.1 jruoho *
979 1.1 jruoho * PARAMETERS: Level - Seriousness (Warning/error, etc.)
980 1.1 jruoho * MessageId - Index into global message buffer
981 1.1 jruoho * Op - Parse node where error happened
982 1.1 jruoho * ExtraMessage - additional error message
983 1.1 jruoho *
984 1.1 jruoho * RETURN: None
985 1.1 jruoho *
986 1.1 jruoho * DESCRIPTION: Main error reporting routine for the ASL compiler (all code
987 1.1 jruoho * except the parser.)
988 1.1 jruoho *
989 1.1 jruoho ******************************************************************************/
990 1.1 jruoho
991 1.1 jruoho void
992 1.1 jruoho AslError (
993 1.1 jruoho UINT8 Level,
994 1.3 christos UINT16 MessageId,
995 1.1 jruoho ACPI_PARSE_OBJECT *Op,
996 1.1 jruoho char *ExtraMessage)
997 1.1 jruoho {
998 1.1 jruoho if (Op)
999 1.1 jruoho {
1000 1.1 jruoho AslCommonError (Level, MessageId, Op->Asl.LineNumber,
1001 1.2 christos Op->Asl.LogicalLineNumber,
1002 1.2 christos Op->Asl.LogicalByteOffset,
1003 1.2 christos Op->Asl.Column,
1004 1.2 christos Op->Asl.Filename, ExtraMessage);
1005 1.1 jruoho }
1006 1.1 jruoho else
1007 1.1 jruoho {
1008 1.1 jruoho AslCommonError (Level, MessageId, 0,
1009 1.2 christos 0, 0, 0, NULL, ExtraMessage);
1010 1.1 jruoho }
1011 1.1 jruoho }
1012 1.1 jruoho
1013 1.1 jruoho
1014 1.1 jruoho /*******************************************************************************
1015 1.1 jruoho *
1016 1.1 jruoho * FUNCTION: AslCoreSubsystemError
1017 1.1 jruoho *
1018 1.1 jruoho * PARAMETERS: Op - Parse node where error happened
1019 1.3 christos * Status - The ACPICA Exception
1020 1.1 jruoho * ExtraMessage - additional error message
1021 1.1 jruoho * Abort - TRUE -> Abort compilation
1022 1.1 jruoho *
1023 1.1 jruoho * RETURN: None
1024 1.1 jruoho *
1025 1.3 christos * DESCRIPTION: Error reporting routine for exceptions returned by the ACPICA
1026 1.3 christos * core subsystem.
1027 1.1 jruoho *
1028 1.1 jruoho ******************************************************************************/
1029 1.1 jruoho
1030 1.1 jruoho void
1031 1.1 jruoho AslCoreSubsystemError (
1032 1.1 jruoho ACPI_PARSE_OBJECT *Op,
1033 1.1 jruoho ACPI_STATUS Status,
1034 1.1 jruoho char *ExtraMessage,
1035 1.1 jruoho BOOLEAN Abort)
1036 1.1 jruoho {
1037 1.1 jruoho
1038 1.2 christos snprintf (MsgBuffer, sizeof(MsgBuffer), "%s %s", AcpiFormatException (Status), ExtraMessage);
1039 1.1 jruoho
1040 1.1 jruoho if (Op)
1041 1.1 jruoho {
1042 1.6 christos AslCommonError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION,
1043 1.6 christos Op->Asl.LineNumber,
1044 1.6 christos Op->Asl.LogicalLineNumber,
1045 1.6 christos Op->Asl.LogicalByteOffset,
1046 1.6 christos Op->Asl.Column,
1047 1.6 christos Op->Asl.Filename, MsgBuffer);
1048 1.1 jruoho }
1049 1.1 jruoho else
1050 1.1 jruoho {
1051 1.6 christos AslCommonError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION,
1052 1.6 christos 0, 0, 0, 0, NULL, MsgBuffer);
1053 1.1 jruoho }
1054 1.1 jruoho
1055 1.1 jruoho if (Abort)
1056 1.1 jruoho {
1057 1.1 jruoho AslAbort ();
1058 1.1 jruoho }
1059 1.1 jruoho }
1060 1.1 jruoho
1061 1.1 jruoho
1062 1.1 jruoho /*******************************************************************************
1063 1.1 jruoho *
1064 1.1 jruoho * FUNCTION: AslCompilererror
1065 1.1 jruoho *
1066 1.1 jruoho * PARAMETERS: CompilerMessage - Error message from the parser
1067 1.1 jruoho *
1068 1.1 jruoho * RETURN: Status (0 for now)
1069 1.1 jruoho *
1070 1.1 jruoho * DESCRIPTION: Report an error situation discovered in a production
1071 1.1 jruoho * NOTE: don't change the name of this function, it is called
1072 1.1 jruoho * from the auto-generated parser.
1073 1.1 jruoho *
1074 1.1 jruoho ******************************************************************************/
1075 1.1 jruoho
1076 1.1 jruoho int
1077 1.1 jruoho AslCompilererror (
1078 1.2 christos const char *CompilerMessage)
1079 1.1 jruoho {
1080 1.1 jruoho
1081 1.4 christos Gbl_SyntaxError++;
1082 1.4 christos
1083 1.1 jruoho AslCommonError (ASL_ERROR, ASL_MSG_SYNTAX, Gbl_CurrentLineNumber,
1084 1.2 christos Gbl_LogicalLineNumber, Gbl_CurrentLineOffset,
1085 1.2 christos Gbl_CurrentColumn, Gbl_Files[ASL_FILE_INPUT].Filename,
1086 1.2 christos ACPI_CAST_PTR (char, CompilerMessage));
1087 1.1 jruoho
1088 1.2 christos return (0);
1089 1.1 jruoho }
1090