1/******************************************************************************
2 *
3 * Module Name: asconvrt - Source conversion code
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2016, 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 "acpisrc.h"
45
46AS_BRACE_INFO               Gbl_BraceInfo[] =
47{
48    {" if",         3},
49    {" else if",    8},
50    {" else while", 11},
51    {" else",       5},
52    {" do ",        4},
53    {NULL,          0}
54};
55
56
57/* Local prototypes */
58
59static char *
60AsMatchValidToken (
61    char                    *Buffer,
62    char                    *Filename,
63    char                    TargetChar,
64    AS_SCAN_CALLBACK        Callback);
65
66static char *
67AsCheckBracesCallback (
68    char                    *Buffer,
69    char                    *Filename,
70    UINT32                  LineNumber);
71
72static UINT32
73AsCountLines (
74    char                    *Buffer,
75    char                    *Filename);
76
77
78/* Opening signature of the Intel legal header */
79
80char        *HeaderBegin = "/******************************************************************************\n *\n * 1. Copyright Notice";
81
82UINT32      NonAnsiCommentCount;
83
84
85/******************************************************************************
86 *
87 * FUNCTION:    AsCountNonAnsiComments
88 *
89 * DESCRIPTION: Count the number of "//" comments. This type of comment is
90 *              non-ANSI C.
91 *
92 * NOTE: July 2014: Allows // within quoted strings and within normal
93 *       comments. Eliminates extraneous warnings from this utility.
94 *
95 ******************************************************************************/
96
97void
98AsCountNonAnsiComments (
99    char                    *Buffer,
100    char                    *Filename)
101{
102
103    AsMatchValidToken (Buffer, Filename, 0, NULL);
104
105    /* Error if any slash-slash comments found */
106
107    if (NonAnsiCommentCount)
108    {
109        AsPrint ("Non-ANSI // Comments Found", NonAnsiCommentCount, Filename);
110        Gbl_NonAnsiComments += NonAnsiCommentCount;
111    }
112}
113
114
115/******************************************************************************
116 *
117 * FUNCTION:    AsCheckForBraces
118 *
119 * DESCRIPTION: Check for an open brace after each if/else/do (etc.)
120 *              statement
121 *
122 ******************************************************************************/
123
124void
125AsCheckForBraces (
126    char                    *Buffer,
127    char                    *Filename)
128{
129
130    AsMatchValidToken (Buffer, Filename, 0, AsCheckBracesCallback);
131}
132
133
134/******************************************************************************
135 *
136 * FUNCTION:    AsCheckBracesCallback
137 *
138 * DESCRIPTION: Check if/else/do statements. Ensure that braces
139 *              are always used.
140 *
141 * TBD: Currently, don't check while() statements. The problem is that there
142 * are two forms: do {} while (); and while () {}.
143 *
144 ******************************************************************************/
145
146static char *
147AsCheckBracesCallback (
148    char                    *Buffer,
149    char                    *Filename,
150    UINT32                  LineNumber)
151{
152    char                    *SubBuffer = Buffer;
153    char                    *NextBrace;
154    char                    *NextSemicolon;
155    AS_BRACE_INFO           *BraceInfo;
156
157
158    for (BraceInfo = Gbl_BraceInfo; BraceInfo->Operator; BraceInfo++)
159    {
160        if (!(strncmp (BraceInfo->Operator, SubBuffer, BraceInfo->Length)))
161        {
162            SubBuffer += (BraceInfo->Length - 1);
163
164            /* Find next brace and the next semicolon */
165
166            NextBrace = AsMatchValidToken (SubBuffer, Filename, '{', NULL);
167            NextSemicolon = AsMatchValidToken (SubBuffer, Filename, ';', NULL);
168
169            /* Next brace should appear before next semicolon */
170
171            if ((!NextBrace) ||
172               (NextSemicolon && (NextBrace > NextSemicolon)))
173            {
174                Gbl_MissingBraces++;
175
176                if (!Gbl_QuietMode)
177                {
178                    printf ("Missing braces for <%s>, line %u: %s\n",
179                        BraceInfo->Operator + 1, LineNumber, Filename);
180                }
181            }
182
183            return (SubBuffer);
184        }
185    }
186
187    /* No match, just return original buffer */
188
189    return (Buffer);
190}
191
192
193/******************************************************************************
194 *
195 * FUNCTION:    AsMatchValidToken
196 *
197 * DESCRIPTION: Find the next matching token in the input buffer.
198 *
199 ******************************************************************************/
200
201static char *
202AsMatchValidToken (
203    char                    *Buffer,
204    char                    *Filename,
205    char                    TargetChar,
206    AS_SCAN_CALLBACK        Callback)
207{
208    char                    *SubBuffer = Buffer;
209    char                    *StringStart;
210    UINT32                  TotalLines;
211
212
213    TotalLines = 1;
214    NonAnsiCommentCount = 0;
215
216    /* Scan from current position up to the end if necessary */
217
218    while (*SubBuffer)
219    {
220        /* Skip normal comments */
221
222        if ((*SubBuffer == '/') &&
223            (*(SubBuffer + 1) == '*'))
224        {
225            /* Must maintain line count */
226
227            SubBuffer += 2;
228            while (strncmp ("*/", SubBuffer, 2))
229            {
230                if (*SubBuffer == '\n')
231                {
232                    TotalLines++;
233                }
234                SubBuffer++;
235            }
236
237            SubBuffer += 2;
238            continue;
239        }
240
241        /* Skip single quoted chars */
242
243        if (*SubBuffer == '\'')
244        {
245            SubBuffer++;
246            if (!(*SubBuffer))
247            {
248                break;
249            }
250
251            if (*SubBuffer == '\\')
252            {
253                SubBuffer++;
254            }
255
256            SubBuffer++;
257            continue;
258        }
259
260        /* Skip quoted strings */
261
262        if (*SubBuffer == '"')
263        {
264            StringStart = SubBuffer;
265            SubBuffer++;
266            if (!(*SubBuffer))
267            {
268                break;
269            }
270
271            while (*SubBuffer != '"')
272            {
273                if ((*SubBuffer == '\n') ||
274                    (!(*SubBuffer)))
275                {
276                    AsPrint ("Unbalanced quoted string",1, Filename);
277                    printf ("    %.32s (line %u)\n", StringStart, TotalLines);
278                    break;
279                }
280
281                /* Handle escapes within the string */
282
283                if (*SubBuffer == '\\')
284                {
285                    SubBuffer++;
286                }
287
288                SubBuffer++;
289            }
290
291            SubBuffer++;
292            continue;
293        }
294
295        /* Now we can check for a slash-slash comment */
296
297        if ((*SubBuffer == '/') &&
298            (*(SubBuffer + 1) == '/'))
299        {
300            NonAnsiCommentCount++;
301
302            /* Skip to end-of-line */
303
304            while ((*SubBuffer != '\n') &&
305                (*SubBuffer))
306            {
307                SubBuffer++;
308            }
309
310            if (!(*SubBuffer))
311            {
312                break;
313            }
314
315            if (*SubBuffer == '\n')
316            {
317                TotalLines++;
318            }
319
320            SubBuffer++;
321            continue;
322        }
323
324        /* Finally, check for a newline */
325
326        if (*SubBuffer == '\n')
327        {
328            TotalLines++;
329            SubBuffer++;
330            continue;
331        }
332
333        /* Normal character, do the user actions */
334
335        if (Callback)
336        {
337            SubBuffer = Callback (SubBuffer, Filename, TotalLines);
338        }
339
340        if (TargetChar && (*SubBuffer == TargetChar))
341        {
342            return (SubBuffer);
343        }
344
345        SubBuffer++;
346    }
347
348    return (NULL);
349}
350
351
352/******************************************************************************
353 *
354 * FUNCTION:    AsRemoveExtraLines
355 *
356 * DESCRIPTION: Remove all extra lines at the start and end of the file.
357 *
358 ******************************************************************************/
359
360void
361AsRemoveExtraLines (
362    char                    *FileBuffer,
363    char                    *Filename)
364{
365    char                    *FileEnd;
366    int                     Length;
367
368
369    /* Remove any extra lines at the start of the file */
370
371    while (*FileBuffer == '\n')
372    {
373        printf ("Removing extra line at start of file: %s\n", Filename);
374        AsRemoveData (FileBuffer, FileBuffer + 1);
375    }
376
377    /* Remove any extra lines at the end of the file */
378
379    Length = strlen (FileBuffer);
380    FileEnd = FileBuffer + (Length - 2);
381
382    while (*FileEnd == '\n')
383    {
384        printf ("Removing extra line at end of file: %s\n", Filename);
385        AsRemoveData (FileEnd, FileEnd + 1);
386        FileEnd--;
387    }
388}
389
390
391/******************************************************************************
392 *
393 * FUNCTION:    AsRemoveSpacesAfterPeriod
394 *
395 * DESCRIPTION: Remove an extra space after a period.
396 *
397 ******************************************************************************/
398
399void
400AsRemoveSpacesAfterPeriod (
401    char                    *FileBuffer,
402    char                    *Filename)
403{
404    int                     ReplaceCount = 0;
405    char                    *Possible;
406
407
408    Possible = FileBuffer;
409    while (Possible)
410    {
411        Possible = strstr (Possible, ".  ");
412        if (Possible)
413        {
414            if ((*(Possible -1) == '.')  ||
415                (*(Possible -1) == '\"') ||
416                (*(Possible -1) == '\n'))
417            {
418                Possible += 3;
419                continue;
420            }
421
422            Possible = AsReplaceData (Possible, 3, ". ", 2);
423            ReplaceCount++;
424        }
425    }
426
427    if (ReplaceCount)
428    {
429        printf ("Removed %d extra blanks after a period: %s\n",
430            ReplaceCount, Filename);
431    }
432}
433
434
435/******************************************************************************
436 *
437 * FUNCTION:    AsMatchExactWord
438 *
439 * DESCRIPTION: Check previous and next characters for whitespace
440 *
441 ******************************************************************************/
442
443BOOLEAN
444AsMatchExactWord (
445    char                    *Word,
446    UINT32                  WordLength)
447{
448    char                    NextChar;
449    char                    PrevChar;
450
451
452    NextChar = Word[WordLength];
453    PrevChar = * (Word -1);
454
455    if (isalnum ((int) NextChar) ||
456        (NextChar == '_')  ||
457        isalnum ((int) PrevChar) ||
458        (PrevChar == '_'))
459    {
460        return (FALSE);
461    }
462
463    return (TRUE);
464}
465
466
467/******************************************************************************
468 *
469 * FUNCTION:    AsPrint
470 *
471 * DESCRIPTION: Common formatted print
472 *
473 ******************************************************************************/
474
475void
476AsPrint (
477    char                    *Message,
478    UINT32                  Count,
479    char                    *Filename)
480{
481
482    if (Gbl_QuietMode)
483    {
484        return;
485    }
486
487    printf ("-- %4u %28.28s : %s\n", Count, Message, Filename);
488}
489
490
491/******************************************************************************
492 *
493 * FUNCTION:    AsTrimLines
494 *
495 * DESCRIPTION: Remove extra blanks from the end of source lines. Does not
496 *              check for tabs.
497 *
498 ******************************************************************************/
499
500void
501AsTrimLines (
502    char                    *Buffer,
503    char                    *Filename)
504{
505    char                    *SubBuffer = Buffer;
506    char                    *StartWhiteSpace = NULL;
507    UINT32                  SpaceCount = 0;
508
509
510    while (*SubBuffer)
511    {
512        while (*SubBuffer != '\n')
513        {
514            if (!*SubBuffer)
515            {
516                goto Exit;
517            }
518
519            if (*SubBuffer == ' ')
520            {
521                if (!StartWhiteSpace)
522                {
523                    StartWhiteSpace = SubBuffer;
524                }
525            }
526            else
527            {
528                StartWhiteSpace = NULL;
529            }
530
531            SubBuffer++;
532        }
533
534        if (StartWhiteSpace)
535        {
536            SpaceCount += (SubBuffer - StartWhiteSpace);
537
538            /* Remove the spaces */
539
540            SubBuffer = AsRemoveData (StartWhiteSpace, SubBuffer);
541            StartWhiteSpace = NULL;
542        }
543
544        SubBuffer++;
545    }
546
547
548Exit:
549    if (SpaceCount)
550    {
551        Gbl_MadeChanges = TRUE;
552        AsPrint ("Extraneous spaces removed", SpaceCount, Filename);
553    }
554}
555
556
557/******************************************************************************
558 *
559 * FUNCTION:    AsTrimWhitespace
560 *
561 * DESCRIPTION: Remove "excess" blank lines - any more than 2 blank lines.
562 *              this can happen during the translation when lines are removed.
563 *
564 ******************************************************************************/
565
566void
567AsTrimWhitespace (
568    char                    *Buffer)
569{
570    char                    *SubBuffer;
571    int                     ReplaceCount = 1;
572
573
574    while (ReplaceCount)
575    {
576        ReplaceCount = AsReplaceString ("\n\n\n\n", "\n\n\n",
577            REPLACE_SUBSTRINGS, Buffer);
578    }
579
580    /*
581     * Check for exactly one blank line after the copyright header
582     */
583
584    /* Find the header */
585
586    SubBuffer = strstr (Buffer, HeaderBegin);
587    if (!SubBuffer)
588    {
589        return;
590    }
591
592    /* Find the end of the header */
593
594    SubBuffer = strstr (SubBuffer, "*/");
595    SubBuffer = AsSkipPastChar (SubBuffer, '\n');
596
597    /* Replace a double blank line with a single */
598
599    if (!strncmp (SubBuffer, "\n\n", 2))
600    {
601        AsReplaceData (SubBuffer, 2, "\n", 1);
602        AcpiOsPrintf ("Found multiple blank lines after copyright\n");
603    }
604
605    /* If no blank line after header, insert one */
606
607    else if (*SubBuffer != '\n')
608    {
609        AsInsertData (SubBuffer, "\n", 1);
610        AcpiOsPrintf ("Inserted blank line after copyright\n");
611    }
612}
613
614
615/******************************************************************************
616 *
617 * FUNCTION:    AsReplaceHeader
618 *
619 * DESCRIPTION: Replace the default Intel legal header with a new header
620 *
621 ******************************************************************************/
622
623void
624AsReplaceHeader (
625    char                    *Buffer,
626    char                    *NewHeader)
627{
628    char                    *SubBuffer;
629    char                    *TokenEnd;
630
631
632    /* Find the original header */
633
634    SubBuffer = strstr (Buffer, HeaderBegin);
635    if (!SubBuffer)
636    {
637        return;
638    }
639
640    /* Find the end of the original header */
641
642    TokenEnd = strstr (SubBuffer, "*/");
643    TokenEnd = AsSkipPastChar (TokenEnd, '\n');
644
645    /* Delete old header, insert new one */
646
647    AsReplaceData (SubBuffer, TokenEnd - SubBuffer,
648        NewHeader, strlen (NewHeader));
649}
650
651
652/******************************************************************************
653 *
654 * FUNCTION:    AsReplaceString
655 *
656 * DESCRIPTION: Replace all instances of a target string with a replacement
657 *              string. Returns count of the strings replaced.
658 *
659 ******************************************************************************/
660
661int
662AsReplaceString (
663    char                    *Target,
664    char                    *Replacement,
665    UINT8                   Type,
666    char                    *Buffer)
667{
668    char                    *SubString1;
669    char                    *SubString2;
670    char                    *SubBuffer;
671    int                     TargetLength;
672    int                     ReplacementLength;
673    int                     ReplaceCount = 0;
674
675
676    TargetLength = strlen (Target);
677    ReplacementLength = strlen (Replacement);
678
679    SubBuffer = Buffer;
680    SubString1 = Buffer;
681
682    while (SubString1)
683    {
684        /* Find the target string */
685
686        SubString1 = strstr (SubBuffer, Target);
687        if (!SubString1)
688        {
689            return (ReplaceCount);
690        }
691
692        /*
693         * Check for translation escape string -- means to ignore
694         * blocks of code while replacing
695         */
696        if (Gbl_IgnoreTranslationEscapes)
697        {
698            SubString2 = NULL;
699        }
700        else
701        {
702            SubString2 = strstr (SubBuffer, AS_START_IGNORE);
703        }
704
705        if ((SubString2) &&
706            (SubString2 < SubString1))
707        {
708            /* Find end of the escape block starting at "Substring2" */
709
710            SubString2 = strstr (SubString2, AS_STOP_IGNORE);
711            if (!SubString2)
712            {
713                /* Didn't find terminator */
714
715                return (ReplaceCount);
716            }
717
718            /* Move buffer to end of escape block and continue */
719
720            SubBuffer = SubString2;
721        }
722
723        /* Do the actual replace if the target was found */
724
725        else
726        {
727            if ((Type & REPLACE_MASK) == REPLACE_WHOLE_WORD)
728            {
729                if (!AsMatchExactWord (SubString1, TargetLength))
730                {
731                    SubBuffer = SubString1 + 1;
732                    continue;
733                }
734            }
735
736            SubBuffer = AsReplaceData (SubString1, TargetLength,
737                Replacement, ReplacementLength);
738
739            if ((Type & EXTRA_INDENT_C) &&
740                (!Gbl_StructDefs))
741            {
742                SubBuffer = AsInsertData (SubBuffer, "        ", 8);
743            }
744
745            ReplaceCount++;
746        }
747    }
748
749    return (ReplaceCount);
750}
751
752
753/******************************************************************************
754 *
755 * FUNCTION:    AsConvertToLineFeeds
756 *
757 * DESCRIPTION: Convert all CR/LF pairs to LF only.
758 *
759 ******************************************************************************/
760
761void
762AsConvertToLineFeeds (
763    char                    *Buffer)
764{
765    char                    *SubString;
766    char                    *SubBuffer;
767
768
769    SubBuffer = Buffer;
770    SubString = Buffer;
771
772    while (SubString)
773    {
774        /* Find the target string */
775
776        SubString = strstr (SubBuffer, "\r\n");
777        if (!SubString)
778        {
779            return;
780        }
781
782        SubBuffer = AsReplaceData (SubString, 1, NULL, 0);
783    }
784}
785
786
787/******************************************************************************
788 *
789 * FUNCTION:    AsInsertCarriageReturns
790 *
791 * DESCRIPTION: Convert lone LFs to CR/LF pairs.
792 *
793 ******************************************************************************/
794
795void
796AsInsertCarriageReturns (
797    char                    *Buffer)
798{
799    char                    *SubString;
800    char                    *SubBuffer;
801
802
803    SubBuffer = Buffer;
804    SubString = Buffer;
805
806    while (SubString)
807    {
808        /* Find the target string */
809
810        SubString = strstr (SubBuffer, "\n");
811        if (!SubString)
812        {
813            return;
814        }
815
816        SubBuffer = AsInsertData (SubString, "\r", 1);
817        SubBuffer += 1;
818    }
819}
820
821
822/******************************************************************************
823 *
824 * FUNCTION:    AsBracesOnSameLine
825 *
826 * DESCRIPTION: Move opening braces up to the same line as an if, for, else,
827 *              or while statement (leave function opening brace on separate
828 *              line).
829 *
830 ******************************************************************************/
831
832void
833AsBracesOnSameLine (
834    char                    *Buffer)
835{
836    char                    *SubBuffer = Buffer;
837    char                    *Beginning;
838    char                    *StartOfThisLine;
839    char                    *Next;
840    BOOLEAN                 BlockBegin = TRUE;
841
842
843    while (*SubBuffer)
844    {
845        /* Ignore comments */
846
847        if ((SubBuffer[0] == '/') &&
848            (SubBuffer[1] == '*'))
849        {
850            SubBuffer = strstr (SubBuffer, "*/");
851            if (!SubBuffer)
852            {
853                return;
854            }
855
856            SubBuffer += 2;
857            continue;
858        }
859
860        /* Ignore quoted strings */
861
862        if (*SubBuffer == '\"')
863        {
864            SubBuffer++;
865            SubBuffer = AsSkipPastChar (SubBuffer, '\"');
866            if (!SubBuffer)
867            {
868                return;
869            }
870        }
871
872        if (!strncmp ("\n}", SubBuffer, 2))
873        {
874            /*
875             * A newline followed by a closing brace closes a function
876             * or struct or initializer block
877             */
878            BlockBegin = TRUE;
879        }
880
881        /*
882         * Move every standalone brace up to the previous line
883         * Check for digit will ignore initializer lists surrounded by braces.
884         * This will work until we we need more complex detection.
885         */
886        if ((*SubBuffer == '{') && !isdigit ((int) SubBuffer[1]))
887        {
888            if (BlockBegin)
889            {
890                BlockBegin = FALSE;
891            }
892            else
893            {
894                /*
895                 * Backup to previous non-whitespace
896                 */
897                Beginning = SubBuffer - 1;
898                while ((*Beginning == ' ')   ||
899                       (*Beginning == '\n'))
900                {
901                    Beginning--;
902                }
903
904                StartOfThisLine = Beginning;
905                while (*StartOfThisLine != '\n')
906                {
907                    StartOfThisLine--;
908                }
909
910                /*
911                 * Move the brace up to the previous line, UNLESS:
912                 *
913                 * 1) There is a conditional compile on the line (starts with '#')
914                 * 2) Previous line ends with an '=' (Start of initializer block)
915                 * 3) Previous line ends with a comma (part of an init list)
916                 * 4) Previous line ends with a backslash (part of a macro)
917                 */
918                if ((StartOfThisLine[1] != '#') &&
919                    (*Beginning != '\\') &&
920                    (*Beginning != '/') &&
921                    (*Beginning != '{') &&
922                    (*Beginning != '=') &&
923                    (*Beginning != ','))
924                {
925                    Beginning++;
926                    SubBuffer++;
927
928                    Gbl_MadeChanges = TRUE;
929
930#ifdef ADD_EXTRA_WHITESPACE
931                    AsReplaceData (Beginning, SubBuffer - Beginning, " {\n", 3);
932#else
933                    /* Find non-whitespace start of next line */
934
935                    Next = SubBuffer + 1;
936                    while ((*Next == ' ')   ||
937                           (*Next == '\t'))
938                    {
939                        Next++;
940                    }
941
942                    /* Find non-whitespace start of this line */
943
944                    StartOfThisLine++;
945                    while ((*StartOfThisLine == ' ')   ||
946                           (*StartOfThisLine == '\t'))
947                    {
948                        StartOfThisLine++;
949                    }
950
951                    /*
952                     * Must be a single-line comment to need more whitespace
953                     * Even then, we don't need more if the previous statement
954                     * is an "else".
955                     */
956                    if ((Next[0] == '/')  &&
957                        (Next[1] == '*')  &&
958                        (Next[2] != '\n') &&
959
960                        (!strncmp (StartOfThisLine, "else if", 7)     ||
961                         !strncmp (StartOfThisLine, "else while", 10) ||
962                          strncmp (StartOfThisLine, "else", 4)))
963                    {
964                        AsReplaceData (Beginning, SubBuffer - Beginning, " {\n", 3);
965                    }
966                    else
967                    {
968                        AsReplaceData (Beginning, SubBuffer - Beginning, " {", 2);
969                    }
970#endif
971                }
972            }
973        }
974
975        SubBuffer++;
976    }
977}
978
979
980/******************************************************************************
981 *
982 * FUNCTION:    AsTabify4
983 *
984 * DESCRIPTION: Convert the text to tabbed text. Alignment of text is
985 *              preserved.
986 *
987 ******************************************************************************/
988
989void
990AsTabify4 (
991    char                    *Buffer)
992{
993    char                    *SubBuffer = Buffer;
994    char                    *NewSubBuffer;
995    UINT32                  SpaceCount = 0;
996    UINT32                  Column = 0;
997
998
999    while (*SubBuffer)
1000    {
1001        if (*SubBuffer == '\n')
1002        {
1003            Column = 0;
1004        }
1005        else
1006        {
1007            Column++;
1008        }
1009
1010        /* Ignore comments */
1011
1012        if ((SubBuffer[0] == '/') &&
1013            (SubBuffer[1] == '*'))
1014        {
1015            SubBuffer = strstr (SubBuffer, "*/");
1016            if (!SubBuffer)
1017            {
1018                return;
1019            }
1020
1021            SubBuffer += 2;
1022            continue;
1023        }
1024
1025        /* Ignore quoted strings */
1026
1027        if (*SubBuffer == '\"')
1028        {
1029            SubBuffer++;
1030            SubBuffer = AsSkipPastChar (SubBuffer, '\"');
1031            if (!SubBuffer)
1032            {
1033                return;
1034            }
1035            SpaceCount = 0;
1036        }
1037
1038        if (*SubBuffer == ' ')
1039        {
1040            SpaceCount++;
1041
1042            if (SpaceCount >= 4)
1043            {
1044                SpaceCount = 0;
1045
1046                NewSubBuffer = (SubBuffer + 1) - 4;
1047                *NewSubBuffer = '\t';
1048                NewSubBuffer++;
1049
1050                /* Remove the spaces */
1051
1052                SubBuffer = AsRemoveData (NewSubBuffer, SubBuffer + 1);
1053            }
1054
1055            if ((Column % 4) == 0)
1056            {
1057                SpaceCount = 0;
1058            }
1059        }
1060        else
1061        {
1062            SpaceCount = 0;
1063        }
1064
1065        SubBuffer++;
1066    }
1067}
1068
1069
1070/******************************************************************************
1071 *
1072 * FUNCTION:    AsTabify8
1073 *
1074 * DESCRIPTION: Convert the text to tabbed text. Alignment of text is
1075 *              preserved.
1076 *
1077 ******************************************************************************/
1078
1079void
1080AsTabify8 (
1081    char                    *Buffer)
1082{
1083    char                    *SubBuffer = Buffer;
1084    char                    *NewSubBuffer;
1085    char                    *CommentEnd = NULL;
1086    UINT32                  SpaceCount = 0;
1087    UINT32                  Column = 0;
1088    UINT32                  TabCount = 0;
1089    UINT32                  LastLineTabCount = 0;
1090    UINT32                  LastLineColumnStart = 0;
1091    UINT32                  ThisColumnStart = 0;
1092    UINT32                  ThisTabCount =  0;
1093    char                    *FirstNonBlank = NULL;
1094
1095
1096    while (*SubBuffer)
1097    {
1098        if (*SubBuffer == '\n')
1099        {
1100            /* This is a standalone blank line */
1101
1102            FirstNonBlank = NULL;
1103            Column = 0;
1104            SpaceCount = 0;
1105            TabCount = 0;
1106            SubBuffer++;
1107            continue;
1108        }
1109
1110        if (!FirstNonBlank)
1111        {
1112            /* Find the first non-blank character on this line */
1113
1114            FirstNonBlank = SubBuffer;
1115            while (*FirstNonBlank == ' ')
1116            {
1117                FirstNonBlank++;
1118            }
1119
1120            /*
1121             * This mechanism limits the difference in tab counts from
1122             * line to line. It helps avoid the situation where a second
1123             * continuation line (which was indented correctly for tabs=4) would
1124             * get indented off the screen if we just blindly converted to tabs.
1125             */
1126            ThisColumnStart = FirstNonBlank - SubBuffer;
1127
1128            if (LastLineTabCount == 0)
1129            {
1130                ThisTabCount = 0;
1131            }
1132            else if (ThisColumnStart == LastLineColumnStart)
1133            {
1134                ThisTabCount = LastLineTabCount -1;
1135            }
1136            else
1137            {
1138                ThisTabCount = LastLineTabCount + 1;
1139            }
1140        }
1141
1142        Column++;
1143
1144        /* Check if we are in a comment */
1145
1146        if ((SubBuffer[0] == '*') &&
1147            (SubBuffer[1] == '/'))
1148        {
1149            SpaceCount = 0;
1150            SubBuffer += 2;
1151
1152            if (*SubBuffer == '\n')
1153            {
1154                if (TabCount > 0)
1155                {
1156                    LastLineTabCount = TabCount;
1157                    TabCount = 0;
1158                }
1159
1160                FirstNonBlank = NULL;
1161                LastLineColumnStart = ThisColumnStart;
1162                SubBuffer++;
1163            }
1164
1165            continue;
1166        }
1167
1168        /* Check for comment open */
1169
1170        if ((SubBuffer[0] == '/') &&
1171            (SubBuffer[1] == '*'))
1172        {
1173            /* Find the end of the comment, it must exist */
1174
1175            CommentEnd = strstr (SubBuffer, "*/");
1176            if (!CommentEnd)
1177            {
1178                return;
1179            }
1180
1181            /* Toss the rest of this line or single-line comment */
1182
1183            while ((SubBuffer < CommentEnd) &&
1184                   (*SubBuffer != '\n'))
1185            {
1186                SubBuffer++;
1187            }
1188
1189            if (*SubBuffer == '\n')
1190            {
1191                if (TabCount > 0)
1192                {
1193                    LastLineTabCount = TabCount;
1194                    TabCount = 0;
1195                }
1196
1197                FirstNonBlank = NULL;
1198                LastLineColumnStart = ThisColumnStart;
1199            }
1200
1201            SpaceCount = 0;
1202            continue;
1203        }
1204
1205        /* Ignore quoted strings */
1206
1207        if ((!CommentEnd) && (*SubBuffer == '\"'))
1208        {
1209            SubBuffer++;
1210            SubBuffer = AsSkipPastChar (SubBuffer, '\"');
1211            if (!SubBuffer)
1212            {
1213                return;
1214            }
1215
1216            SpaceCount = 0;
1217        }
1218
1219        if (*SubBuffer != ' ')
1220        {
1221            /* Not a space, skip to end of line */
1222
1223            SubBuffer = AsSkipUntilChar (SubBuffer, '\n');
1224            if (!SubBuffer)
1225            {
1226                return;
1227            }
1228            if (TabCount > 0)
1229            {
1230                LastLineTabCount = TabCount;
1231                TabCount = 0;
1232            }
1233
1234            FirstNonBlank = NULL;
1235            LastLineColumnStart = ThisColumnStart;
1236            Column = 0;
1237            SpaceCount = 0;
1238        }
1239        else
1240        {
1241            /* Another space */
1242
1243            SpaceCount++;
1244
1245            if (SpaceCount >= 4)
1246            {
1247                /* Replace this group of spaces with a tab character */
1248
1249                SpaceCount = 0;
1250
1251                NewSubBuffer = SubBuffer - 3;
1252
1253                if (TabCount <= ThisTabCount ? (ThisTabCount +1) : 0)
1254                {
1255                    *NewSubBuffer = '\t';
1256                    NewSubBuffer++;
1257                    SubBuffer++;
1258                    TabCount++;
1259                }
1260
1261                /* Remove the spaces */
1262
1263                SubBuffer = AsRemoveData (NewSubBuffer, SubBuffer);
1264                continue;
1265            }
1266        }
1267
1268        SubBuffer++;
1269    }
1270}
1271
1272
1273/******************************************************************************
1274 *
1275 * FUNCTION:    AsCountLines
1276 *
1277 * DESCRIPTION: Count the number of lines in the input buffer. Also count
1278 *              the number of long lines (lines longer than 80 chars).
1279 *
1280 ******************************************************************************/
1281
1282static UINT32
1283AsCountLines (
1284    char                    *Buffer,
1285    char                    *Filename)
1286{
1287    char                    *SubBuffer = Buffer;
1288    char                    *EndOfLine;
1289    UINT32                  LineCount = 0;
1290    UINT32                  LongLineCount = 0;
1291
1292
1293    while (*SubBuffer)
1294    {
1295        EndOfLine = AsSkipUntilChar (SubBuffer, '\n');
1296        if (!EndOfLine)
1297        {
1298            Gbl_TotalLines += LineCount;
1299            return (LineCount);
1300        }
1301
1302        if ((EndOfLine - SubBuffer) > 80)
1303        {
1304            LongLineCount++;
1305            VERBOSE_PRINT (("long: %.80s\n", SubBuffer));
1306        }
1307
1308        LineCount++;
1309        SubBuffer = EndOfLine + 1;
1310    }
1311
1312    if (LongLineCount)
1313    {
1314        VERBOSE_PRINT (("%u Lines longer than 80 found in %s\n",
1315            LongLineCount, Filename));
1316
1317        Gbl_LongLines += LongLineCount;
1318    }
1319
1320    Gbl_TotalLines += LineCount;
1321    return (LineCount);
1322}
1323
1324
1325/******************************************************************************
1326 *
1327 * FUNCTION:    AsCountTabs
1328 *
1329 * DESCRIPTION: Simply count the number of tabs in the input file buffer
1330 *
1331 ******************************************************************************/
1332
1333void
1334AsCountTabs (
1335    char                    *Buffer,
1336    char                    *Filename)
1337{
1338    UINT32                  i;
1339    UINT32                  TabCount = 0;
1340
1341
1342    for (i = 0; Buffer[i]; i++)
1343    {
1344        if (Buffer[i] == '\t')
1345        {
1346            TabCount++;
1347        }
1348    }
1349
1350    if (TabCount)
1351    {
1352        AsPrint ("Tabs found", TabCount, Filename);
1353        Gbl_Tabs += TabCount;
1354    }
1355
1356    AsCountLines (Buffer, Filename);
1357}
1358
1359
1360/******************************************************************************
1361 *
1362 * FUNCTION:    AsCountSourceLines
1363 *
1364 * DESCRIPTION: Count the number of C source lines. Defined by 1) not a
1365 *              comment, and 2) not a blank line.
1366 *
1367 ******************************************************************************/
1368
1369void
1370AsCountSourceLines (
1371    char                    *Buffer,
1372    char                    *Filename)
1373{
1374    char                    *SubBuffer = Buffer;
1375    UINT32                  LineCount = 0;
1376    UINT32                  WhiteCount = 0;
1377    UINT32                  CommentCount = 0;
1378
1379
1380    while (*SubBuffer)
1381    {
1382        /* Detect comments (// comments are not used, non-ansii) */
1383
1384        if ((SubBuffer[0] == '/') &&
1385            (SubBuffer[1] == '*'))
1386        {
1387            SubBuffer += 2;
1388
1389            /* First line of multi-line comment is often just whitespace */
1390
1391            if (SubBuffer[0] == '\n')
1392            {
1393                WhiteCount++;
1394                SubBuffer++;
1395            }
1396            else
1397            {
1398                CommentCount++;
1399            }
1400
1401            /* Find end of comment */
1402
1403            while (SubBuffer[0] && SubBuffer[1] &&
1404                !(((SubBuffer[0] == '*') &&
1405                    (SubBuffer[1] == '/'))))
1406            {
1407                if (SubBuffer[0] == '\n')
1408                {
1409                    CommentCount++;
1410                }
1411
1412                SubBuffer++;
1413            }
1414        }
1415
1416        /* A linefeed followed by a non-linefeed is a valid source line */
1417
1418        else if ((SubBuffer[0] == '\n') &&
1419                 (SubBuffer[1] != '\n'))
1420        {
1421            LineCount++;
1422        }
1423
1424        /* Two back-to-back linefeeds indicate a whitespace line */
1425
1426        else if ((SubBuffer[0] == '\n') &&
1427                 (SubBuffer[1] == '\n'))
1428        {
1429            WhiteCount++;
1430        }
1431
1432        SubBuffer++;
1433    }
1434
1435    /* Adjust comment count for legal header */
1436
1437    if (Gbl_HeaderSize < CommentCount)
1438    {
1439        CommentCount -= Gbl_HeaderSize;
1440        Gbl_HeaderLines += Gbl_HeaderSize;
1441    }
1442
1443    Gbl_SourceLines += LineCount;
1444    Gbl_WhiteLines += WhiteCount;
1445    Gbl_CommentLines += CommentCount;
1446
1447    VERBOSE_PRINT (("%u Comment %u White %u Code %u Lines in %s\n",
1448        CommentCount, WhiteCount, LineCount,
1449        LineCount + WhiteCount + CommentCount, Filename));
1450}
1451
1452
1453/******************************************************************************
1454 *
1455 * FUNCTION:    AsInsertPrefix
1456 *
1457 * DESCRIPTION: Insert struct or union prefixes
1458 *
1459 ******************************************************************************/
1460
1461void
1462AsInsertPrefix (
1463    char                    *Buffer,
1464    char                    *Keyword,
1465    UINT8                   Type)
1466{
1467    char                    *SubString;
1468    char                    *SubBuffer;
1469    char                    *EndKeyword;
1470    int                     InsertLength;
1471    char                    *InsertString;
1472    int                     TrailingSpaces;
1473    char                    LowerKeyword[128];
1474    int                     KeywordLength;
1475
1476
1477    switch (Type)
1478    {
1479    case SRC_TYPE_STRUCT:
1480
1481        InsertString = "struct ";
1482        break;
1483
1484    case SRC_TYPE_UNION:
1485
1486        InsertString = "union ";
1487        break;
1488
1489    default:
1490
1491        return;
1492    }
1493
1494    strcpy (LowerKeyword, Keyword);
1495    AcpiUtStrlwr (LowerKeyword);
1496
1497    SubBuffer = Buffer;
1498    SubString = Buffer;
1499    InsertLength = strlen (InsertString);
1500    KeywordLength = strlen (Keyword);
1501
1502
1503    while (SubString)
1504    {
1505        /* Find an instance of the keyword */
1506
1507        SubString = strstr (SubBuffer, LowerKeyword);
1508        if (!SubString)
1509        {
1510            return;
1511        }
1512
1513        SubBuffer = SubString;
1514
1515        /* Must be standalone word, not a substring */
1516
1517        if (AsMatchExactWord (SubString, KeywordLength))
1518        {
1519            /* Make sure the keyword isn't already prefixed with the insert */
1520
1521            if (!strncmp (SubString - InsertLength, InsertString, InsertLength))
1522            {
1523                /* Add spaces if not already at the end-of-line */
1524
1525                if (*(SubBuffer + KeywordLength) != '\n')
1526                {
1527                    /* Already present, add spaces after to align structure members */
1528
1529#if 0
1530/* ONLY FOR C FILES */
1531                    AsInsertData (SubBuffer + KeywordLength, "        ", 8);
1532#endif
1533                }
1534                goto Next;
1535            }
1536
1537            /* Make sure the keyword isn't at the end of a struct/union */
1538            /* Note: This code depends on a single space after the brace */
1539
1540            if (*(SubString - 2) == '}')
1541            {
1542                goto Next;
1543            }
1544
1545            /* Prefix the keyword with the insert string */
1546
1547            Gbl_MadeChanges = TRUE;
1548
1549            /* Is there room for insertion */
1550
1551            EndKeyword = SubString + strlen (LowerKeyword);
1552
1553            TrailingSpaces = 0;
1554            while (EndKeyword[TrailingSpaces] == ' ')
1555            {
1556                TrailingSpaces++;
1557            }
1558
1559            /*
1560             * Use "if (TrailingSpaces > 1)" if we want to ignore casts
1561             */
1562            SubBuffer = SubString + InsertLength;
1563
1564            if (TrailingSpaces > InsertLength)
1565            {
1566                /* Insert the keyword */
1567
1568                memmove (SubBuffer, SubString, KeywordLength);
1569
1570                /* Insert the keyword */
1571
1572                memmove (SubString, InsertString, InsertLength);
1573            }
1574            else
1575            {
1576                AsInsertData (SubString, InsertString, InsertLength);
1577            }
1578        }
1579
1580Next:
1581        SubBuffer += KeywordLength;
1582    }
1583}
1584
1585#ifdef ACPI_FUTURE_IMPLEMENTATION
1586/******************************************************************************
1587 *
1588 * FUNCTION:    AsTrimComments
1589 *
1590 * DESCRIPTION: Finds 3-line comments with only a single line of text
1591 *
1592 ******************************************************************************/
1593
1594void
1595AsTrimComments (
1596    char                    *Buffer,
1597    char                    *Filename)
1598{
1599    char                    *SubBuffer = Buffer;
1600    char                    *Ptr1;
1601    char                    *Ptr2;
1602    UINT32                  LineCount;
1603    UINT32                  ShortCommentCount = 0;
1604
1605
1606    while (1)
1607    {
1608        /* Find comment open, within procedure level */
1609
1610        SubBuffer = strstr (SubBuffer, "    /*");
1611        if (!SubBuffer)
1612        {
1613            goto Exit;
1614        }
1615
1616        /* Find comment terminator */
1617
1618        Ptr1 = strstr (SubBuffer, "*/");
1619        if (!Ptr1)
1620        {
1621            goto Exit;
1622        }
1623
1624        /* Find next EOL (from original buffer) */
1625
1626        Ptr2 = strstr (SubBuffer, "\n");
1627        if (!Ptr2)
1628        {
1629            goto Exit;
1630        }
1631
1632        /* Ignore one-line comments */
1633
1634        if (Ptr1 < Ptr2)
1635        {
1636            /* Normal comment, ignore and continue; */
1637
1638            SubBuffer = Ptr2;
1639            continue;
1640        }
1641
1642        /* Examine multi-line comment */
1643
1644        LineCount = 1;
1645        while (Ptr1 > Ptr2)
1646        {
1647            /* Find next EOL */
1648
1649            Ptr2++;
1650            Ptr2 = strstr (Ptr2, "\n");
1651            if (!Ptr2)
1652            {
1653                goto Exit;
1654            }
1655
1656            LineCount++;
1657        }
1658
1659        SubBuffer = Ptr1;
1660
1661        if (LineCount <= 3)
1662        {
1663            ShortCommentCount++;
1664        }
1665    }
1666
1667
1668Exit:
1669
1670    if (ShortCommentCount)
1671    {
1672        AsPrint ("Short Comments found", ShortCommentCount, Filename);
1673    }
1674}
1675#endif
1676
1677#ifdef ACPI_UNUSED_FUNCTIONS
1678/******************************************************************************
1679 *
1680 * FUNCTION:    AsCheckAndSkipLiterals
1681 *
1682 * DESCRIPTION: Generic routine to skip comments and quoted string literals.
1683 *              Keeps a line count.
1684 *
1685 ******************************************************************************/
1686
1687static char *
1688AsCheckAndSkipLiterals (
1689    char                    *Buffer,
1690    UINT32                  *TotalLines);
1691
1692
1693static char *
1694AsCheckAndSkipLiterals (
1695    char                    *Buffer,
1696    UINT32                  *TotalLines)
1697{
1698    UINT32                  NewLines = 0;
1699    char                    *SubBuffer = Buffer;
1700    char                    *LiteralEnd;
1701
1702
1703    /* Ignore comments */
1704
1705    if ((SubBuffer[0] == '/') &&
1706        (SubBuffer[1] == '*'))
1707    {
1708        LiteralEnd = strstr (SubBuffer, "*/");
1709        SubBuffer += 2;     /* Get past comment opening */
1710
1711        if (!LiteralEnd)
1712        {
1713            return (SubBuffer);
1714        }
1715
1716        while (SubBuffer < LiteralEnd)
1717        {
1718            if (*SubBuffer == '\n')
1719            {
1720                NewLines++;
1721            }
1722
1723            SubBuffer++;
1724        }
1725
1726        SubBuffer += 2;     /* Get past comment close */
1727    }
1728
1729    /* Ignore quoted strings */
1730
1731    else if (*SubBuffer == '\"')
1732    {
1733        SubBuffer++;
1734        LiteralEnd = AsSkipPastChar (SubBuffer, '\"');
1735        if (!LiteralEnd)
1736        {
1737            return (SubBuffer);
1738        }
1739    }
1740
1741    if (TotalLines)
1742    {
1743        (*TotalLines) += NewLines;
1744    }
1745    return (SubBuffer);
1746}
1747#endif
1748