1 /******************************************************************************
2  *
3  * Module Name: asremove - Source conversion - removal functions
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, 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 
82     while (SubString)
83     {
84         SubString = strstr (SubBuffer, Keyword);
85 
86         if (SubString)
87         {
88             SubBuffer = SubString;
89 
90             if ((Type == REPLACE_WHOLE_WORD) &&
91                 (!AsMatchExactWord (SubString, KeywordLength)))
92             {
93                 SubBuffer++;
94                 continue;
95             }
96 
97             /* Find start of this line */
98 
99             while (*SubString != '\n')
100             {
101                 SubString--;
102             }
103             SubString++;
104 
105             /* Find end of this statement */
106 
107             SubBuffer = AsSkipPastChar (SubBuffer, ';');
108             if (!SubBuffer)
109             {
110                 return;
111             }
112 
113             /* Find end of this line */
114 
115             SubBuffer = AsSkipPastChar (SubBuffer, '\n');
116             if (!SubBuffer)
117             {
118                 return;
119             }
120 
121             /* If next line is blank, remove it too */
122 
123             if (*SubBuffer == '\n')
124             {
125                 SubBuffer++;
126             }
127 
128             /* Remove the lines */
129 
130             SubBuffer = AsRemoveData (SubString, SubBuffer);
131         }
132     }
133 }
134 
135 
136 /******************************************************************************
137  *
138  * FUNCTION:    AsRemoveConditionalCompile
139  *
140  * DESCRIPTION: Remove a "#ifdef" statement, and all text that it encompasses.
141  *              Limitations: cannot handle nested ifdefs.
142  *
143  ******************************************************************************/
144 
145 void
146 AsRemoveConditionalCompile (
147     char                    *Buffer,
148     char                    *Keyword)
149 {
150     char                    *SubString;
151     char                    *SubBuffer;
152     char                    *IfPtr;
153     char                    *EndifPtr;
154     char                    *ElsePtr;
155     char                    *Comment;
156     int                     KeywordLength;
157 
158 
159     KeywordLength = strlen (Keyword);
160     SubBuffer = Buffer;
161     SubString = Buffer;
162 
163 
164     while (SubString)
165     {
166         SubBuffer = strstr (SubString, Keyword);
167         if (!SubBuffer)
168         {
169             return;
170         }
171 
172         /*
173          * Check for translation escape string -- means to ignore
174          * blocks of code while replacing
175          */
176         if (Gbl_IgnoreTranslationEscapes)
177         {
178             Comment = NULL;
179         }
180         else
181         {
182             Comment = strstr (SubString, AS_START_IGNORE);
183         }
184 
185         if ((Comment) &&
186             (Comment < SubBuffer))
187         {
188             SubString = strstr (Comment, AS_STOP_IGNORE);
189             if (!SubString)
190             {
191                 return;
192             }
193 
194             SubString += 3;
195             continue;
196         }
197 
198         /* Check for ordinary comment */
199 
200         Comment = strstr (SubString, "/*");
201 
202         if ((Comment) &&
203             (Comment < SubBuffer))
204         {
205             SubString = strstr (Comment, "*/");
206             if (!SubString)
207             {
208                 return;
209             }
210 
211             SubString += 2;
212             continue;
213         }
214 
215         SubString = SubBuffer;
216         if (!AsMatchExactWord (SubString, KeywordLength))
217         {
218             SubString++;
219             continue;
220         }
221 
222         /* Find start of this line */
223 
224         while (*SubString != '\n' && (SubString > Buffer))
225         {
226             SubString--;
227         }
228         SubString++;
229 
230         /* Find the "#ifxxxx" */
231 
232         IfPtr = strstr (SubString, "#if");
233         if (!IfPtr)
234         {
235             return;
236         }
237 
238         if (IfPtr > SubBuffer)
239         {
240             /* Not the right #if */
241 
242             SubString = SubBuffer + strlen (Keyword);
243             continue;
244         }
245 
246         /* Find closing #endif or #else */
247 
248         EndifPtr = strstr (SubBuffer, "#endif");
249         if (!EndifPtr)
250         {
251             /* There has to be an #endif */
252 
253             return;
254         }
255 
256         ElsePtr = strstr (SubBuffer, "#else");
257         if ((ElsePtr) &&
258             (EndifPtr > ElsePtr))
259         {
260             /* This #ifdef contains an #else clause */
261             /* Find end of this line */
262 
263             SubBuffer = AsSkipPastChar (ElsePtr, '\n');
264             if (!SubBuffer)
265             {
266                 return;
267             }
268 
269             /* Remove the #ifdef .... #else code */
270 
271             AsRemoveData (SubString, SubBuffer);
272 
273             /* Next, we will remove the #endif statement */
274 
275             EndifPtr = strstr (SubString, "#endif");
276             if (!EndifPtr)
277             {
278                 /* There has to be an #endif */
279 
280                 return;
281             }
282 
283             SubString = EndifPtr;
284         }
285 
286         /* Remove the ... #endif part */
287         /* Find end of this line */
288 
289         SubBuffer = AsSkipPastChar (EndifPtr, '\n');
290         if (!SubBuffer)
291         {
292             return;
293         }
294 
295         /* Remove the lines */
296 
297         SubBuffer = AsRemoveData (SubString, SubBuffer);
298     }
299 }
300 
301 
302 /******************************************************************************
303  *
304  * FUNCTION:    AsRemoveMacro
305  *
306  * DESCRIPTION: Remove every line that contains the keyword. Does not
307  *              skip comments.
308  *
309  ******************************************************************************/
310 
311 void
312 AsRemoveMacro (
313     char                    *Buffer,
314     char                    *Keyword)
315 {
316     char                    *SubString;
317     char                    *SubBuffer;
318     int                     NestLevel;
319 
320 
321     SubBuffer = Buffer;
322     SubString = Buffer;
323 
324 
325     while (SubString)
326     {
327         SubString = strstr (SubBuffer, Keyword);
328 
329         if (SubString)
330         {
331             SubBuffer = SubString;
332 
333             /* Find start of the macro parameters */
334 
335             while (*SubString != '(')
336             {
337                 SubString++;
338             }
339             SubString++;
340 
341             /* Remove the macro name and opening paren */
342 
343             SubString = AsRemoveData (SubBuffer, SubString);
344 
345             NestLevel = 1;
346             while (*SubString)
347             {
348                 if (*SubString == '(')
349                 {
350                     NestLevel++;
351                 }
352                 else if (*SubString == ')')
353                 {
354                     NestLevel--;
355                 }
356 
357                 SubString++;
358 
359                 if (NestLevel == 0)
360                 {
361                     break;
362                 }
363             }
364 
365             /* Remove the closing paren */
366 
367             SubBuffer = AsRemoveData (SubString-1, SubString);
368         }
369     }
370 }
371 
372 
373 /******************************************************************************
374  *
375  * FUNCTION:    AsRemoveLine
376  *
377  * DESCRIPTION: Remove every line that contains the keyword. Does not
378  *              skip comments.
379  *
380  ******************************************************************************/
381 
382 void
383 AsRemoveLine (
384     char                    *Buffer,
385     char                    *Keyword)
386 {
387     char                    *SubString;
388     char                    *SubBuffer;
389 
390 
391     SubBuffer = Buffer;
392     SubString = Buffer;
393 
394 
395     while (SubString)
396     {
397         SubString = strstr (SubBuffer, Keyword);
398 
399         if (SubString)
400         {
401             SubBuffer = SubString;
402 
403             /* Find start of this line */
404 
405             while (*SubString != '\n')
406             {
407                 SubString--;
408             }
409             SubString++;
410 
411             /* Find end of this line */
412 
413             SubBuffer = AsSkipPastChar (SubBuffer, '\n');
414             if (!SubBuffer)
415             {
416                 return;
417             }
418 
419             /* Remove the line */
420 
421             SubBuffer = AsRemoveData (SubString, SubBuffer);
422         }
423     }
424 }
425 
426 
427 /******************************************************************************
428  *
429  * FUNCTION:    AsReduceTypedefs
430  *
431  * DESCRIPTION: Eliminate certain typedefs
432  *
433  ******************************************************************************/
434 
435 void
436 AsReduceTypedefs (
437     char                    *Buffer,
438     char                    *Keyword)
439 {
440     char                    *SubString;
441     char                    *SubBuffer;
442     int                     NestLevel;
443 
444 
445     SubBuffer = Buffer;
446     SubString = Buffer;
447 
448 
449     while (SubString)
450     {
451         SubString = strstr (SubBuffer, Keyword);
452 
453         if (SubString)
454         {
455             /* Remove the typedef itself */
456 
457             SubBuffer = SubString + strlen ("typedef") + 1;
458             SubBuffer = AsRemoveData (SubString, SubBuffer);
459 
460             /* Find the opening brace of the struct or union */
461 
462             while (*SubString != '{')
463             {
464                 SubString++;
465             }
466             SubString++;
467 
468             /* Find the closing brace. Handles nested braces */
469 
470             NestLevel = 1;
471             while (*SubString)
472             {
473                 if (*SubString == '{')
474                 {
475                     NestLevel++;
476                 }
477                 else if (*SubString == '}')
478                 {
479                     NestLevel--;
480                 }
481 
482                 SubString++;
483 
484                 if (NestLevel == 0)
485                 {
486                     break;
487                 }
488             }
489 
490             /* Remove an extra line feed if present */
491 
492             if (!strncmp (SubString - 3, "\n\n", 2))
493             {
494                 *(SubString -2) = '}';
495                 SubString--;
496             }
497 
498             /* Find the end of the typedef name */
499 
500             SubBuffer = AsSkipUntilChar (SubString, ';');
501 
502             /* And remove the typedef name */
503 
504             SubBuffer = AsRemoveData (SubString, SubBuffer);
505         }
506     }
507 }
508 
509 
510 /******************************************************************************
511  *
512  * FUNCTION:    AsRemoveEmptyBlocks
513  *
514  * DESCRIPTION: Remove any C blocks (e.g., if {}) that contain no code. This
515  *              can happen as a result of removing lines such as DEBUG_PRINT.
516  *
517  ******************************************************************************/
518 
519 void
520 AsRemoveEmptyBlocks (
521     char                    *Buffer,
522     char                    *Filename)
523 {
524     char                    *SubBuffer;
525     char                    *BlockStart;
526     BOOLEAN                 EmptyBlock = TRUE;
527     BOOLEAN                 AnotherPassRequired = TRUE;
528     UINT32                  BlockCount = 0;
529 
530 
531     while (AnotherPassRequired)
532     {
533         SubBuffer = Buffer;
534         AnotherPassRequired = FALSE;
535 
536         while (*SubBuffer)
537         {
538             if (*SubBuffer == '{')
539             {
540                 BlockStart = SubBuffer;
541                 EmptyBlock = TRUE;
542 
543                 SubBuffer++;
544                 while (*SubBuffer != '}')
545                 {
546                     if ((*SubBuffer != ' ') &&
547                         (*SubBuffer != '\n'))
548                     {
549                         EmptyBlock = FALSE;
550                         break;
551                     }
552                     SubBuffer++;
553                 }
554 
555                 if (EmptyBlock)
556                 {
557                     /* Find start of the first line of the block */
558 
559                     while (*BlockStart != '\n')
560                     {
561                         BlockStart--;
562                     }
563 
564                     /* Find end of the last line of the block */
565 
566                     SubBuffer = AsSkipUntilChar (SubBuffer, '\n');
567                     if (!SubBuffer)
568                     {
569                         break;
570                     }
571 
572                     /* Remove the block */
573 
574                     SubBuffer = AsRemoveData (BlockStart, SubBuffer);
575                     BlockCount++;
576                     AnotherPassRequired = TRUE;
577                     continue;
578                 }
579             }
580 
581             SubBuffer++;
582         }
583     }
584 
585     if (BlockCount)
586     {
587         Gbl_MadeChanges = TRUE;
588         AsPrint ("Code blocks deleted", BlockCount, Filename);
589     }
590 }
591 
592 
593 /******************************************************************************
594  *
595  * FUNCTION:    AsRemoveDebugMacros
596  *
597  * DESCRIPTION: Remove all "Debug" macros -- macros that produce debug output.
598  *
599  ******************************************************************************/
600 
601 void
602 AsRemoveDebugMacros (
603     char                    *Buffer)
604 {
605     AsRemoveConditionalCompile (Buffer, "ACPI_DEBUG_OUTPUT");
606 
607     AsRemoveStatement (Buffer, "ACPI_DEBUG_PRINT",      REPLACE_WHOLE_WORD);
608     AsRemoveStatement (Buffer, "ACPI_DEBUG_PRINT_RAW",  REPLACE_WHOLE_WORD);
609     AsRemoveStatement (Buffer, "DEBUG_EXEC",            REPLACE_WHOLE_WORD);
610     AsRemoveStatement (Buffer, "FUNCTION_ENTRY",        REPLACE_WHOLE_WORD);
611     AsRemoveStatement (Buffer, "PROC_NAME",             REPLACE_WHOLE_WORD);
612     AsRemoveStatement (Buffer, "FUNCTION_TRACE",        REPLACE_SUBSTRINGS);
613     AsRemoveStatement (Buffer, "DUMP_",                 REPLACE_SUBSTRINGS);
614 
615     AsReplaceString ("return_VOID",         "return", REPLACE_WHOLE_WORD, Buffer);
616     AsReplaceString ("return_PTR",          "return", REPLACE_WHOLE_WORD, Buffer);
617     AsReplaceString ("return_ACPI_STATUS",  "return", REPLACE_WHOLE_WORD, Buffer);
618     AsReplaceString ("return_acpi_status",  "return", REPLACE_WHOLE_WORD, Buffer);
619     AsReplaceString ("return_VALUE",        "return", REPLACE_WHOLE_WORD, Buffer);
620 }
621 
622 
623 /******************************************************************************
624  *
625  * FUNCTION:    AsCleanupSpecialMacro
626  *
627  * DESCRIPTION: For special macro invocations (invoked without ";" at the end
628  *              of the lines), do the following:
629  *              1. Remove spaces appended by indent at the beginning of lines.
630  *              2. Add an empty line between two special macro invocations.
631  *
632  ******************************************************************************/
633 
634 void
635 AsCleanupSpecialMacro (
636     char                    *Buffer,
637     char                    *Keyword)
638 {
639     char                    *SubString;
640     char                    *SubBuffer;
641     char                    *CommentEnd;
642     int                     NewLine;
643     int                     NestLevel;
644 
645 
646     SubBuffer = Buffer;
647     SubString = Buffer;
648 
649     while (SubString)
650     {
651         SubString = strstr (SubBuffer, Keyword);
652 
653         if (SubString)
654         {
655             /* Find start of the macro parameters */
656 
657             while (*SubString != '(')
658             {
659                 SubString++;
660             }
661             SubString++;
662 
663             NestLevel = 1;
664             while (*SubString)
665             {
666                 if (*SubString == '(')
667                 {
668                     NestLevel++;
669                 }
670                 else if (*SubString == ')')
671                 {
672                     NestLevel--;
673                 }
674 
675                 SubString++;
676 
677                 if (NestLevel == 0)
678                 {
679                     break;
680                 }
681             }
682 
683 SkipLine:
684 
685             /* Find end of the line */
686 
687             NewLine = FALSE;
688             while (!NewLine && *SubString)
689             {
690                 if (*SubString == '\n' && *(SubString - 1) != '\\')
691                 {
692                     NewLine = TRUE;
693                 }
694                 SubString++;
695             }
696 
697             /* Find end of the line */
698 
699             if (*SubString == '#' || *SubString == '\n')
700             {
701                 goto SkipLine;
702             }
703 
704             SubBuffer = SubString;
705 
706             /* Find start of the non-space */
707 
708             while (*SubString == ' ')
709             {
710                 SubString++;
711             }
712 
713             /* Find end of the line */
714 
715             if (*SubString == '#' || *SubString == '\n')
716             {
717                 goto SkipLine;
718             }
719 
720             /* Find end of the line */
721 
722             if (*SubString == '/' || *SubString == '*')
723             {
724                 CommentEnd = strstr (SubString, "*/");
725                 if (CommentEnd)
726                 {
727                     SubString = CommentEnd + 2;
728                     goto SkipLine;
729                 }
730             }
731 
732             SubString = AsRemoveData (SubBuffer, SubString);
733         }
734     }
735 }
736