]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/dev/acpica/compiler/prutils.c
MFV of 233442, tzdata2012a
[FreeBSD/FreeBSD.git] / sys / contrib / dev / acpica / compiler / prutils.c
1 /******************************************************************************
2  *
3  * Module Name: prutils - Preprocessor utilities
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2012, 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 <contrib/dev/acpica/compiler/aslcompiler.h>
45 #include <contrib/dev/acpica/compiler/dtcompiler.h>
46
47
48 #define _COMPONENT          ASL_PREPROCESSOR
49         ACPI_MODULE_NAME    ("prutils")
50
51
52 /*******************************************************************************
53  *
54  * FUNCTION:    PrSetLineNumber
55  *
56  * PARAMETERS:  OriginalLineNumber      - Line number in original source file,
57  *                                        or include file
58  *              PreprocessorLineNumber  - Line number in the preprocessed file
59  *
60  * RETURN:      None
61  *
62  * DESCRIPTION: Insert this mapping into the mapping data structure, for use
63  *              in possible error/warning messages.
64  *
65  * Line number mapping functions.
66  * For error messages, we need to keep track of the line number in the
67  * original file, versus the preprocessed (.i) file.
68  *
69  ******************************************************************************/
70
71 void
72 PrSetLineNumber (
73     UINT32                  OriginalLineNumber,
74     UINT32                  PreprocessorLineNumber)
75 {
76     UINT32                  Entry;
77     PR_LINE_MAPPING         *Block;
78     UINT32                  Index;
79     UINT32                  i;
80
81
82     Entry = PreprocessorLineNumber / PR_LINES_PER_BLOCK;
83     Index = PreprocessorLineNumber % PR_LINES_PER_BLOCK;
84     Block = Gbl_MapBlockHead;
85
86     for (i = 0; i < Entry; i++)
87     {
88         /* Allocate new mapping blocks as necessary */
89
90         if (!Block->Next)
91         {
92             Block->Next = UtLocalCalloc (sizeof (PR_LINE_MAPPING));
93             Block->Next->Map = UtLocalCalloc (PR_LINES_PER_BLOCK * sizeof (UINT32));
94         }
95
96         Block = Block->Next;
97     }
98
99     Block->Map[Index] = OriginalLineNumber;
100 }
101
102
103 /*******************************************************************************
104  *
105  * FUNCTION:    PrGetLineNumber
106  *
107  * PARAMETERS:  PreprocessorLineNumber  - Line number in the preprocessed file
108  *                                        (or, the "logical line number)
109  *
110  * RETURN:      The line number in the original source file or include file.
111  *
112  * DESCRIPTION: Return the mapped value of a line number in the preprocessed
113  *              source file to the actual line number in the original source
114  *              file.
115  *
116  ******************************************************************************/
117
118 UINT32
119 PrGetLineNumber (
120     UINT32                  PreprocessorLineNumber)
121 {
122     UINT32                  Entry;
123     PR_LINE_MAPPING         *Block;
124     UINT32                  Index;
125     UINT32                  i;
126
127
128     Entry = PreprocessorLineNumber / PR_LINES_PER_BLOCK;
129     Index = PreprocessorLineNumber % PR_LINES_PER_BLOCK;
130     Block = Gbl_MapBlockHead;
131
132     for (i = 0; i < Entry; i++)
133     {
134         Block = Block->Next;
135         if (!Block)
136         {
137             /* Bad error, should not happen */
138             return (0);
139         }
140     }
141
142     return (Block->Map[Index]);
143 }
144
145
146 /******************************************************************************
147  *
148  * FUNCTION:    PrGetNextToken
149  *
150  * PARAMETERS:  Buffer              - Current line buffer
151  *              MatchString         - String with valid token delimiters
152  *              Next                - Set to next possible token in buffer
153  *
154  * RETURN:      Next token (null-terminated). Modifies the input line.
155  *              Remainder of line is stored in *Next.
156  *
157  * DESCRIPTION: Local implementation of strtok() with local storage for the
158  *              next pointer. Not only thread-safe, but allows multiple
159  *              parsing of substrings such as expressions.
160  *
161  *****************************************************************************/
162
163 char *
164 PrGetNextToken (
165     char                    *Buffer,
166     char                    *MatchString,
167     char                    **Next)
168 {
169     char                    *TokenStart;
170
171
172     if (!Buffer)
173     {
174         /* Use Next if it is valid */
175
176         Buffer = *Next;
177         if (!(*Next))
178         {
179             return (NULL);
180         }
181     }
182
183     /* Skip any leading delimiters */
184
185     while (*Buffer)
186     {
187         if (strchr (MatchString, *Buffer))
188         {
189             Buffer++;
190         }
191         else
192         {
193             break;
194         }
195     }
196
197     /* Anything left on the line? */
198
199     if (!(*Buffer))
200     {
201         *Next = NULL;
202         return (NULL);
203     }
204
205     TokenStart = Buffer;
206
207     /* Find the end of this token */
208
209     while (*Buffer)
210     {
211         if (strchr (MatchString, *Buffer))
212         {
213             *Buffer = 0;
214             *Next = Buffer+1;
215             if (!**Next)
216             {
217                 *Next = NULL;
218             }
219             return (TokenStart);
220         }
221         Buffer++;
222     }
223
224     *Next = NULL;
225     return (TokenStart);
226 }
227
228
229 /*******************************************************************************
230  *
231  * FUNCTION:    PrError
232  *
233  * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
234  *              MessageId           - Index into global message buffer
235  *              Column              - Column in current line
236  *
237  * RETURN:      None
238  *
239  * DESCRIPTION: Preprocessor error reporting. Front end to AslCommonError2
240  *
241  ******************************************************************************/
242
243 void
244 PrError (
245     UINT8                   Level,
246     UINT8                   MessageId,
247     UINT32                  Column)
248 {
249 #if 0
250     AcpiOsPrintf ("%s (%u) : %s", Gbl_Files[ASL_FILE_INPUT].Filename,
251         Gbl_CurrentLineNumber, Gbl_CurrentLineBuffer);
252 #endif
253
254
255     if (Column > 120)
256     {
257         Column = 0;
258     }
259
260     /* TBD: Need Logical line number? */
261
262     AslCommonError2 (Level, MessageId,
263         Gbl_CurrentLineNumber, Column,
264         Gbl_CurrentLineBuffer,
265         Gbl_Files[ASL_FILE_INPUT].Filename, "Preprocessor");
266
267     Gbl_PreprocessorError = TRUE;
268 }
269
270
271 /*******************************************************************************
272  *
273  * FUNCTION:    PrReplaceData
274  *
275  * PARAMETERS:  Buffer              - Original(target) buffer pointer
276  *              LengthToRemove      - Length to be removed from target buffer
277  *              BufferToAdd         - Data to be inserted into target buffer
278  *              LengthToAdd         - Length of BufferToAdd
279  *
280  * RETURN:      None
281  *
282  * DESCRIPTION: Generic buffer data replacement.
283  *
284  ******************************************************************************/
285
286 void
287 PrReplaceData (
288     char                    *Buffer,
289     UINT32                  LengthToRemove,
290     char                    *BufferToAdd,
291     UINT32                  LengthToAdd)
292 {
293     UINT32                  BufferLength;
294
295
296     /* Buffer is a string, so the length must include the terminating zero */
297
298     BufferLength = strlen (Buffer) + 1;
299
300     if (LengthToRemove != LengthToAdd)
301     {
302         /*
303          * Move some of the existing data
304          * 1) If adding more bytes than removing, make room for the new data
305          * 2) if removing more bytes than adding, delete the extra space
306          */
307         if (LengthToRemove > 0)
308         {
309             memmove ((Buffer + LengthToAdd), (Buffer + LengthToRemove),
310                 (BufferLength - LengthToRemove));
311         }
312     }
313
314     /* Now we can move in the new data */
315
316     if (LengthToAdd > 0)
317     {
318         memmove (Buffer, BufferToAdd, LengthToAdd);
319     }
320 }
321
322
323 /*******************************************************************************
324  *
325  * FUNCTION:    PrOpenIncludeFile
326  *
327  * PARAMETERS:  Filename            - Filename or pathname for include file
328  *
329  * RETURN:      None.
330  *
331  * DESCRIPTION: Open an include file and push it on the input file stack.
332  *
333  ******************************************************************************/
334
335 void
336 PrOpenIncludeFile (
337     char                    *Filename)
338 {
339     FILE                    *IncludeFile;
340     ASL_INCLUDE_DIR         *NextDir;
341
342
343     /*
344      * start the actual include file on the next line
345      */
346     Gbl_CurrentLineOffset++;
347
348     /* Attempt to open the include file */
349
350     /* If the file specifies an absolute path, just open it */
351
352     if ((Filename[0] == '/')  ||
353         (Filename[0] == '\\') ||
354         (Filename[1] == ':'))
355     {
356         IncludeFile = PrOpenIncludeWithPrefix ("", Filename);
357         if (!IncludeFile)
358         {
359             goto ErrorExit;
360         }
361         return;
362     }
363
364     /*
365      * The include filename is not an absolute path.
366      *
367      * First, search for the file within the "local" directory -- meaning
368      * the same directory that contains the source file.
369      *
370      * Construct the file pathname from the global directory name.
371      */
372     IncludeFile = PrOpenIncludeWithPrefix (Gbl_DirectoryPath, Filename);
373     if (IncludeFile)
374     {
375         return;
376     }
377
378     /*
379      * Second, search for the file within the (possibly multiple)
380      * directories specified by the -I option on the command line.
381      */
382     NextDir = Gbl_IncludeDirList;
383     while (NextDir)
384     {
385         IncludeFile = PrOpenIncludeWithPrefix (NextDir->Dir, Filename);
386         if (IncludeFile)
387         {
388             return;
389         }
390
391         NextDir = NextDir->Next;
392     }
393
394     /* We could not open the include file after trying very hard */
395
396 ErrorExit:
397     sprintf (Gbl_MainTokenBuffer, "%s, %s", Filename, strerror (errno));
398     PrError (ASL_ERROR, ASL_MSG_INCLUDE_FILE_OPEN, 0);
399 }
400
401
402 /*******************************************************************************
403  *
404  * FUNCTION:    FlOpenIncludeWithPrefix
405  *
406  * PARAMETERS:  PrefixDir       - Prefix directory pathname. Can be a zero
407  *                                length string.
408  *              Filename        - The include filename from the source ASL.
409  *
410  * RETURN:      Valid file descriptor if successful. Null otherwise.
411  *
412  * DESCRIPTION: Open an include file and push it on the input file stack.
413  *
414  ******************************************************************************/
415
416 FILE *
417 PrOpenIncludeWithPrefix (
418     char                    *PrefixDir,
419     char                    *Filename)
420 {
421     FILE                    *IncludeFile;
422     char                    *Pathname;
423
424
425     /* Build the full pathname to the file */
426
427     Pathname = ACPI_ALLOCATE (strlen (PrefixDir) + strlen (Filename) + 1);
428
429     strcpy (Pathname, PrefixDir);
430     strcat (Pathname, Filename);
431
432     DbgPrint (ASL_PARSE_OUTPUT, "\n" PR_PREFIX_ID
433         "Opening include file: path %s\n",
434         Gbl_CurrentLineNumber, Pathname);
435
436     /* Attempt to open the file, push if successful */
437
438     IncludeFile = fopen (Pathname, "r");
439     if (IncludeFile)
440     {
441         /* Push the include file on the open input file stack */
442
443         PrPushInputFileStack (IncludeFile, Pathname);
444         return (IncludeFile);
445     }
446
447     ACPI_FREE (Pathname);
448     return (NULL);
449 }
450
451
452 /*******************************************************************************
453  *
454  * FUNCTION:    AslPushInputFileStack
455  *
456  * PARAMETERS:  InputFile           - Open file pointer
457  *              Filename            - Name of the file
458  *
459  * RETURN:      None
460  *
461  * DESCRIPTION: Push the InputFile onto the file stack, and point the parser
462  *              to this file. Called when an include file is successfully
463  *              opened.
464  *
465  ******************************************************************************/
466
467 void
468 PrPushInputFileStack (
469     FILE                    *InputFile,
470     char                    *Filename)
471 {
472     PR_FILE_NODE            *Fnode;
473
474
475     /* Save the current state in an Fnode */
476
477     Fnode = UtLocalCalloc (sizeof (PR_FILE_NODE));
478
479     Fnode->File = Gbl_Files[ASL_FILE_INPUT].Handle;
480     Fnode->Next = Gbl_InputFileList;
481     Fnode->Filename = Gbl_Files[ASL_FILE_INPUT].Filename;
482     Fnode->CurrentLineNumber = Gbl_CurrentLineNumber;
483
484     /* Push it on the stack */
485
486     Gbl_InputFileList = Fnode;
487
488     DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
489         "Push InputFile Stack, returning %p\n\n",
490         Gbl_CurrentLineNumber, InputFile);
491
492     /* Reset the global line count and filename */
493
494     Gbl_Files[ASL_FILE_INPUT].Filename = Filename;
495     Gbl_Files[ASL_FILE_INPUT].Handle = InputFile;
496     Gbl_CurrentLineNumber = 1;
497 }
498
499
500 /*******************************************************************************
501  *
502  * FUNCTION:    AslPopInputFileStack
503  *
504  * PARAMETERS:  None
505  *
506  * RETURN:      0 if a node was popped, -1 otherwise
507  *
508  * DESCRIPTION: Pop the top of the input file stack and point the parser to
509  *              the saved parse buffer contained in the fnode.  Also, set the
510  *              global line counters to the saved values.  This function is
511  *              called when an include file reaches EOF.
512  *
513  ******************************************************************************/
514
515 BOOLEAN
516 PrPopInputFileStack (
517     void)
518 {
519     PR_FILE_NODE            *Fnode;
520
521
522     Fnode = Gbl_InputFileList;
523     DbgPrint (ASL_PARSE_OUTPUT, "\n" PR_PREFIX_ID
524         "Pop InputFile Stack, Fnode %p\n\n",
525         Gbl_CurrentLineNumber, Fnode);
526
527     if (!Fnode)
528     {
529         return (FALSE);
530     }
531
532     /* Close the current include file */
533
534     fclose (Gbl_Files[ASL_FILE_INPUT].Handle);
535
536     /* Update the top-of-stack */
537
538     Gbl_InputFileList = Fnode->Next;
539
540     /* Reset global line counter and filename */
541
542     Gbl_Files[ASL_FILE_INPUT].Filename = Fnode->Filename;
543     Gbl_Files[ASL_FILE_INPUT].Handle = Fnode->File;
544     Gbl_CurrentLineNumber = Fnode->CurrentLineNumber;
545
546     /* All done with this node */
547
548     ACPI_FREE (Fnode);
549     return (TRUE);
550 }