aslsupport.l revision 250838
1234518Sjkim/******************************************************************************
2234518Sjkim *
3234518Sjkim * Module Name: aslsupport.l - Flex/lex scanner C support routines.
4234518Sjkim *              NOTE: Included into aslcompile.l, not compiled by itself.
5234518Sjkim *
6234518Sjkim *****************************************************************************/
7234518Sjkim
8234518Sjkim/*
9245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp.
10234518Sjkim * All rights reserved.
11234518Sjkim *
12234518Sjkim * Redistribution and use in source and binary forms, with or without
13234518Sjkim * modification, are permitted provided that the following conditions
14234518Sjkim * are met:
15234518Sjkim * 1. Redistributions of source code must retain the above copyright
16234518Sjkim *    notice, this list of conditions, and the following disclaimer,
17234518Sjkim *    without modification.
18234518Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19234518Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
20234518Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
21234518Sjkim *    including a substantially similar Disclaimer requirement for further
22234518Sjkim *    binary redistribution.
23234518Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
24234518Sjkim *    of any contributors may be used to endorse or promote products derived
25234518Sjkim *    from this software without specific prior written permission.
26234518Sjkim *
27234518Sjkim * Alternatively, this software may be distributed under the terms of the
28234518Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
29234518Sjkim * Software Foundation.
30234518Sjkim *
31234518Sjkim * NO WARRANTY
32234518Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33234518Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34234518Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35234518Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36234518Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37234518Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38234518Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39234518Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40234518Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41234518Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42234518Sjkim * POSSIBILITY OF SUCH DAMAGES.
43234518Sjkim */
44234518Sjkim
45234518Sjkim
46234518Sjkim/* Configuration */
47234518Sjkim
48234518Sjkim#define ASL_SPACES_PER_TAB      4
49234518Sjkim
50234518Sjkim#define ASL_NORMAL_CHAR         0
51234518Sjkim#define ASL_ESCAPE_SEQUENCE     1
52234518Sjkim#define ASL_OCTAL_CONSTANT      2
53234518Sjkim#define ASL_HEX_CONSTANT        3
54234518Sjkim
55234518Sjkim
56234518Sjkim/* File node - used for "Include" operator file stack */
57234518Sjkim
58234518Sjkimtypedef struct asl_file_node
59234518Sjkim{
60234518Sjkim    FILE                    *File;
61234518Sjkim    UINT32                  CurrentLineNumber;
62234518Sjkim    YY_BUFFER_STATE         State;
63234518Sjkim    char                    *Filename;
64234518Sjkim    struct asl_file_node    *Next;
65234518Sjkim
66234518Sjkim} ASL_FILE_NODE;
67234518Sjkim
68234518Sjkim/* File stack for the "Include" operator (NOT #include operator) */
69234518Sjkim
70234518SjkimASL_FILE_NODE               *Gbl_IncludeFileStack = NULL;
71234518Sjkim
72234518Sjkim
73234518Sjkim/*******************************************************************************
74234518Sjkim *
75234518Sjkim * FUNCTION:    AslDoLineDirective
76234518Sjkim *
77234518Sjkim * PARAMETERS:  None. Uses input() to access current source code line
78234518Sjkim *
79234518Sjkim * RETURN:      Updates global line number and filename
80234518Sjkim *
81234518Sjkim * DESCRIPTION: Handle #line directives emitted by the preprocessor.
82234518Sjkim *
83234518Sjkim * The #line directive is emitted by the preprocesser, and is used to
84234518Sjkim * pass through line numbers from the original source code file to the
85234518Sjkim * preprocessor output file (.i). This allows any compiler-generated
86234518Sjkim * error messages to be displayed with the correct line number.
87234518Sjkim *
88234518Sjkim ******************************************************************************/
89234518Sjkim
90234518Sjkimstatic void
91234518SjkimAslDoLineDirective (
92234518Sjkim    void)
93234518Sjkim{
94237412Sjkim    int                     c;
95234518Sjkim    char                    *Token;
96234518Sjkim    UINT32                  LineNumber;
97234518Sjkim    char                    *Filename;
98237412Sjkim    UINT32                  i;
99234518Sjkim
100234518Sjkim
101234518Sjkim    /* Eat the entire line that contains the #line directive */
102234518Sjkim
103237412Sjkim    Gbl_LineBufPtr = Gbl_CurrentLineBuffer;
104237412Sjkim
105237412Sjkim    while ((c = input()) != '\n' && c != EOF)
106234518Sjkim    {
107237412Sjkim        *Gbl_LineBufPtr = c;
108237412Sjkim        Gbl_LineBufPtr++;
109234518Sjkim    }
110237412Sjkim    *Gbl_LineBufPtr = 0;
111234518Sjkim
112234518Sjkim    /* First argument is the actual line number */
113234518Sjkim
114234518Sjkim    Token = strtok (Gbl_CurrentLineBuffer, " ");
115234518Sjkim    if (!Token)
116234518Sjkim    {
117234518Sjkim        goto ResetAndExit;
118234518Sjkim    }
119234518Sjkim
120237412Sjkim    /* First argument is the line number */
121234518Sjkim
122234518Sjkim    LineNumber = (UINT32) UtDoConstant (Token);
123234518Sjkim
124237412Sjkim    /* Emit the appropriate number of newlines */
125237412Sjkim
126237412Sjkim    Gbl_CurrentColumn = 0;
127237412Sjkim    if (LineNumber > Gbl_CurrentLineNumber)
128237412Sjkim    {
129237412Sjkim        for (i = 0; i < (LineNumber - Gbl_CurrentLineNumber); i++)
130237412Sjkim        {
131237412Sjkim            FlWriteFile (ASL_FILE_SOURCE_OUTPUT, "\n", 1);
132237412Sjkim            Gbl_CurrentColumn++;
133237412Sjkim        }
134237412Sjkim    }
135237412Sjkim
136237412Sjkim    FlSetLineNumber (LineNumber);
137237412Sjkim
138234518Sjkim    /* Second argument is the optional filename (in double quotes) */
139234518Sjkim
140234518Sjkim    Token = strtok (NULL, " \"");
141234518Sjkim    if (Token)
142234518Sjkim    {
143234518Sjkim        Filename = ACPI_ALLOCATE_ZEROED (strlen (Token) + 1);
144234518Sjkim        strcpy (Filename, Token);
145234518Sjkim        FlSetFilename (Filename);
146234518Sjkim    }
147234518Sjkim
148234518Sjkim    /* Third argument is not supported at this time */
149234518Sjkim
150234518SjkimResetAndExit:
151237412Sjkim
152237412Sjkim    /* Reset globals for a new line */
153237412Sjkim
154237412Sjkim    Gbl_CurrentLineOffset += Gbl_CurrentColumn;
155237412Sjkim    Gbl_CurrentColumn = 0;
156237412Sjkim    Gbl_LineBufPtr = Gbl_CurrentLineBuffer;
157234518Sjkim}
158234518Sjkim
159234518Sjkim
160234518Sjkim/*******************************************************************************
161234518Sjkim *
162234518Sjkim * FUNCTION:    AslPopInputFileStack
163234518Sjkim *
164234518Sjkim * PARAMETERS:  None
165234518Sjkim *
166234518Sjkim * RETURN:      0 if a node was popped, -1 otherwise
167234518Sjkim *
168234518Sjkim * DESCRIPTION: Pop the top of the input file stack and point the parser to
169241973Sjkim *              the saved parse buffer contained in the fnode. Also, set the
170241973Sjkim *              global line counters to the saved values. This function is
171234518Sjkim *              called when an include file reaches EOF.
172234518Sjkim *
173234518Sjkim ******************************************************************************/
174234518Sjkim
175234518Sjkimint
176234518SjkimAslPopInputFileStack (
177234518Sjkim    void)
178234518Sjkim{
179234518Sjkim    ASL_FILE_NODE           *Fnode;
180234518Sjkim
181234518Sjkim
182234518Sjkim    Fnode = Gbl_IncludeFileStack;
183234518Sjkim    DbgPrint (ASL_PARSE_OUTPUT, "\nPop InputFile Stack, Fnode %p\n\n", Fnode);
184234518Sjkim
185234518Sjkim    if (!Fnode)
186234518Sjkim    {
187234518Sjkim        return (-1);
188234518Sjkim    }
189234518Sjkim
190234518Sjkim    /* Close the current include file */
191234518Sjkim
192234518Sjkim    fclose (yyin);
193234518Sjkim
194234518Sjkim    /* Update the top-of-stack */
195234518Sjkim
196234518Sjkim    Gbl_IncludeFileStack = Fnode->Next;
197234518Sjkim
198234518Sjkim    /* Reset global line counter and filename */
199234518Sjkim
200234518Sjkim    Gbl_Files[ASL_FILE_INPUT].Filename = Fnode->Filename;
201234518Sjkim    Gbl_CurrentLineNumber = Fnode->CurrentLineNumber;
202234518Sjkim
203234518Sjkim    /* Point the parser to the popped file */
204234518Sjkim
205234518Sjkim    yy_delete_buffer (YY_CURRENT_BUFFER);
206234518Sjkim    yy_switch_to_buffer (Fnode->State);
207234518Sjkim
208234518Sjkim    /* All done with this node */
209234518Sjkim
210234518Sjkim    ACPI_FREE (Fnode);
211234518Sjkim    return (0);
212234518Sjkim}
213234518Sjkim
214234518Sjkim
215234518Sjkim/*******************************************************************************
216234518Sjkim *
217234518Sjkim * FUNCTION:    AslPushInputFileStack
218234518Sjkim *
219234518Sjkim * PARAMETERS:  InputFile           - Open file pointer
220234518Sjkim *              Filename            - Name of the file
221234518Sjkim *
222234518Sjkim * RETURN:      None
223234518Sjkim *
224234518Sjkim * DESCRIPTION: Push the InputFile onto the file stack, and point the parser
225241973Sjkim *              to this file. Called when an include file is successfully
226234518Sjkim *              opened.
227234518Sjkim *
228234518Sjkim ******************************************************************************/
229234518Sjkim
230234518Sjkimvoid
231234518SjkimAslPushInputFileStack (
232234518Sjkim    FILE                    *InputFile,
233234518Sjkim    char                    *Filename)
234234518Sjkim{
235234518Sjkim    ASL_FILE_NODE           *Fnode;
236234518Sjkim    YY_BUFFER_STATE         State;
237234518Sjkim
238234518Sjkim
239234518Sjkim    /* Save the current state in an Fnode */
240234518Sjkim
241234518Sjkim    Fnode = UtLocalCalloc (sizeof (ASL_FILE_NODE));
242234518Sjkim
243234518Sjkim    Fnode->File                 = yyin;
244234518Sjkim    Fnode->Next                 = Gbl_IncludeFileStack;
245234518Sjkim    Fnode->State                = YY_CURRENT_BUFFER;
246234518Sjkim    Fnode->CurrentLineNumber    = Gbl_CurrentLineNumber;
247234518Sjkim    Fnode->Filename             = Gbl_Files[ASL_FILE_INPUT].Filename;
248234518Sjkim
249234518Sjkim    /* Push it on the stack */
250234518Sjkim
251234518Sjkim    Gbl_IncludeFileStack = Fnode;
252234518Sjkim
253234518Sjkim    /* Point the parser to this file */
254234518Sjkim
255234518Sjkim    State = yy_create_buffer (InputFile, YY_BUF_SIZE);
256234518Sjkim    yy_switch_to_buffer (State);
257234518Sjkim
258234518Sjkim    DbgPrint (ASL_PARSE_OUTPUT, "\nPush InputFile Stack, returning %p\n\n", InputFile);
259234518Sjkim
260234518Sjkim    /* Reset the global line count and filename */
261234518Sjkim
262234518Sjkim    Gbl_Files[ASL_FILE_INPUT].Filename = Filename;
263234518Sjkim    Gbl_CurrentLineNumber = 1;
264234518Sjkim    yyin = InputFile;
265234518Sjkim}
266234518Sjkim
267234518Sjkim
268234518Sjkim/*******************************************************************************
269234518Sjkim *
270234518Sjkim * FUNCTION:    AslResetCurrentLineBuffer
271234518Sjkim *
272234518Sjkim * PARAMETERS:  None
273234518Sjkim *
274234518Sjkim * RETURN:      None
275234518Sjkim *
276234518Sjkim * DESCRIPTION: Reset the Line Buffer to zero, increment global line numbers.
277234518Sjkim *
278234518Sjkim ******************************************************************************/
279234518Sjkim
280234518Sjkimvoid
281234518SjkimAslResetCurrentLineBuffer (
282234518Sjkim    void)
283234518Sjkim{
284234518Sjkim
285234518Sjkim    if (Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Handle)
286234518Sjkim    {
287234518Sjkim        FlWriteFile (ASL_FILE_SOURCE_OUTPUT, Gbl_CurrentLineBuffer,
288234518Sjkim            Gbl_LineBufPtr - Gbl_CurrentLineBuffer);
289234518Sjkim    }
290234518Sjkim
291234518Sjkim    Gbl_CurrentLineOffset += Gbl_CurrentColumn;
292234518Sjkim    Gbl_CurrentColumn = 0;
293234518Sjkim
294234518Sjkim    Gbl_CurrentLineNumber++;
295234518Sjkim    Gbl_LogicalLineNumber++;
296234518Sjkim    Gbl_LineBufPtr = Gbl_CurrentLineBuffer;
297234518Sjkim}
298234518Sjkim
299234518Sjkim
300234518Sjkim/*******************************************************************************
301234518Sjkim *
302234518Sjkim * FUNCTION:    AslInsertLineBuffer
303234518Sjkim *
304234518Sjkim * PARAMETERS:  SourceChar      - One char from the input ASL source file
305234518Sjkim *
306234518Sjkim * RETURN:      None
307234518Sjkim *
308234518Sjkim * DESCRIPTION: Put one character of the source file into the temp line buffer
309234518Sjkim *
310234518Sjkim ******************************************************************************/
311234518Sjkim
312234518Sjkimvoid
313234518SjkimAslInsertLineBuffer (
314234518Sjkim    int                     SourceChar)
315234518Sjkim{
316234518Sjkim    UINT32                  i;
317234518Sjkim    UINT32                  Count = 1;
318234518Sjkim
319234518Sjkim
320234518Sjkim    if (SourceChar == EOF)
321234518Sjkim    {
322234518Sjkim        return;
323234518Sjkim    }
324234518Sjkim
325234518Sjkim    Gbl_InputByteCount++;
326234518Sjkim
327241973Sjkim    /* Handle tabs. Convert to spaces */
328234518Sjkim
329234518Sjkim    if (SourceChar == '\t')
330234518Sjkim    {
331234518Sjkim        SourceChar = ' ';
332234518Sjkim        Count = ASL_SPACES_PER_TAB -
333234518Sjkim                    (Gbl_CurrentColumn & (ASL_SPACES_PER_TAB-1));
334234518Sjkim    }
335234518Sjkim
336234518Sjkim    for (i = 0; i < Count; i++)
337234518Sjkim    {
338234518Sjkim        Gbl_CurrentColumn++;
339234518Sjkim
340234518Sjkim        /* Insert the character into the line buffer */
341234518Sjkim
342234518Sjkim        *Gbl_LineBufPtr = (UINT8) SourceChar;
343234518Sjkim        Gbl_LineBufPtr++;
344234518Sjkim
345240716Sjkim        if (Gbl_LineBufPtr > (Gbl_CurrentLineBuffer + (Gbl_LineBufferSize - 1)))
346234518Sjkim        {
347234518Sjkim#if 0
348234518Sjkim            /*
349234518Sjkim             * Warning if we have split a long source line.
350234518Sjkim             * <Probably overkill>
351234518Sjkim             */
352240716Sjkim            sprintf (MsgBuffer, "Max %u", Gbl_LineBufferSize);
353234518Sjkim            AslCommonError (ASL_WARNING, ASL_MSG_LONG_LINE,
354234518Sjkim                            Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
355234518Sjkim                            Gbl_CurrentLineOffset, Gbl_CurrentColumn,
356234518Sjkim                            Gbl_Files[ASL_FILE_INPUT].Filename, MsgBuffer);
357234518Sjkim#endif
358234518Sjkim
359234518Sjkim            AslResetCurrentLineBuffer ();
360234518Sjkim        }
361234518Sjkim        else if (SourceChar == '\n')
362234518Sjkim        {
363234518Sjkim            /* End of line */
364234518Sjkim
365234518Sjkim            AslResetCurrentLineBuffer ();
366234518Sjkim        }
367234518Sjkim    }
368234518Sjkim}
369234518Sjkim
370234518Sjkim
371234518Sjkim/*******************************************************************************
372234518Sjkim *
373234518Sjkim * FUNCTION:    count
374234518Sjkim *
375234518Sjkim * PARAMETERS:  yytext      - Contains the matched keyword.
376234518Sjkim *              Type        - Keyword/Character type:
377234518Sjkim *                             0 = anything except a keyword
378234518Sjkim *                             1 = pseudo-keywords
379234518Sjkim *                             2 = non-executable ASL keywords
380234518Sjkim *                             3 = executable ASL keywords
381234518Sjkim *
382234518Sjkim * RETURN:      None
383234518Sjkim *
384234518Sjkim * DESCRIPTION: Count keywords and put them into the line buffer
385234518Sjkim *
386234518Sjkim ******************************************************************************/
387234518Sjkim
388234518Sjkimstatic void
389234518Sjkimcount (
390234518Sjkim    int                 Type)
391234518Sjkim{
392234518Sjkim    int                 i;
393234518Sjkim
394234518Sjkim
395234518Sjkim    switch (Type)
396234518Sjkim    {
397234518Sjkim    case 2:
398250838Sjkim
399234518Sjkim        TotalKeywords++;
400234518Sjkim        TotalNamedObjects++;
401234518Sjkim        break;
402234518Sjkim
403234518Sjkim    case 3:
404250838Sjkim
405234518Sjkim        TotalKeywords++;
406234518Sjkim        TotalExecutableOpcodes++;
407234518Sjkim        break;
408246849Sjkim
409246849Sjkim    default:
410250838Sjkim
411246849Sjkim        break;
412234518Sjkim    }
413234518Sjkim
414234518Sjkim    for (i = 0; (yytext[i] != 0) && (yytext[i] != EOF); i++)
415234518Sjkim    {
416234518Sjkim        AslInsertLineBuffer (yytext[i]);
417234518Sjkim        *Gbl_LineBufPtr = 0;
418234518Sjkim    }
419234518Sjkim}
420234518Sjkim
421234518Sjkim
422234518Sjkim/*******************************************************************************
423234518Sjkim *
424234518Sjkim * FUNCTION:    AslDoComment
425234518Sjkim *
426234518Sjkim * PARAMETERS:  none
427234518Sjkim *
428234518Sjkim * RETURN:      none
429234518Sjkim *
430234518Sjkim * DESCRIPTION: Process a standard comment.
431234518Sjkim *
432234518Sjkim ******************************************************************************/
433234518Sjkim
434234518Sjkimstatic char
435234518SjkimAslDoComment (
436234518Sjkim    void)
437234518Sjkim{
438237412Sjkim    int                 c;
439237412Sjkim    int                 c1 = 0;
440234518Sjkim
441234518Sjkim
442234518Sjkim    AslInsertLineBuffer ('/');
443234518Sjkim    AslInsertLineBuffer ('*');
444234518Sjkim
445234518Sjkimloop:
446234518Sjkim
447234518Sjkim    /* Eat chars until end-of-comment */
448234518Sjkim
449237412Sjkim    while ((c = input()) != '*' && c != EOF)
450234518Sjkim    {
451234518Sjkim        AslInsertLineBuffer (c);
452234518Sjkim        c1 = c;
453234518Sjkim    }
454234518Sjkim
455234518Sjkim    if (c == EOF)
456234518Sjkim    {
457234518Sjkim        goto EarlyEOF;
458234518Sjkim    }
459234518Sjkim
460234518Sjkim    /*
461234518Sjkim     * Check for nested comment -- can help catch cases where a previous
462234518Sjkim     * comment was accidently left unterminated
463234518Sjkim     */
464234518Sjkim    if ((c1 == '/') && (c == '*'))
465234518Sjkim    {
466234518Sjkim        AslCommonError (ASL_WARNING, ASL_MSG_NESTED_COMMENT,
467234518Sjkim                        Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
468234518Sjkim                        Gbl_InputByteCount, Gbl_CurrentColumn,
469234518Sjkim                        Gbl_Files[ASL_FILE_INPUT].Filename, NULL);
470234518Sjkim    }
471234518Sjkim
472234518Sjkim    /* Comment is closed only if the NEXT character is a slash */
473234518Sjkim
474234518Sjkim    AslInsertLineBuffer (c);
475234518Sjkim
476237412Sjkim    if ((c1 = input()) != '/' && c1 != EOF)
477234518Sjkim    {
478234518Sjkim        unput(c1);
479234518Sjkim        goto loop;
480234518Sjkim    }
481234518Sjkim
482234518Sjkim    if (c1 == EOF)
483234518Sjkim    {
484234518Sjkim        goto EarlyEOF;
485234518Sjkim    }
486234518Sjkim
487234518Sjkim    AslInsertLineBuffer (c1);
488234518Sjkim    return (TRUE);
489234518Sjkim
490234518Sjkim
491234518SjkimEarlyEOF:
492234518Sjkim    /*
493234518Sjkim     * Premature End-Of-File
494234518Sjkim     */
495234518Sjkim    AslCommonError (ASL_ERROR, ASL_MSG_EARLY_EOF,
496234518Sjkim                    Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
497234518Sjkim                    Gbl_CurrentLineOffset, Gbl_CurrentColumn,
498234518Sjkim                    Gbl_Files[ASL_FILE_INPUT].Filename, NULL);
499234518Sjkim    return (FALSE);
500234518Sjkim}
501234518Sjkim
502234518Sjkim
503234518Sjkim/*******************************************************************************
504234518Sjkim *
505234518Sjkim * FUNCTION:    AslDoCommentType2
506234518Sjkim *
507234518Sjkim * PARAMETERS:  none
508234518Sjkim *
509234518Sjkim * RETURN:      none
510234518Sjkim *
511234518Sjkim * DESCRIPTION: Process a new "//" comment.
512234518Sjkim *
513234518Sjkim ******************************************************************************/
514234518Sjkim
515234518Sjkimstatic char
516234518SjkimAslDoCommentType2 (
517234518Sjkim    void)
518234518Sjkim{
519237412Sjkim    int                 c;
520234518Sjkim
521234518Sjkim
522234518Sjkim    AslInsertLineBuffer ('/');
523234518Sjkim    AslInsertLineBuffer ('/');
524234518Sjkim
525237412Sjkim    while ((c = input()) != '\n' && c != EOF)
526234518Sjkim    {
527234518Sjkim        AslInsertLineBuffer (c);
528234518Sjkim    }
529234518Sjkim
530234518Sjkim    if (c == EOF)
531234518Sjkim    {
532234518Sjkim        /* End of file is OK, change to newline. Let parser detect EOF later */
533234518Sjkim
534234518Sjkim        c = '\n';
535234518Sjkim    }
536234518Sjkim
537234518Sjkim    AslInsertLineBuffer (c);
538234518Sjkim    return (TRUE);
539234518Sjkim}
540234518Sjkim
541234518Sjkim
542234518Sjkim/*******************************************************************************
543234518Sjkim *
544234518Sjkim * FUNCTION:    AslDoStringLiteral
545234518Sjkim *
546234518Sjkim * PARAMETERS:  none
547234518Sjkim *
548234518Sjkim * RETURN:      none
549234518Sjkim *
550234518Sjkim * DESCRIPTION: Process a string literal (surrounded by quotes)
551234518Sjkim *
552234518Sjkim ******************************************************************************/
553234518Sjkim
554234518Sjkimstatic char
555234518SjkimAslDoStringLiteral (
556234518Sjkim    void)
557234518Sjkim{
558234518Sjkim    char                *StringBuffer = MsgBuffer;
559234518Sjkim    char                *EndBuffer = MsgBuffer + ASL_MSG_BUFFER_SIZE;
560234518Sjkim    char                *CleanString;
561237412Sjkim    int                 StringChar;
562234518Sjkim    UINT32              State = ASL_NORMAL_CHAR;
563234518Sjkim    UINT32              i = 0;
564234518Sjkim    UINT8               Digit;
565234518Sjkim    char                ConvertBuffer[4];
566234518Sjkim
567234518Sjkim
568234518Sjkim    /*
569234518Sjkim     * Eat chars until end-of-literal.
570234518Sjkim     * NOTE:  Put back the original surrounding quotes into the
571234518Sjkim     * source line buffer.
572234518Sjkim     */
573234518Sjkim    AslInsertLineBuffer ('\"');
574237412Sjkim    while ((StringChar = input()) != EOF)
575234518Sjkim    {
576234518Sjkim        AslInsertLineBuffer (StringChar);
577234518Sjkim
578234518SjkimDoCharacter:
579234518Sjkim        switch (State)
580234518Sjkim        {
581234518Sjkim        case ASL_NORMAL_CHAR:
582234518Sjkim
583234518Sjkim            switch (StringChar)
584234518Sjkim            {
585234518Sjkim            case '\\':
586234518Sjkim                /*
587241973Sjkim                 * Special handling for backslash-escape sequence. We will
588234518Sjkim                 * toss the backslash and translate the escape char(s).
589234518Sjkim                 */
590234518Sjkim                State = ASL_ESCAPE_SEQUENCE;
591234518Sjkim                continue;
592234518Sjkim
593234518Sjkim            case '\"':
594234518Sjkim
595234518Sjkim                /* String terminator */
596234518Sjkim
597234518Sjkim                goto CompletedString;
598246849Sjkim
599246849Sjkim            default:
600250838Sjkim
601246849Sjkim                break;
602234518Sjkim            }
603234518Sjkim            break;
604234518Sjkim
605234518Sjkim
606234518Sjkim        case ASL_ESCAPE_SEQUENCE:
607234518Sjkim
608234518Sjkim            State = ASL_NORMAL_CHAR;
609234518Sjkim            switch (StringChar)
610234518Sjkim            {
611234518Sjkim            case 'a':
612250838Sjkim
613234518Sjkim                StringChar = 0x07;      /* BELL */
614234518Sjkim                break;
615234518Sjkim
616234518Sjkim            case 'b':
617250838Sjkim
618234518Sjkim                StringChar = 0x08;      /* BACKSPACE */
619234518Sjkim                break;
620234518Sjkim
621234518Sjkim            case 'f':
622250838Sjkim
623234518Sjkim                StringChar = 0x0C;      /* FORMFEED */
624234518Sjkim                break;
625234518Sjkim
626234518Sjkim            case 'n':
627250838Sjkim
628234518Sjkim                StringChar = 0x0A;      /* LINEFEED */
629234518Sjkim                break;
630234518Sjkim
631234518Sjkim            case 'r':
632250838Sjkim
633234518Sjkim                StringChar = 0x0D;      /* CARRIAGE RETURN*/
634234518Sjkim                break;
635234518Sjkim
636234518Sjkim            case 't':
637250838Sjkim
638234518Sjkim                StringChar = 0x09;      /* HORIZONTAL TAB */
639234518Sjkim                break;
640234518Sjkim
641234518Sjkim            case 'v':
642250838Sjkim
643234518Sjkim                StringChar = 0x0B;      /* VERTICAL TAB */
644234518Sjkim                break;
645234518Sjkim
646234518Sjkim            case 'x':
647250838Sjkim
648234518Sjkim                State = ASL_HEX_CONSTANT;
649234518Sjkim                i = 0;
650234518Sjkim                continue;
651234518Sjkim
652234518Sjkim            case '\'':                  /* Single Quote */
653234518Sjkim            case '\"':                  /* Double Quote */
654234518Sjkim            case '\\':                  /* Backslash */
655250838Sjkim
656234518Sjkim                break;
657234518Sjkim
658234518Sjkim            default:
659234518Sjkim
660234518Sjkim                /* Check for an octal digit (0-7) */
661234518Sjkim
662234518Sjkim                if (ACPI_IS_OCTAL_DIGIT (StringChar))
663234518Sjkim                {
664234518Sjkim                    State = ASL_OCTAL_CONSTANT;
665234518Sjkim                    ConvertBuffer[0] = StringChar;
666234518Sjkim                    i = 1;
667234518Sjkim                    continue;
668234518Sjkim                }
669234518Sjkim
670234518Sjkim                /* Unknown escape sequence issue warning, but use the character */
671234518Sjkim
672234518Sjkim                AslCommonError (ASL_WARNING, ASL_MSG_INVALID_ESCAPE,
673234518Sjkim                                Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
674234518Sjkim                                Gbl_CurrentLineOffset, Gbl_CurrentColumn,
675234518Sjkim                                Gbl_Files[ASL_FILE_INPUT].Filename, NULL);
676234518Sjkim                break;
677234518Sjkim            }
678234518Sjkim            break;
679234518Sjkim
680234518Sjkim
681234518Sjkim        case ASL_OCTAL_CONSTANT:
682234518Sjkim
683234518Sjkim            /* Up to three octal digits allowed */
684234518Sjkim
685234518Sjkim            if (!ACPI_IS_OCTAL_DIGIT (StringChar) ||
686234518Sjkim                (i > 2))
687234518Sjkim            {
688234518Sjkim                /*
689241973Sjkim                 * Reached end of the constant. Convert the assembled ASCII
690234518Sjkim                 * string and resume processing of the next character
691234518Sjkim                 */
692234518Sjkim                ConvertBuffer[i] = 0;
693234518Sjkim                Digit = (UINT8) ACPI_STRTOUL (ConvertBuffer, NULL, 8);
694234518Sjkim
695234518Sjkim                /* Check for NULL or non-ascii character (ignore if so) */
696234518Sjkim
697234518Sjkim                if ((Digit == 0) || (Digit > ACPI_ASCII_MAX))
698234518Sjkim                {
699234518Sjkim                    AslCommonError (ASL_WARNING, ASL_MSG_INVALID_STRING,
700234518Sjkim                                    Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
701234518Sjkim                                    Gbl_CurrentLineOffset, Gbl_CurrentColumn,
702234518Sjkim                                    Gbl_Files[ASL_FILE_INPUT].Filename, NULL);
703234518Sjkim                }
704234518Sjkim                else
705234518Sjkim                {
706234518Sjkim                    *StringBuffer = (char) Digit;
707234518Sjkim                    StringBuffer++;
708234518Sjkim                    if (StringBuffer >= EndBuffer)
709234518Sjkim                    {
710234518Sjkim                        goto BufferOverflow;
711234518Sjkim                    }
712234518Sjkim                }
713234518Sjkim
714234518Sjkim                State = ASL_NORMAL_CHAR;
715234518Sjkim                goto DoCharacter;
716234518Sjkim                break;
717234518Sjkim            }
718234518Sjkim
719234518Sjkim            /* Append another digit of the constant */
720234518Sjkim
721234518Sjkim            ConvertBuffer[i] = StringChar;
722234518Sjkim            i++;
723234518Sjkim            continue;
724234518Sjkim
725234518Sjkim        case ASL_HEX_CONSTANT:
726234518Sjkim
727234518Sjkim            /* Up to two hex digits allowed */
728234518Sjkim
729234518Sjkim            if (!ACPI_IS_XDIGIT (StringChar) ||
730234518Sjkim                (i > 1))
731234518Sjkim            {
732234518Sjkim                /*
733241973Sjkim                 * Reached end of the constant. Convert the assembled ASCII
734234518Sjkim                 * string and resume processing of the next character
735234518Sjkim                 */
736234518Sjkim                ConvertBuffer[i] = 0;
737234518Sjkim                Digit = (UINT8) ACPI_STRTOUL (ConvertBuffer, NULL, 16);
738234518Sjkim
739234518Sjkim                /* Check for NULL or non-ascii character (ignore if so) */
740234518Sjkim
741234518Sjkim                if ((Digit == 0) || (Digit > ACPI_ASCII_MAX))
742234518Sjkim                {
743234518Sjkim                    AslCommonError (ASL_WARNING, ASL_MSG_INVALID_STRING,
744234518Sjkim                                    Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
745234518Sjkim                                    Gbl_CurrentLineOffset, Gbl_CurrentColumn,
746234518Sjkim                                    Gbl_Files[ASL_FILE_INPUT].Filename, NULL);
747234518Sjkim                }
748234518Sjkim                else
749234518Sjkim                {
750234518Sjkim                    *StringBuffer = (char) Digit;
751234518Sjkim                    StringBuffer++;
752234518Sjkim                    if (StringBuffer >= EndBuffer)
753234518Sjkim                    {
754234518Sjkim                        goto BufferOverflow;
755234518Sjkim                    }
756234518Sjkim                }
757234518Sjkim
758234518Sjkim                State = ASL_NORMAL_CHAR;
759234518Sjkim                goto DoCharacter;
760234518Sjkim                break;
761234518Sjkim            }
762234518Sjkim
763234518Sjkim            /* Append another digit of the constant */
764234518Sjkim
765234518Sjkim            ConvertBuffer[i] = StringChar;
766234518Sjkim            i++;
767234518Sjkim            continue;
768246849Sjkim
769246849Sjkim        default:
770250838Sjkim
771246849Sjkim            break;
772234518Sjkim        }
773234518Sjkim
774234518Sjkim        /* Save the finished character */
775234518Sjkim
776234518Sjkim        *StringBuffer = StringChar;
777234518Sjkim        StringBuffer++;
778234518Sjkim        if (StringBuffer >= EndBuffer)
779234518Sjkim        {
780234518Sjkim            goto BufferOverflow;
781234518Sjkim        }
782234518Sjkim    }
783234518Sjkim
784234518Sjkim    /*
785234518Sjkim     * Premature End-Of-File
786234518Sjkim     */
787234518Sjkim    AslCommonError (ASL_ERROR, ASL_MSG_EARLY_EOF,
788234518Sjkim                    Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
789234518Sjkim                    Gbl_CurrentLineOffset, Gbl_CurrentColumn,
790234518Sjkim                    Gbl_Files[ASL_FILE_INPUT].Filename, NULL);
791234518Sjkim    return (FALSE);
792234518Sjkim
793234518Sjkim
794234518SjkimCompletedString:
795234518Sjkim    /*
796234518Sjkim     * Null terminate the input string and copy string to a new buffer
797234518Sjkim     */
798234518Sjkim    *StringBuffer = 0;
799234518Sjkim
800234518Sjkim    CleanString = UtGetStringBuffer (strlen (MsgBuffer) + 1);
801234518Sjkim    if (!CleanString)
802234518Sjkim    {
803234518Sjkim        AslCommonError (ASL_ERROR, ASL_MSG_MEMORY_ALLOCATION,
804234518Sjkim                        Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
805234518Sjkim                        Gbl_CurrentLineOffset, Gbl_CurrentColumn,
806234518Sjkim                        Gbl_Files[ASL_FILE_INPUT].Filename, NULL);
807234518Sjkim        return (FALSE);
808234518Sjkim    }
809234518Sjkim
810234518Sjkim    ACPI_STRCPY (CleanString, MsgBuffer);
811234518Sjkim    AslCompilerlval.s = CleanString;
812234518Sjkim    return (TRUE);
813234518Sjkim
814234518Sjkim
815234518SjkimBufferOverflow:
816234518Sjkim
817234518Sjkim    /* Literal was too long */
818234518Sjkim
819234518Sjkim    AslCommonError (ASL_ERROR, ASL_MSG_STRING_LENGTH,
820234518Sjkim                    Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
821234518Sjkim                    Gbl_CurrentLineOffset, Gbl_CurrentColumn,
822234518Sjkim                    Gbl_Files[ASL_FILE_INPUT].Filename, "Max length 4096");
823234518Sjkim    return (FALSE);
824234518Sjkim}
825