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