1 /******************************************************************************
2  *
3  * Module Name: asremove - Source conversion - removal functions
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "acpisrc.h"
45 
46 /* Local prototypes */
47 
48 void
49 AsRemoveStatement (
50     char                    *Buffer,
51     char                    *Keyword,
52     UINT32                  Type);
53 
54 
55 /******************************************************************************
56  *
57  * FUNCTION:    AsRemoveStatement
58  *
59  * DESCRIPTION: Remove all statements that contain the given keyword.
60  *              Limitations:  Removes text from the start of the line that
61  *              contains the keyword to the next semicolon. Currently
62  *              doesn't ignore comments.
63  *
64  ******************************************************************************/
65 
66 void
67 AsRemoveStatement (
68     char                    *Buffer,
69     char                    *Keyword,
70     UINT32                  Type)
71 {
72     char                    *SubString;
73     char                    *SubBuffer;
74     int                     KeywordLength;
75 
76 
77     KeywordLength = strlen (Keyword);
78     SubBuffer = Buffer;
79     SubString = Buffer;
80 
81     while (SubString)
82     {
83         SubString = strstr (SubBuffer, Keyword);
84 
85         if (SubString)
86         {
87             SubBuffer = SubString;
88 
89             if ((Type == REPLACE_WHOLE_WORD) &&
90                 (!AsMatchExactWord (SubString, KeywordLength)))
91             {
92                 SubBuffer++;
93                 continue;
94             }
95 
96             /* Find start of this line */
97 
98             while (*SubString != '\n')
99             {
100                 SubString--;
101             }
102             SubString++;
103 
104             /* Find end of this statement */
105 
106             SubBuffer = AsSkipPastChar (SubBuffer, ';');
107             if (!SubBuffer)
108             {
109                 return;
110             }
111 
112             /* Find end of this line */
113 
114             SubBuffer = AsSkipPastChar (SubBuffer, '\n');
115             if (!SubBuffer)
116             {
117                 return;
118             }
119 
120             /* If next line is blank, remove it too */
121 
122             if (*SubBuffer == '\n')
123             {
124                 SubBuffer++;
125             }
126 
127             /* Remove the lines */
128 
129             SubBuffer = AsRemoveData (SubString, SubBuffer);
130         }
131     }
132 }
133 
134 
135 /******************************************************************************
136  *
137  * FUNCTION:    AsRemoveConditionalCompile
138  *
139  * DESCRIPTION: Remove a "#ifdef" statement, and all text that it encompasses.
140  *              Limitations: cannot handle nested ifdefs.
141  *
142  ******************************************************************************/
143 
144 void
145 AsRemoveConditionalCompile (
146     char                    *Buffer,
147     char                    *Keyword)
148 {
149     char                    *SubString;
150     char                    *SubBuffer;
151     char                    *IfPtr;
152     char                    *EndifPtr;
153     char                    *ElsePtr;
154     char                    *Comment;
155     int                     KeywordLength;
156 
157 
158     KeywordLength = strlen (Keyword);
159     SubBuffer = Buffer;
160     SubString = Buffer;
161 
162     while (SubString)
163     {
164         SubBuffer = strstr (SubString, Keyword);
165         if (!SubBuffer)
166         {
167             return;
168         }
169 
170         /*
171          * Check for translation escape string -- means to ignore
172          * blocks of code while replacing
173          */
174         if (Gbl_IgnoreTranslationEscapes)
175         {
176             Comment = NULL;
177         }
178         else
179         {
180             Comment = strstr (SubString, AS_START_IGNORE);
181         }
182 
183         if ((Comment) &&
184             (Comment < SubBuffer))
185         {
186             SubString = strstr (Comment, AS_STOP_IGNORE);
187             if (!SubString)
188             {
189                 return;
190             }
191 
192             SubString += 3;
193             continue;
194         }
195 
196         /* Check for ordinary comment */
197 
198         Comment = strstr (SubString, "/*");
199 
200         if ((Comment) &&
201             (Comment < SubBuffer))
202         {
203             SubString = strstr (Comment, "*/");
204             if (!SubString)
205             {
206                 return;
207             }
208 
209             SubString += 2;
210             continue;
211         }
212 
213         SubString = SubBuffer;
214         if (!AsMatchExactWord (SubString, KeywordLength))
215         {
216             SubString++;
217             continue;
218         }
219 
220         /* Find start of this line */
221 
222         while (*SubString != '\n' && (SubString > Buffer))
223         {
224             SubString--;
225         }
226 
227         SubString++;
228 
229         /* Find the "#ifxxxx" */
230 
231         IfPtr = strstr (SubString, "#if");
232         if (!IfPtr)
233         {
234             return;
235         }
236 
237         if (IfPtr > SubBuffer)
238         {
239             /* Not the right #if */
240 
241             SubString = SubBuffer + strlen (Keyword);
242             continue;
243         }
244 
245         /* Find closing #endif or #else */
246 
247         EndifPtr = strstr (SubBuffer, "#endif");
248         if (!EndifPtr)
249         {
250             /* There has to be an #endif */
251 
252             return;
253         }
254 
255         ElsePtr = strstr (SubBuffer, "#else");
256         if ((ElsePtr) &&
257             (EndifPtr > ElsePtr))
258         {
259             /* This #ifdef contains an #else clause */
260             /* Find end of this line */
261 
262             SubBuffer = AsSkipPastChar (ElsePtr, '\n');
263             if (!SubBuffer)
264             {
265                 return;
266             }
267 
268             /* Remove the #ifdef .... #else code */
269 
270             AsRemoveData (SubString, SubBuffer);
271 
272             /* Next, we will remove the #endif statement */
273 
274             EndifPtr = strstr (SubString, "#endif");
275             if (!EndifPtr)
276             {
277                 /* There has to be an #endif */
278 
279                 return;
280             }
281 
282             SubString = EndifPtr;
283         }
284 
285         /* Remove the ... #endif part */
286         /* Find end of this line */
287 
288         SubBuffer = AsSkipPastChar (EndifPtr, '\n');
289         if (!SubBuffer)
290         {
291             return;
292         }
293 
294         /* Remove the lines */
295 
296         SubBuffer = AsRemoveData (SubString, SubBuffer);
297     }
298 }
299 
300 
301 #ifdef _OBSOLETE_FUNCTIONS
302 /******************************************************************************
303  *
304  * FUNCTION:    AsRemoveMacro
305  *
306  * DESCRIPTION: Remove every line that contains the keyword. Does not
307  *              skip comments.
308  *
309  ******************************************************************************/
310 
311 NOTE: This function is no longer used and is commented out for now.
312 
313 Also, it appears to have one or more bugs in it. It can incorrectly remove
314 lines of code, producing some garbage.
315 
316 void
317 AsRemoveMacro (
318     char                    *Buffer,
319     char                    *Keyword)
320 {
321     char                    *SubString;
322     char                    *SubBuffer;
323     int                     NestLevel;
324 
325 
326     SubBuffer = Buffer;
327     SubString = Buffer;
328 
329     while (SubString)
330     {
331         SubString = strstr (SubBuffer, Keyword);
332 
333         if (SubString)
334         {
335             SubBuffer = SubString;
336 
337             /* Find start of the macro parameters */
338 
339             while (*SubString != '(')
340             {
341                 SubString++;
342             }
343             SubString++;
344 
345             /* Remove the macro name and opening paren */
346 
347             SubString = AsRemoveData (SubBuffer, SubString);
348 
349             NestLevel = 1;
350             while (*SubString)
351             {
352                 if (*SubString == '(')
353                 {
354                     NestLevel++;
355                 }
356                 else if (*SubString == ')')
357                 {
358                     NestLevel--;
359                 }
360 
361                 SubString++;
362 
363                 if (NestLevel == 0)
364                 {
365                     break;
366                 }
367             }
368 
369             /* Remove the closing paren */
370 
371             SubBuffer = AsRemoveData (SubString-1, SubString);
372         }
373     }
374 }
375 #endif
376 
377 /******************************************************************************
378  *
379  * FUNCTION:    AsRemoveLine
380  *
381  * DESCRIPTION: Remove every line that contains the keyword. Does not
382  *              skip comments.
383  *
384  ******************************************************************************/
385 
386 void
387 AsRemoveLine (
388     char                    *Buffer,
389     char                    *Keyword)
390 {
391     char                    *SubString;
392     char                    *SubBuffer;
393 
394 
395     SubBuffer = Buffer;
396     SubString = Buffer;
397 
398     while (SubString)
399     {
400         SubString = strstr (SubBuffer, Keyword);
401 
402         if (SubString)
403         {
404             SubBuffer = SubString;
405 
406             /* Find start of this line */
407 
408             while (*SubString != '\n')
409             {
410                 SubString--;
411             }
412             SubString++;
413 
414             /* Find end of this line */
415 
416             SubBuffer = AsSkipPastChar (SubBuffer, '\n');
417             if (!SubBuffer)
418             {
419                 return;
420             }
421 
422             /* Remove the line */
423 
424             SubBuffer = AsRemoveData (SubString, SubBuffer);
425         }
426     }
427 }
428 
429 
430 /******************************************************************************
431  *
432  * FUNCTION:    AsReduceTypedefs
433  *
434  * DESCRIPTION: Eliminate certain typedefs
435  *
436  ******************************************************************************/
437 
438 void
439 AsReduceTypedefs (
440     char                    *Buffer,
441     char                    *Keyword)
442 {
443     char                    *SubString;
444     char                    *SubBuffer;
445     int                     NestLevel;
446 
447 
448     SubBuffer = Buffer;
449     SubString = Buffer;
450 
451     while (SubString)
452     {
453         SubString = strstr (SubBuffer, Keyword);
454 
455         if (SubString)
456         {
457             /* Remove the typedef itself */
458 
459             SubBuffer = SubString + strlen ("typedef") + 1;
460             SubBuffer = AsRemoveData (SubString, SubBuffer);
461 
462             /* Find the opening brace of the struct or union */
463 
464             while (*SubString != '{')
465             {
466                 SubString++;
467             }
468             SubString++;
469 
470             /* Find the closing brace. Handles nested braces */
471 
472             NestLevel = 1;
473             while (*SubString)
474             {
475                 if (*SubString == '{')
476                 {
477                     NestLevel++;
478                 }
479                 else if (*SubString == '}')
480                 {
481                     NestLevel--;
482                 }
483 
484                 SubString++;
485 
486                 if (NestLevel == 0)
487                 {
488                     break;
489                 }
490             }
491 
492             /* Remove an extra line feed if present */
493 
494             if (!strncmp (SubString - 3, "\n\n", 2))
495             {
496                 *(SubString -2) = '}';
497                 SubString--;
498             }
499 
500             /* Find the end of the typedef name */
501 
502             SubBuffer = AsSkipUntilChar (SubString, ';');
503 
504             /* And remove the typedef name */
505 
506             SubBuffer = AsRemoveData (SubString, SubBuffer);
507         }
508     }
509 }
510 
511 
512 /******************************************************************************
513  *
514  * FUNCTION:    AsRemoveEmptyBlocks
515  *
516  * DESCRIPTION: Remove any C blocks (e.g., if {}) that contain no code. This
517  *              can happen as a result of removing lines such as DEBUG_PRINT.
518  *
519  ******************************************************************************/
520 
521 void
522 AsRemoveEmptyBlocks (
523     char                    *Buffer,
524     char                    *Filename)
525 {
526     char                    *SubBuffer;
527     char                    *BlockStart;
528     BOOLEAN                 EmptyBlock = TRUE;
529     BOOLEAN                 AnotherPassRequired = TRUE;
530     UINT32                  BlockCount = 0;
531 
532 
533     while (AnotherPassRequired)
534     {
535         SubBuffer = Buffer;
536         AnotherPassRequired = FALSE;
537 
538         while (*SubBuffer)
539         {
540             if (*SubBuffer == '{')
541             {
542                 BlockStart = SubBuffer;
543                 EmptyBlock = TRUE;
544 
545                 SubBuffer++;
546                 while (*SubBuffer != '}')
547                 {
548                     if ((*SubBuffer != ' ') &&
549                         (*SubBuffer != '\n'))
550                     {
551                         EmptyBlock = FALSE;
552                         break;
553                     }
554 
555                     SubBuffer++;
556                 }
557 
558                 if (EmptyBlock)
559                 {
560                     /* Find start of the first line of the block */
561 
562                     while (*BlockStart != '\n')
563                     {
564                         BlockStart--;
565                     }
566 
567                     /* Find end of the last line of the block */
568 
569                     SubBuffer = AsSkipUntilChar (SubBuffer, '\n');
570                     if (!SubBuffer)
571                     {
572                         break;
573                     }
574 
575                     /* Remove the block */
576 
577                     SubBuffer = AsRemoveData (BlockStart, SubBuffer);
578                     BlockCount++;
579                     AnotherPassRequired = TRUE;
580                     continue;
581                 }
582             }
583 
584             SubBuffer++;
585         }
586     }
587 
588     if (BlockCount)
589     {
590         Gbl_MadeChanges = TRUE;
591         AsPrint ("Code blocks deleted", BlockCount, Filename);
592     }
593 }
594 
595 
596 /******************************************************************************
597  *
598  * FUNCTION:    AsRemoveDebugMacros
599  *
600  * DESCRIPTION: Remove all "Debug" macros -- macros that produce debug output.
601  *
602  ******************************************************************************/
603 
604 void
605 AsRemoveDebugMacros (
606     char                    *Buffer)
607 {
608     AsRemoveConditionalCompile (Buffer, "ACPI_DEBUG_OUTPUT");
609 
610     AsRemoveStatement (Buffer, "ACPI_DEBUG_PRINT",      REPLACE_WHOLE_WORD);
611     AsRemoveStatement (Buffer, "ACPI_DEBUG_PRINT_RAW",  REPLACE_WHOLE_WORD);
612     AsRemoveStatement (Buffer, "DEBUG_EXEC",            REPLACE_WHOLE_WORD);
613     AsRemoveStatement (Buffer, "FUNCTION_ENTRY",        REPLACE_WHOLE_WORD);
614     AsRemoveStatement (Buffer, "PROC_NAME",             REPLACE_WHOLE_WORD);
615     AsRemoveStatement (Buffer, "FUNCTION_TRACE",        REPLACE_SUBSTRINGS);
616     AsRemoveStatement (Buffer, "DUMP_",                 REPLACE_SUBSTRINGS);
617 
618     AsReplaceString ("return_VOID",         "return", REPLACE_WHOLE_WORD, Buffer);
619     AsReplaceString ("return_PTR",          "return", REPLACE_WHOLE_WORD, Buffer);
620     AsReplaceString ("return_ACPI_STATUS",  "return", REPLACE_WHOLE_WORD, Buffer);
621     AsReplaceString ("return_acpi_status",  "return", REPLACE_WHOLE_WORD, Buffer);
622     AsReplaceString ("return_VALUE",        "return", REPLACE_WHOLE_WORD, Buffer);
623 }
624 
625 
626 /******************************************************************************
627  *
628  * FUNCTION:    AsCleanupSpecialMacro
629  *
630  * DESCRIPTION: For special macro invocations (invoked without ";" at the end
631  *              of the lines), do the following:
632  *              1. Remove spaces appended by indent at the beginning of lines.
633  *              2. Add an empty line between two special macro invocations.
634  *
635  ******************************************************************************/
636 
637 void
638 AsCleanupSpecialMacro (
639     char                    *Buffer,
640     char                    *Keyword)
641 {
642     char                    *SubString;
643     char                    *SubBuffer;
644     char                    *CommentEnd;
645     int                     NewLine;
646     int                     NestLevel;
647 
648 
649     SubBuffer = Buffer;
650     SubString = Buffer;
651 
652     while (SubString)
653     {
654         SubString = strstr (SubBuffer, Keyword);
655 
656         if (SubString)
657         {
658             /* Find start of the macro parameters */
659 
660             while (*SubString != '(')
661             {
662                 SubString++;
663             }
664 
665             SubString++;
666 
667             NestLevel = 1;
668             while (*SubString)
669             {
670                 if (*SubString == '(')
671                 {
672                     NestLevel++;
673                 }
674                 else if (*SubString == ')')
675                 {
676                     NestLevel--;
677                 }
678 
679                 SubString++;
680 
681                 if (NestLevel == 0)
682                 {
683                     break;
684                 }
685             }
686 
687 SkipLine:
688 
689             /* Find end of the line */
690 
691             NewLine = FALSE;
692             while (!NewLine && *SubString)
693             {
694                 if (*SubString == '\n' && *(SubString - 1) != '\\')
695                 {
696                     NewLine = TRUE;
697                 }
698 
699                 SubString++;
700             }
701 
702             /* Find end of the line */
703 
704             if (*SubString == '#' || *SubString == '\n')
705             {
706                 goto SkipLine;
707             }
708 
709             SubBuffer = SubString;
710 
711             /* Find start of the non-space */
712 
713             while (*SubString == ' ')
714             {
715                 SubString++;
716             }
717 
718             /* Find end of the line */
719 
720             if (*SubString == '#' || *SubString == '\n')
721             {
722                 goto SkipLine;
723             }
724 
725             /* Find end of the line */
726 
727             if (*SubString == '/' || *SubString == '*')
728             {
729                 CommentEnd = strstr (SubString, "*/");
730                 if (CommentEnd)
731                 {
732                     SubString = CommentEnd + 2;
733                     goto SkipLine;
734                 }
735             }
736 
737             SubString = AsRemoveData (SubBuffer, SubString);
738         }
739     }
740 }
741