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