xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/cvparser.c (revision deb6f0161a9109e7de9b519dc8dfb9478668dcdd)
1 /******************************************************************************
2  *
3  * Module Name: cvparser - Converter functions that are called from the AML
4  *                         parser.
5  *
6  *****************************************************************************/
7 
8 /*
9  * Copyright (C) 2000 - 2018, Intel Corp.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44 
45 #include "aslcompiler.h"
46 #include "acparser.h"
47 #include "acdispat.h"
48 #include "amlcode.h"
49 #include "acinterp.h"
50 #include "acdisasm.h"
51 #include "acconvert.h"
52 
53 
54 /* local prototypes */
55 
56 static BOOLEAN
57 CvCommentExists (
58     UINT8                   *Address);
59 
60 static BOOLEAN
61 CvIsFilename (
62     char                   *Filename);
63 
64 static ACPI_FILE_NODE*
65 CvFileAddressLookup(
66     char                    *Address,
67     ACPI_FILE_NODE          *Head);
68 
69 static void
70 CvAddToFileTree (
71     char                    *Filename,
72     char                    *PreviousFilename);
73 
74 static void
75 CvSetFileParent (
76     char                    *ChildFile,
77     char                    *ParentFile);
78 
79 
80 /*******************************************************************************
81  *
82  * FUNCTION:    CvIsFilename
83  *
84  * PARAMETERS:  filename - input filename
85  *
86  * RETURN:      BOOLEAN - TRUE if all characters are between 0x20 and 0x7f
87  *
88  * DESCRIPTION: Take a given char * and see if it contains all printable
89  *              characters. If all characters have hexvalues 20-7f and ends with
90  *              .dsl, we will assume that it is a proper filename.
91  *
92  ******************************************************************************/
93 
94 static BOOLEAN
95 CvIsFilename (
96     char                    *Filename)
97 {
98     UINT64                  Length = strlen(Filename);
99     char                    *FileExt = Filename + Length - 4;
100     UINT64                  i;
101 
102 
103     if ((Length > 4) && AcpiUtStricmp (FileExt, ".dsl"))
104     {
105         return (FALSE);
106     }
107 
108     for(i = 0; i<Length; ++i)
109     {
110         if (!isprint ((int) Filename[i]))
111         {
112             return (FALSE);
113         }
114     }
115 
116     return (TRUE);
117 }
118 
119 
120 /*******************************************************************************
121  *
122  * FUNCTION:    CvInitFileTree
123  *
124  * PARAMETERS:  Table      - input table
125  *              AmlStart   - Address of the starting point of the AML.
126  *              AmlLength  - Length of the AML file.
127  *
128  * RETURN:      None
129  *
130  * DESCRIPTION: Initialize the file dependency tree by scanning the AML.
131  *              This is referred as ASL_CV_INIT_FILETREE.
132  *
133  ******************************************************************************/
134 
135 void
136 CvInitFileTree (
137     ACPI_TABLE_HEADER       *Table,
138     UINT8                   *AmlStart,
139     UINT32                  AmlLength)
140 {
141     UINT8                   *TreeAml;
142     UINT8                   *FileEnd;
143     char                    *Filename = NULL;
144     char                    *PreviousFilename = NULL;
145     char                    *ParentFilename = NULL;
146     char                    *ChildFilename = NULL;
147 
148 
149     if (!AcpiGbl_CaptureComments)
150     {
151         return;
152     }
153 
154     CvDbgPrint ("AmlLength: %x\n", AmlLength);
155     CvDbgPrint ("AmlStart:  %p\n", AmlStart);
156     CvDbgPrint ("AmlEnd?:   %p\n", AmlStart+AmlLength);
157 
158     AcpiGbl_FileTreeRoot = AcpiOsAcquireObject (AcpiGbl_FileCache);
159 
160     AcpiGbl_FileTreeRoot->FileStart = (char *)(AmlStart);
161     AcpiGbl_FileTreeRoot->FileEnd = (char *)(AmlStart + Table->Length);
162     AcpiGbl_FileTreeRoot->Next = NULL;
163     AcpiGbl_FileTreeRoot->Parent = NULL;
164     AcpiGbl_FileTreeRoot->Filename = (char *)(AmlStart+2);
165 
166     /* Set the root file to the current open file */
167 
168     AcpiGbl_FileTreeRoot->File = AcpiGbl_OutputFile;
169 
170     /*
171      * Set this to true because we dont need to output
172      * an include statement for the topmost file
173      */
174     AcpiGbl_FileTreeRoot->IncludeWritten = TRUE;
175     Filename = NULL;
176     AcpiGbl_CurrentFilename = (char *)(AmlStart+2);
177     AcpiGbl_RootFilename    = (char *)(AmlStart+2);
178 
179     TreeAml = AmlStart;
180     FileEnd = AmlStart + AmlLength;
181 
182     while (TreeAml <= FileEnd)
183     {
184         /*
185          * Make sure that this filename contains all printable characters
186          * and a .dsl extension at the end. If not, then it must be some
187          * raw data that doesn't outline a filename.
188          */
189         if ((*TreeAml == AML_COMMENT_OP) &&
190             (*(TreeAml +1) == FILENAME_COMMENT) &&
191             (CvIsFilename ((char *)(TreeAml +2))))
192         {
193             CvDbgPrint ("A9 and a 08 file\n");
194             PreviousFilename = Filename;
195             Filename = (char *) (TreeAml +2);
196 
197             CvAddToFileTree (Filename, PreviousFilename);
198             ChildFilename = Filename;
199             CvDbgPrint ("%s\n", Filename);
200         }
201         else if ((*TreeAml == AML_COMMENT_OP) &&
202             (*(TreeAml +1) == PARENTFILENAME_COMMENT) &&
203             (CvIsFilename ((char *)(TreeAml +2))))
204         {
205             CvDbgPrint ("A9 and a 09 file\n");
206             ParentFilename = (char *)(TreeAml +2);
207             CvSetFileParent (ChildFilename, ParentFilename);
208             CvDbgPrint ("%s\n", ParentFilename);
209         }
210 
211         ++TreeAml;
212     }
213 }
214 
215 
216 /*******************************************************************************
217  *
218  * FUNCTION:    CvClearOpComments
219  *
220  * PARAMETERS:  Op -- clear all comments within this Op
221  *
222  * RETURN:      None
223  *
224  * DESCRIPTION: Clear all converter-related fields of the given Op.
225  *              This is referred as ASL_CV_CLEAR_OP_COMMENTS.
226  *
227  ******************************************************************************/
228 
229 void
230 CvClearOpComments (
231     ACPI_PARSE_OBJECT       *Op)
232 {
233 
234     Op->Common.InlineComment     = NULL;
235     Op->Common.EndNodeComment    = NULL;
236     Op->Common.NameComment       = NULL;
237     Op->Common.CommentList       = NULL;
238     Op->Common.EndBlkComment     = NULL;
239     Op->Common.CloseBraceComment = NULL;
240     Op->Common.CvFilename        = NULL;
241     Op->Common.CvParentFilename  = NULL;
242 }
243 
244 
245 /*******************************************************************************
246  *
247  * FUNCTION:    CvCommentExists
248  *
249  * PARAMETERS:  Address - check if this address appears in the list
250  *
251  * RETURN:      BOOLEAN - TRUE if the address exists.
252  *
253  * DESCRIPTION: Look at the pointer address and check if this appears in the
254  *              list of all addresses. If it exists in the list, return TRUE
255  *              if it exists. Otherwise add to the list and return FALSE.
256  *
257  ******************************************************************************/
258 
259 static BOOLEAN
260 CvCommentExists (
261     UINT8                    *Address)
262 {
263     ACPI_COMMENT_ADDR_NODE   *Current = AcpiGbl_CommentAddrListHead;
264     UINT8                    Option;
265 
266 
267     if (!Address)
268     {
269         return (FALSE);
270     }
271 
272     Option = *(Address + 1);
273 
274     /*
275      * FILENAME_COMMENT and PARENTFILENAME_COMMENT are not treated as
276      * comments. They serve as markers for where the file starts and ends.
277      */
278     if ((Option == FILENAME_COMMENT) ||
279         (Option == PARENTFILENAME_COMMENT))
280     {
281        return (FALSE);
282     }
283 
284     if (!Current)
285     {
286         AcpiGbl_CommentAddrListHead =
287             AcpiOsAcquireObject (AcpiGbl_RegCommentCache);
288         AcpiGbl_CommentAddrListHead->Addr = Address;
289         AcpiGbl_CommentAddrListHead->Next = NULL;
290         return (FALSE);
291     }
292     else
293     {
294         while (Current)
295         {
296             if (Current->Addr != Address)
297             {
298                 Current = Current->Next;
299             }
300             else
301             {
302                 return (TRUE);
303             }
304         }
305 
306         /*
307          * If the execution gets to this point, it means that this
308          * address does not exists in the list. Add this address to the
309          * beginning of the list.
310          */
311         Current = AcpiGbl_CommentAddrListHead;
312         AcpiGbl_CommentAddrListHead =
313             AcpiOsAcquireObject (AcpiGbl_RegCommentCache);
314 
315         AcpiGbl_CommentAddrListHead->Addr = Address;
316         AcpiGbl_CommentAddrListHead->Next = Current;
317         return (FALSE);
318     }
319 }
320 
321 
322 /*******************************************************************************
323  *
324  * FUNCTION:    CvFilenameExists
325  *
326  * PARAMETERS:  Filename        - filename to search
327  *
328  * RETURN:      ACPI_FILE_NODE - a pointer to a file node
329  *
330  * DESCRIPTION: Look for the given filename in the file dependency tree.
331  *              Returns the file node if it exists, returns NULL if it does not.
332  *
333  ******************************************************************************/
334 
335 ACPI_FILE_NODE*
336 CvFilenameExists(
337     char                    *Filename,
338     ACPI_FILE_NODE          *Head)
339 {
340     ACPI_FILE_NODE          *Current = Head;
341 
342 
343     if (!Filename)
344     {
345         return (NULL);
346     }
347 
348     while (Current)
349     {
350         if (!AcpiUtStricmp (Current->Filename, Filename))
351         {
352             return (Current);
353         }
354 
355         Current = Current->Next;
356     }
357     return (NULL);
358 }
359 
360 
361 /*******************************************************************************
362  *
363  * FUNCTION:    CvFileAddressLookup
364  *
365  * PARAMETERS:  Address        - address to look up
366  *              Head           - file dependency tree
367  *
368  * RETURN:      ACPI_FILE_NODE - pointer to a file node containing the address
369  *
370  * DESCRIPTION: Look for the given address in the file dependency tree.
371  *              Returns the first file node where the given address is within
372  *              the file node's starting and ending address.
373  *
374  ******************************************************************************/
375 
376 static ACPI_FILE_NODE *
377 CvFileAddressLookup(
378     char                    *Address,
379     ACPI_FILE_NODE          *Head)
380 {
381     ACPI_FILE_NODE          *Current = Head;
382 
383 
384     while (Current)
385     {
386         if ((Address >= Current->FileStart) &&
387             (Address < Current->FileEnd ||
388             !Current->FileEnd))
389         {
390             return (Current);
391         }
392 
393         Current = Current->Next;
394     }
395 
396     return (NULL);
397 }
398 
399 
400 /*******************************************************************************
401  *
402  * FUNCTION:    CvLabelFileNode
403  *
404  * PARAMETERS:  Op
405  *
406  * RETURN:      None
407  *
408  * DESCRIPTION: Takes a given parse op, looks up its Op->Common.Aml field
409  *              within the file tree and fills in approperiate file information
410  *              from a matching node within the tree.
411  *              This is referred as ASL_CV_LABEL_FILENODE.
412  *
413  ******************************************************************************/
414 
415 void
416 CvLabelFileNode(
417     ACPI_PARSE_OBJECT       *Op)
418 {
419     ACPI_FILE_NODE          *Node;
420 
421 
422     if (!Op)
423     {
424         return;
425     }
426 
427     Node = CvFileAddressLookup ((char *)
428         Op->Common.Aml, AcpiGbl_FileTreeRoot);
429     if (!Node)
430     {
431        return;
432     }
433 
434     Op->Common.CvFilename = Node->Filename;
435     if (Node->Parent)
436     {
437         Op->Common.CvParentFilename = Node->Parent->Filename;
438     }
439     else
440     {
441         Op->Common.CvParentFilename = Node->Filename;
442     }
443 }
444 
445 
446 /*******************************************************************************
447  *
448  * FUNCTION:    CvAddToFileTree
449  *
450  * PARAMETERS:  Filename          - Address containing the name of the current
451  *                                  filename
452  *              PreviousFilename  - Address containing the name of the previous
453  *                                  filename
454  *
455  * RETURN:      None
456  *
457  * DESCRIPTION: Add this filename to the AcpiGbl_FileTree if it does not exist.
458  *
459  ******************************************************************************/
460 
461 static void
462 CvAddToFileTree (
463     char                    *Filename,
464     char                    *PreviousFilename)
465 {
466     ACPI_FILE_NODE          *Node;
467 
468 
469     if (!AcpiUtStricmp(Filename, AcpiGbl_RootFilename) &&
470         PreviousFilename)
471     {
472         Node = CvFilenameExists (PreviousFilename, AcpiGbl_FileTreeRoot);
473         if (Node)
474         {
475             /*
476              * Set the end point of the PreviousFilename to the address
477              * of Filename.
478              */
479             Node->FileEnd = Filename;
480         }
481     }
482     else if (!AcpiUtStricmp(Filename, AcpiGbl_RootFilename) &&
483              !PreviousFilename)
484     {
485         return;
486     }
487 
488     Node = CvFilenameExists (Filename, AcpiGbl_FileTreeRoot);
489     if (Node && PreviousFilename)
490     {
491         /*
492          * Update the end of the previous file and all of their parents'
493          * ending addresses. This is done to ensure that parent file
494          * ranges extend to the end of their childrens' files.
495          */
496         Node = CvFilenameExists (PreviousFilename, AcpiGbl_FileTreeRoot);
497         if (Node && (Node->FileEnd < Filename))
498         {
499             Node->FileEnd = Filename;
500             Node = Node->Parent;
501             while (Node)
502             {
503                 if (Node->FileEnd < Filename)
504                 {
505                     Node->FileEnd = Filename;
506                 }
507 
508                 Node = Node->Parent;
509             }
510         }
511     }
512     else
513     {
514         Node = AcpiGbl_FileTreeRoot;
515         AcpiGbl_FileTreeRoot = AcpiOsAcquireObject (AcpiGbl_FileCache);
516 
517         AcpiGbl_FileTreeRoot->Next = Node;
518         AcpiGbl_FileTreeRoot->Parent = NULL;
519         AcpiGbl_FileTreeRoot->Filename = Filename;
520         AcpiGbl_FileTreeRoot->FileStart = Filename;
521         AcpiGbl_FileTreeRoot->IncludeWritten = FALSE;
522         AcpiGbl_FileTreeRoot->File = fopen(Filename, "w+");
523 
524         /*
525          * If we can't open the file, we need to abort here before we
526          * accidentally write to a NULL file.
527          */
528         if (!AcpiGbl_FileTreeRoot->File)
529         {
530             /* delete the .xxx file */
531 
532             FlDeleteFile (ASL_FILE_AML_OUTPUT);
533             sprintf (MsgBuffer, "\"%s\" - %s", Filename, strerror (errno));
534             AslCommonError (ASL_ERROR, ASL_MSG_OPEN, 0, 0, 0, 0,
535                 NULL, MsgBuffer);
536             AslAbort ();
537         }
538     }
539 }
540 
541 
542 /*******************************************************************************
543  *
544  * FUNCTION:    CvSetFileParent
545  *
546  * PARAMETERS:  ChildFile  - contains the filename of the child file
547  *              ParentFile - contains the filename of the parent file.
548  *
549  * RETURN:      None
550  *
551  * DESCRIPTION: Point the parent pointer of the Child to the node that
552  *              corresponds with the parent file node.
553  *
554  ******************************************************************************/
555 
556 static void
557 CvSetFileParent (
558     char                    *ChildFile,
559     char                    *ParentFile)
560 {
561     ACPI_FILE_NODE          *Child;
562     ACPI_FILE_NODE          *Parent;
563 
564 
565     Child  = CvFilenameExists (ChildFile, AcpiGbl_FileTreeRoot);
566     Parent = CvFilenameExists (ParentFile, AcpiGbl_FileTreeRoot);
567 
568     if (Child && Parent)
569     {
570         Child->Parent = Parent;
571 
572         while (Child->Parent)
573         {
574             if (Child->Parent->FileEnd < Child->FileStart)
575             {
576                 Child->Parent->FileEnd = Child->FileStart;
577             }
578 
579             Child = Child->Parent;
580         }
581     }
582 }
583 
584 
585 /*******************************************************************************
586  *
587  * FUNCTION:    CvCaptureCommentsOnly
588  *
589  * PARAMETERS:  ParserState         - A parser state object
590  *
591  * RETURN:      None
592  *
593  * DESCRIPTION: Look at the aml that the parser state is pointing to,
594  *              capture any AML_COMMENT_OP and it's arguments and increment the
595  *              aml pointer past the comment. Comments are transferred to parse
596  *              nodes through CvTransferComments() as well as
597  *              AcpiPsBuildNamedOp().
598  *              This is referred as ASL_CV_CAPTURE_COMMENTS_ONLY.
599  *
600  ******************************************************************************/
601 
602 void
603 CvCaptureCommentsOnly (
604     ACPI_PARSE_STATE        *ParserState)
605 {
606     UINT8                   *Aml = ParserState->Aml;
607     UINT16                  Opcode = (UINT16) ACPI_GET8 (Aml);
608     UINT32                  Length = 0;
609     UINT8                   CommentOption;
610     BOOLEAN                 StdDefBlockFlag = FALSE;
611     ACPI_COMMENT_NODE       *CommentNode;
612     ACPI_FILE_NODE          *FileNode;
613 
614 
615     if (!AcpiGbl_CaptureComments ||
616         Opcode != AML_COMMENT_OP)
617     {
618        return;
619     }
620 
621     while (Opcode == AML_COMMENT_OP)
622     {
623         CvDbgPrint ("comment aml address: %p\n", Aml);
624 
625         if (CvCommentExists(ParserState->Aml))
626         {
627             CvDbgPrint ("Avoiding capturing an existing comment.\n");
628         }
629         else
630         {
631             CommentOption = *(Aml +1);
632 
633             /*
634              * Increment past the comment option and point the
635              * appropriate char pointers
636              */
637             Aml += 2;
638 
639             /* Found a comment. Now, set pointers to these comments. */
640 
641             switch (CommentOption)
642             {
643                 case STD_DEFBLK_COMMENT:
644 
645                     StdDefBlockFlag = TRUE;
646 
647                     /*
648                      * Add to a linked list of nodes. This list will be
649                      * taken by the parse node created next.
650                      */
651                     CommentNode = AcpiOsAcquireObject (
652                         AcpiGbl_RegCommentCache);
653                     CommentNode->Comment = ACPI_CAST_PTR (char, Aml);
654                     CommentNode->Next = NULL;
655 
656                     if (!AcpiGbl_DefBlkCommentListHead)
657                     {
658                         AcpiGbl_DefBlkCommentListHead = CommentNode;
659                         AcpiGbl_DefBlkCommentListTail = CommentNode;
660                     }
661                     else
662                     {
663                         AcpiGbl_DefBlkCommentListTail->Next = CommentNode;
664                         AcpiGbl_DefBlkCommentListTail =
665                             AcpiGbl_DefBlkCommentListTail->Next;
666                     }
667                     break;
668 
669                 case STANDARD_COMMENT:
670 
671                     CvDbgPrint ("found regular comment.\n");
672 
673                     /*
674                      * Add to a linked list of nodes. This list will be
675                      * taken by the parse node created next.
676                      */
677                     CommentNode = AcpiOsAcquireObject (
678                         AcpiGbl_RegCommentCache);
679                     CommentNode->Comment = ACPI_CAST_PTR (char, Aml);
680                     CommentNode->Next    = NULL;
681 
682                     if (!AcpiGbl_RegCommentListHead)
683                     {
684                         AcpiGbl_RegCommentListHead = CommentNode;
685                         AcpiGbl_RegCommentListTail = CommentNode;
686                     }
687                     else
688                     {
689                         AcpiGbl_RegCommentListTail->Next = CommentNode;
690                         AcpiGbl_RegCommentListTail =
691                             AcpiGbl_RegCommentListTail->Next;
692                     }
693                     break;
694 
695                 case ENDBLK_COMMENT:
696 
697                     CvDbgPrint ("found endblk comment.\n");
698 
699                     /* Add to a linked list of nodes. This will be
700                      * taken by the next created parse node.
701                      */
702                     CommentNode = AcpiOsAcquireObject (
703                         AcpiGbl_RegCommentCache);
704                     CommentNode->Comment = ACPI_CAST_PTR (char, Aml);
705                     CommentNode->Next    = NULL;
706 
707                     if (!AcpiGbl_EndBlkCommentListHead)
708                     {
709                         AcpiGbl_EndBlkCommentListHead = CommentNode;
710                         AcpiGbl_EndBlkCommentListTail = CommentNode;
711                     }
712                     else
713                     {
714                         AcpiGbl_EndBlkCommentListTail->Next = CommentNode;
715                         AcpiGbl_EndBlkCommentListTail =
716                             AcpiGbl_EndBlkCommentListTail->Next;
717                     }
718                     break;
719 
720                 case INLINE_COMMENT:
721 
722                     CvDbgPrint ("found inline comment.\n");
723                     AcpiGbl_CurrentInlineComment =
724                         ACPI_CAST_PTR (char, Aml);
725                     break;
726 
727                 case ENDNODE_COMMENT:
728 
729                     CvDbgPrint ("found EndNode comment.\n");
730                     AcpiGbl_CurrentEndNodeComment =
731                         ACPI_CAST_PTR (char, Aml);
732                     break;
733 
734                 case CLOSE_BRACE_COMMENT:
735 
736                     CvDbgPrint ("found close brace comment.\n");
737                     AcpiGbl_CurrentCloseBraceComment =
738                         ACPI_CAST_PTR (char, Aml);
739                     break;
740 
741                 case END_DEFBLK_COMMENT:
742 
743                     CvDbgPrint ("Found comment that belongs after"
744                         " the } for a definition block.\n");
745                     AcpiGbl_CurrentScope->Common.CloseBraceComment =
746                         ACPI_CAST_PTR (char, Aml);
747                     break;
748 
749                 case FILENAME_COMMENT:
750 
751                     CvDbgPrint ("Found a filename: %s\n",
752                         ACPI_CAST_PTR (char, Aml));
753                     FileNode = CvFilenameExists (
754                         ACPI_CAST_PTR (char, Aml), AcpiGbl_FileTreeRoot);
755 
756                     /*
757                      * If there is an INCLUDE_COMMENT followed by a
758                      * FILENAME_COMMENT, then the INCLUDE_COMMENT is a comment
759                      * that is emitted before the #include for the file.
760                      * We will save the IncludeComment within the FileNode
761                      * associated with this FILENAME_COMMENT.
762                      */
763                     if (FileNode && AcpiGbl_IncCommentListHead)
764                     {
765                         FileNode->IncludeComment = AcpiGbl_IncCommentListHead;
766                         AcpiGbl_IncCommentListHead = NULL;
767                         AcpiGbl_IncCommentListTail = NULL;
768                     }
769                     break;
770 
771                 case PARENTFILENAME_COMMENT:
772                     CvDbgPrint ("    Found a parent filename.\n");
773                     break;
774 
775                 case INCLUDE_COMMENT:
776 
777                     /*
778                      * Add to a linked list. This list will be taken by the
779                      * parse node created next. See the FILENAME_COMMENT case
780                      * for more details
781                      */
782                     CommentNode = AcpiOsAcquireObject (
783                         AcpiGbl_RegCommentCache);
784                     CommentNode->Comment = ACPI_CAST_PTR (char, Aml);
785                     CommentNode->Next = NULL;
786 
787                     if (!AcpiGbl_IncCommentListHead)
788                     {
789                         AcpiGbl_IncCommentListHead = CommentNode;
790                         AcpiGbl_IncCommentListTail = CommentNode;
791                     }
792                     else
793                     {
794                         AcpiGbl_IncCommentListTail->Next = CommentNode;
795                         AcpiGbl_IncCommentListTail =
796                             AcpiGbl_IncCommentListTail->Next;
797                     }
798 
799                     CvDbgPrint ("Found a include comment: %s\n",
800                         CommentNode->Comment);
801                     break;
802 
803                 default:
804 
805                     /* Not a valid comment option. Revert the AML */
806 
807                     Aml -= 2;
808                     goto DefBlock;
809 
810             } /* End switch statement */
811 
812         } /* End else */
813 
814         /* Determine the length and move forward that amount */
815 
816         Length = 0;
817         while (ParserState->Aml[Length])
818         {
819             Length++;
820         }
821 
822         ParserState->Aml += Length + 1;
823 
824         /* Peek at the next Opcode. */
825 
826         Aml = ParserState->Aml;
827         Opcode = (UINT16) ACPI_GET8 (Aml);
828     }
829 
830 DefBlock:
831     if (StdDefBlockFlag)
832     {
833         /*
834          * Give all of its comments to the current scope, which is known as
835          * the definition block, since STD_DEFBLK_COMMENT only appears after
836          * definition block headers.
837          */
838         AcpiGbl_CurrentScope->Common.CommentList
839             = AcpiGbl_DefBlkCommentListHead;
840         AcpiGbl_DefBlkCommentListHead = NULL;
841         AcpiGbl_DefBlkCommentListTail = NULL;
842     }
843 }
844 
845 
846 /*******************************************************************************
847  *
848  * FUNCTION:    CvCaptureComments
849  *
850  * PARAMETERS:  ParserState         - A parser state object
851  *
852  * RETURN:      None
853  *
854  * DESCRIPTION: Wrapper function for CvCaptureCommentsOnly
855  *              This is referred as ASL_CV_CAPTURE_COMMENTS.
856  *
857  ******************************************************************************/
858 
859 void
860 CvCaptureComments (
861     ACPI_WALK_STATE         *WalkState)
862 {
863     UINT8                   *Aml;
864     UINT16                  Opcode;
865     const ACPI_OPCODE_INFO  *OpInfo;
866 
867 
868     if (!AcpiGbl_CaptureComments)
869     {
870         return;
871     }
872 
873     /*
874      * Before parsing, check to see that comments that come directly
875      * after deferred opcodes aren't being processed.
876      */
877     Aml = WalkState->ParserState.Aml;
878     Opcode = (UINT16) ACPI_GET8 (Aml);
879     OpInfo = AcpiPsGetOpcodeInfo (Opcode);
880 
881     if (!(OpInfo->Flags & AML_DEFER) ||
882         ((OpInfo->Flags & AML_DEFER) &&
883         (WalkState->PassNumber != ACPI_IMODE_LOAD_PASS1)))
884     {
885         CvCaptureCommentsOnly (&WalkState->ParserState);
886         WalkState->Aml = WalkState->ParserState.Aml;
887     }
888 
889 }
890 
891 
892 /*******************************************************************************
893  *
894  * FUNCTION:    CvTransferComments
895  *
896  * PARAMETERS:  Op                  - Transfer comments to this Op
897  *
898  * RETURN:      None
899  *
900  * DESCRIPTION: Transfer all of the commments stored in global containers to the
901  *              given Op. This will be invoked shortly after the parser creates
902  *              a ParseOp.
903  *              This is referred as ASL_CV_TRANSFER_COMMENTS.
904  *
905  ******************************************************************************/
906 
907 void
908 CvTransferComments (
909     ACPI_PARSE_OBJECT       *Op)
910 {
911 
912     Op->Common.InlineComment = AcpiGbl_CurrentInlineComment;
913     AcpiGbl_CurrentInlineComment = NULL;
914 
915     Op->Common.EndNodeComment = AcpiGbl_CurrentEndNodeComment;
916     AcpiGbl_CurrentEndNodeComment = NULL;
917 
918     Op->Common.CloseBraceComment = AcpiGbl_CurrentCloseBraceComment;
919     AcpiGbl_CurrentCloseBraceComment = NULL;
920 
921     Op->Common.CommentList = AcpiGbl_RegCommentListHead;
922     AcpiGbl_RegCommentListHead = NULL;
923     AcpiGbl_RegCommentListTail = NULL;
924 
925     Op->Common.EndBlkComment = AcpiGbl_EndBlkCommentListHead;
926     AcpiGbl_EndBlkCommentListHead = NULL;
927     AcpiGbl_EndBlkCommentListTail = NULL;
928 }
929