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