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 
46 AS_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 
59 static char *
60 AsMatchValidToken (
61     char                    *Buffer,
62     char                    *Filename,
63     char                    TargetChar,
64     AS_SCAN_CALLBACK        Callback);
65 
66 static char *
67 AsCheckBracesCallback (
68     char                    *Buffer,
69     char                    *Filename,
70     UINT32                  LineNumber);
71 
72 static UINT32
73 AsCountLines (
74     char                    *Buffer,
75     char                    *Filename);
76 
77 
78 /* Opening signature of the Intel legal header */
79 
80 char        *HeaderBegin = "/******************************************************************************\n *\n * 1. Copyright Notice";
81 
82 UINT32      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 
97 void
98 AsCountNonAnsiComments (
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 
124 void
125 AsCheckForBraces (
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 
146 static char *
147 AsCheckBracesCallback (
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 
201 static char *
202 AsMatchValidToken (
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 
360 void
361 AsRemoveExtraLines (
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 
399 void
400 AsRemoveSpacesAfterPeriod (
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 
443 BOOLEAN
444 AsMatchExactWord (
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 
475 void
476 AsPrint (
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 
500 void
501 AsTrimLines (
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 
548 Exit:
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 
566 void
567 AsTrimWhitespace (
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 
623 void
624 AsReplaceHeader (
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 
661 int
662 AsReplaceString (
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 
761 void
762 AsConvertToLineFeeds (
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 
795 void
796 AsInsertCarriageReturns (
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 
832 void
833 AsBracesOnSameLine (
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 
989 void
990 AsTabify4 (
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 
1079 void
1080 AsTabify8 (
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 
1282 static UINT32
1283 AsCountLines (
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 
1333 void
1334 AsCountTabs (
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 
1369 void
1370 AsCountSourceLines (
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 
1461 void
1462 AsInsertPrefix (
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 
1580 Next:
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 
1594 void
1595 AsTrimComments (
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 
1668 Exit:
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 
1687 static char *
1688 AsCheckAndSkipLiterals (
1689     char                    *Buffer,
1690     UINT32                  *TotalLines);
1691 
1692 
1693 static char *
1694 AsCheckAndSkipLiterals (
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