Sync ACPICA with Intel's version 20151124.
[dragonfly.git] / sys / contrib / dev / acpica / source / compiler / asllistsup.c
1 /******************************************************************************
2  *
3  * Module Name: asllistsup - Listing file support utilities
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2015, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43
44 #include "aslcompiler.h"
45 #include "aslcompiler.y.h"
46
47
48 #define _COMPONENT          ACPI_COMPILER
49         ACPI_MODULE_NAME    ("aslistsup")
50
51
52 /*******************************************************************************
53  *
54  * FUNCTION:    LsDumpAscii
55  *
56  * PARAMETERS:  FileId          - ID of current listing file
57  *              Count           - Number of bytes to convert
58  *              Buffer          - Buffer of bytes to convert
59  *
60  * RETURN:      None
61  *
62  * DESCRIPTION: Convert hex bytes to ascii
63  *
64  ******************************************************************************/
65
66 void
67 LsDumpAscii (
68     UINT32                  FileId,
69     UINT32                  Count,
70     UINT8                   *Buffer)
71 {
72     UINT8                   BufChar;
73     UINT32                  i;
74
75
76     FlPrintFile (FileId, "    \"");
77     for (i = 0; i < Count; i++)
78     {
79         BufChar = Buffer[i];
80         if (isprint (BufChar))
81         {
82             FlPrintFile (FileId, "%c", BufChar);
83         }
84         else
85         {
86             /* Not a printable character, just put out a dot */
87
88             FlPrintFile (FileId, ".");
89         }
90     }
91
92     FlPrintFile (FileId, "\"");
93 }
94
95
96 /*******************************************************************************
97  *
98  * FUNCTION:    LsDumpAsciiInComment
99  *
100  * PARAMETERS:  FileId          - ID of current listing file
101  *              Count           - Number of bytes to convert
102  *              Buffer          - Buffer of bytes to convert
103  *
104  * RETURN:      None
105  *
106  * DESCRIPTION: Convert hex bytes to ascii
107  *
108  ******************************************************************************/
109
110 void
111 LsDumpAsciiInComment (
112     UINT32                  FileId,
113     UINT32                  Count,
114     UINT8                   *Buffer)
115 {
116     UINT8                   BufChar = 0;
117     UINT8                   LastChar;
118     UINT32                  i;
119
120
121     FlPrintFile (FileId, "    \"");
122     for (i = 0; i < Count; i++)
123     {
124         LastChar = BufChar;
125         BufChar = Buffer[i];
126
127         if (isprint (BufChar))
128         {
129             /* Handle embedded C comment sequences */
130
131             if (((LastChar == '*') && (BufChar == '/')) ||
132                 ((LastChar == '/') && (BufChar == '*')))
133             {
134                 /* Insert a space to break the sequence */
135
136                 FlPrintFile (FileId, ".", BufChar);
137             }
138
139             FlPrintFile (FileId, "%c", BufChar);
140         }
141         else
142         {
143             /* Not a printable character, just put out a dot */
144
145             FlPrintFile (FileId, ".");
146         }
147     }
148
149     FlPrintFile (FileId, "\"");
150 }
151
152
153 /*******************************************************************************
154  *
155  * FUNCTION:    LsCheckException
156  *
157  * PARAMETERS:  LineNumber          - Current logical (cumulative) line #
158  *              FileId              - ID of output listing file
159  *
160  * RETURN:      None
161  *
162  * DESCRIPTION: Check if there is an exception for this line, and if there is,
163  *              put it in the listing immediately. Handles multiple errors
164  *              per line. Gbl_NextError points to the next error in the
165  *              sorted (by line #) list of compile errors/warnings.
166  *
167  ******************************************************************************/
168
169 void
170 LsCheckException (
171     UINT32                  LineNumber,
172     UINT32                  FileId)
173 {
174
175     if ((!Gbl_NextError) ||
176         (LineNumber < Gbl_NextError->LogicalLineNumber ))
177     {
178         return;
179     }
180
181     /* Handle multiple errors per line */
182
183     if (FileId == ASL_FILE_LISTING_OUTPUT)
184     {
185         while (Gbl_NextError &&
186               (LineNumber >= Gbl_NextError->LogicalLineNumber))
187         {
188             AePrintException (FileId, Gbl_NextError, "\n[****iasl****]\n");
189             Gbl_NextError = Gbl_NextError->Next;
190         }
191
192         FlPrintFile (FileId, "\n");
193     }
194 }
195
196
197 /*******************************************************************************
198  *
199  * FUNCTION:    LsWriteListingHexBytes
200  *
201  * PARAMETERS:  Buffer          - AML code buffer
202  *              Length          - Number of AML bytes to write
203  *              FileId          - ID of current listing file.
204  *
205  * RETURN:      None
206  *
207  * DESCRIPTION: Write the contents of the AML buffer to the listing file via
208  *              the listing buffer. The listing buffer is flushed every 16
209  *              AML bytes.
210  *
211  ******************************************************************************/
212
213 void
214 LsWriteListingHexBytes (
215     UINT8                   *Buffer,
216     UINT32                  Length,
217     UINT32                  FileId)
218 {
219     UINT32                  i;
220
221
222     /* Transfer all requested bytes */
223
224     for (i = 0; i < Length; i++)
225     {
226         /* Print line header when buffer is empty */
227
228         if (Gbl_CurrentHexColumn == 0)
229         {
230             if (Gbl_HasIncludeFiles)
231             {
232                 FlPrintFile (FileId, "%*s", 10, " ");
233             }
234
235             switch (FileId)
236             {
237             case ASL_FILE_LISTING_OUTPUT:
238
239                 FlPrintFile (FileId, "%8.8X%s", Gbl_CurrentAmlOffset,
240                     ASL_LISTING_LINE_PREFIX);
241                 break;
242
243             case ASL_FILE_ASM_SOURCE_OUTPUT:
244
245                 FlPrintFile (FileId, "    db ");
246                 break;
247
248             case ASL_FILE_C_SOURCE_OUTPUT:
249
250                 FlPrintFile (FileId, "        ");
251                 break;
252
253             default:
254
255                 /* No other types supported */
256
257                 return;
258             }
259         }
260
261         /* Transfer AML byte and update counts */
262
263         Gbl_AmlBuffer[Gbl_CurrentHexColumn] = Buffer[i];
264
265         Gbl_CurrentHexColumn++;
266         Gbl_CurrentAmlOffset++;
267
268         /* Flush buffer when it is full */
269
270         if (Gbl_CurrentHexColumn >= HEX_LISTING_LINE_SIZE)
271         {
272             LsFlushListingBuffer (FileId);
273         }
274     }
275 }
276
277
278 /*******************************************************************************
279  *
280  * FUNCTION:    LsWriteSourceLines
281  *
282  * PARAMETERS:  ToLineNumber            -
283  *              ToLogicalLineNumber     - Write up to this source line number
284  *              FileId                  - ID of current listing file
285  *
286  * RETURN:      None
287  *
288  * DESCRIPTION: Read then write source lines to the listing file until we have
289  *              reached the specified logical (cumulative) line number. This
290  *              automatically echos out comment blocks and other non-AML
291  *              generating text until we get to the actual AML-generating line
292  *              of ASL code specified by the logical line number.
293  *
294  ******************************************************************************/
295
296 void
297 LsWriteSourceLines (
298     UINT32                  ToLineNumber,
299     UINT32                  ToLogicalLineNumber,
300     UINT32                  FileId)
301 {
302
303     /* Nothing to do for these file types */
304
305     if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) ||
306         (FileId == ASL_FILE_C_INCLUDE_OUTPUT))
307     {
308         return;
309     }
310
311     Gbl_CurrentLine = ToLogicalLineNumber;
312
313     /* Flush any hex bytes remaining from the last opcode */
314
315     LsFlushListingBuffer (FileId);
316
317     /* Read lines and write them as long as we are not caught up */
318
319     if (Gbl_SourceLine < Gbl_CurrentLine)
320     {
321         /*
322          * If we just completed writing some AML hex bytes, output a linefeed
323          * to add some whitespace for readability.
324          */
325         if (Gbl_HexBytesWereWritten)
326         {
327             FlPrintFile (FileId, "\n");
328             Gbl_HexBytesWereWritten = FALSE;
329         }
330
331         if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
332         {
333             FlPrintFile (FileId, "    /*\n");
334         }
335
336         /* Write one line at a time until we have reached the target line # */
337
338         while ((Gbl_SourceLine < Gbl_CurrentLine) &&
339                 LsWriteOneSourceLine (FileId))
340         { ; }
341
342         if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
343         {
344             FlPrintFile (FileId, "     */");
345         }
346
347         FlPrintFile (FileId, "\n");
348     }
349 }
350
351
352 /*******************************************************************************
353  *
354  * FUNCTION:    LsWriteOneSourceLine
355  *
356  * PARAMETERS:  FileId          - ID of current listing file
357  *
358  * RETURN:      FALSE on EOF (input source file), TRUE otherwise
359  *
360  * DESCRIPTION: Read one line from the input source file and echo it to the
361  *              listing file, prefixed with the line number, and if the source
362  *              file contains include files, prefixed with the current filename
363  *
364  ******************************************************************************/
365
366 UINT32
367 LsWriteOneSourceLine (
368     UINT32                  FileId)
369 {
370     UINT8                   FileByte;
371     UINT32                  Column = 0;
372     UINT32                  Index = 16;
373     BOOLEAN                 StartOfLine = FALSE;
374     BOOLEAN                 ProcessLongLine = FALSE;
375
376
377     Gbl_SourceLine++;
378     Gbl_ListingNode->LineNumber++;
379
380     /* Ignore lines that are completely blank (but count the line above) */
381
382     if (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) != AE_OK)
383     {
384         return (0);
385     }
386     if (FileByte == '\n')
387     {
388         return (1);
389     }
390
391     /*
392      * This is a non-empty line, we will print the entire line with
393      * the line number and possibly other prefixes and transforms.
394      */
395
396     /* Line prefixes for special files, C and ASM output */
397
398     if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
399     {
400         FlPrintFile (FileId, "     *");
401     }
402     if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
403     {
404         FlPrintFile (FileId, "; ");
405     }
406
407     if (Gbl_HasIncludeFiles)
408     {
409         /*
410          * This file contains "include" statements, print the current
411          * filename and line number within the current file
412          */
413         FlPrintFile (FileId, "%12s %5d%s",
414             Gbl_ListingNode->Filename, Gbl_ListingNode->LineNumber,
415             ASL_LISTING_LINE_PREFIX);
416     }
417     else
418     {
419         /* No include files, just print the line number */
420
421         FlPrintFile (FileId, "%8u%s", Gbl_SourceLine,
422             ASL_LISTING_LINE_PREFIX);
423     }
424
425     /* Read the rest of this line (up to a newline or EOF) */
426
427     do
428     {
429         if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
430         {
431             if (FileByte == '/')
432             {
433                 FileByte = '*';
434             }
435         }
436
437         /* Split long input lines for readability in the listing */
438
439         Column++;
440         if (Column >= 128)
441         {
442             if (!ProcessLongLine)
443             {
444                 if ((FileByte != '}') &&
445                     (FileByte != '{'))
446                 {
447                     goto WriteByte;
448                 }
449
450                 ProcessLongLine = TRUE;
451             }
452
453             if (FileByte == '{')
454             {
455                 FlPrintFile (FileId, "\n%*s{\n", Index, " ");
456                 StartOfLine = TRUE;
457                 Index += 4;
458                 continue;
459             }
460
461             else if (FileByte == '}')
462             {
463                 if (!StartOfLine)
464                 {
465                     FlPrintFile (FileId, "\n");
466                 }
467
468                 StartOfLine = TRUE;
469                 Index -= 4;
470                 FlPrintFile (FileId, "%*s}\n", Index, " ");
471                 continue;
472             }
473
474             /* Ignore spaces/tabs at the start of line */
475
476             else if ((FileByte == ' ') && StartOfLine)
477             {
478                 continue;
479             }
480
481             else if (StartOfLine)
482             {
483                 StartOfLine = FALSE;
484                 FlPrintFile (FileId, "%*s", Index, " ");
485             }
486
487 WriteByte:
488             FlWriteFile (FileId, &FileByte, 1);
489             if (FileByte == '\n')
490             {
491                 /*
492                  * This line has been completed.
493                  * Check if an error occurred on this source line during the compile.
494                  * If so, we print the error message after the source line.
495                  */
496                 LsCheckException (Gbl_SourceLine, FileId);
497                 return (1);
498             }
499         }
500         else
501         {
502             FlWriteFile (FileId, &FileByte, 1);
503             if (FileByte == '\n')
504             {
505                 /*
506                  * This line has been completed.
507                  * Check if an error occurred on this source line during the compile.
508                  * If so, we print the error message after the source line.
509                  */
510                 LsCheckException (Gbl_SourceLine, FileId);
511                 return (1);
512             }
513         }
514
515     } while (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) == AE_OK);
516
517     /* EOF on the input file was reached */
518
519     return (0);
520 }
521
522
523 /*******************************************************************************
524  *
525  * FUNCTION:    LsFlushListingBuffer
526  *
527  * PARAMETERS:  FileId          - ID of the listing file
528  *
529  * RETURN:      None
530  *
531  * DESCRIPTION: Flush out the current contents of the 16-byte hex AML code
532  *              buffer. Usually called at the termination of a single line
533  *              of source code or when the buffer is full.
534  *
535  ******************************************************************************/
536
537 void
538 LsFlushListingBuffer (
539     UINT32                  FileId)
540 {
541     UINT32                  i;
542
543
544     if (Gbl_CurrentHexColumn == 0)
545     {
546         return;
547     }
548
549     /* Write the hex bytes */
550
551     switch (FileId)
552     {
553     case ASL_FILE_LISTING_OUTPUT:
554
555         for (i = 0; i < Gbl_CurrentHexColumn; i++)
556         {
557             FlPrintFile (FileId, "%2.2X ", Gbl_AmlBuffer[i]);
558         }
559
560         for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 3); i++)
561         {
562             FlWriteFile (FileId, ".", 1);
563         }
564
565         /* Write the ASCII character associated with each of the bytes */
566
567         LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
568         break;
569
570
571     case ASL_FILE_ASM_SOURCE_OUTPUT:
572
573         for (i = 0; i < Gbl_CurrentHexColumn; i++)
574         {
575             if (i > 0)
576             {
577                 FlPrintFile (FileId, ",");
578             }
579
580             FlPrintFile (FileId, "0%2.2Xh", Gbl_AmlBuffer[i]);
581         }
582
583         for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++)
584         {
585             FlWriteFile (FileId, " ", 1);
586         }
587
588         FlPrintFile (FileId, "  ;%8.8X",
589             Gbl_CurrentAmlOffset - HEX_LISTING_LINE_SIZE);
590
591         /* Write the ASCII character associated with each of the bytes */
592
593         LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
594         break;
595
596
597     case ASL_FILE_C_SOURCE_OUTPUT:
598
599         for (i = 0; i < Gbl_CurrentHexColumn; i++)
600         {
601             FlPrintFile (FileId, "0x%2.2X,", Gbl_AmlBuffer[i]);
602         }
603
604         /* Pad hex output with spaces if line is shorter than max line size */
605
606         for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++)
607         {
608             FlWriteFile (FileId, " ", 1);
609         }
610
611         /* AML offset for the start of the line */
612
613         FlPrintFile (FileId, "    /* %8.8X",
614             Gbl_CurrentAmlOffset - Gbl_CurrentHexColumn);
615
616         /* Write the ASCII character associated with each of the bytes */
617
618         LsDumpAsciiInComment (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
619         FlPrintFile (FileId, " */");
620         break;
621
622     default:
623
624         /* No other types supported */
625
626         return;
627     }
628
629     FlPrintFile (FileId, "\n");
630
631     Gbl_CurrentHexColumn = 0;
632     Gbl_HexBytesWereWritten = TRUE;
633 }
634
635
636 /*******************************************************************************
637  *
638  * FUNCTION:    LsPushNode
639  *
640  * PARAMETERS:  Filename        - Pointer to the include filename
641  *
642  * RETURN:      None
643  *
644  * DESCRIPTION: Push a listing node on the listing/include file stack. This
645  *              stack enables tracking of include files (infinitely nested)
646  *              and resumption of the listing of the parent file when the
647  *              include file is finished.
648  *
649  ******************************************************************************/
650
651 void
652 LsPushNode (
653     char                    *Filename)
654 {
655     ASL_LISTING_NODE        *Lnode;
656
657
658     /* Create a new node */
659
660     Lnode = UtLocalCalloc (sizeof (ASL_LISTING_NODE));
661
662     /* Initialize */
663
664     Lnode->Filename = Filename;
665     Lnode->LineNumber = 0;
666
667     /* Link (push) */
668
669     Lnode->Next = Gbl_ListingNode;
670     Gbl_ListingNode = Lnode;
671 }
672
673
674 /*******************************************************************************
675  *
676  * FUNCTION:    LsPopNode
677  *
678  * PARAMETERS:  None
679  *
680  * RETURN:      List head after current head is popped off
681  *
682  * DESCRIPTION: Pop the current head of the list, free it, and return the
683  *              next node on the stack (the new current node).
684  *
685  ******************************************************************************/
686
687 ASL_LISTING_NODE *
688 LsPopNode (
689     void)
690 {
691     ASL_LISTING_NODE        *Lnode;
692
693
694     /* Just grab the node at the head of the list */
695
696     Lnode = Gbl_ListingNode;
697     if ((!Lnode) ||
698         (!Lnode->Next))
699     {
700         AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL,
701             "Could not pop empty listing stack");
702         return (Gbl_ListingNode);
703     }
704
705     Gbl_ListingNode = Lnode->Next;
706     ACPI_FREE (Lnode);
707
708     /* New "Current" node is the new head */
709
710     return (Gbl_ListingNode);
711 }