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 #ifdef _OBSOLETE_FUNCTIONS
303 /******************************************************************************
304  *
305  * FUNCTION:    AsRemoveMacro
306  *
307  * DESCRIPTION: Remove every line that contains the keyword. Does not
308  *              skip comments.
309  *
310  ******************************************************************************/
311 
312 NOTE: This function is no longer used and is commented out for now.
313 
314 Also, it appears to have one or more bugs in it. It can incorrectly remove
315 lines of code, producing some garbage.
316 
317 void
318 AsRemoveMacro (
319     char                    *Buffer,
320     char                    *Keyword)
321 {
322     char                    *SubString;
323     char                    *SubBuffer;
324     int                     NestLevel;
325 
326 
327     SubBuffer = Buffer;
328     SubString = Buffer;
329 
330 
331     while (SubString)
332     {
333         SubString = strstr (SubBuffer, Keyword);
334 
335         if (SubString)
336         {
337             SubBuffer = SubString;
338 
339             /* Find start of the macro parameters */
340 
341             while (*SubString != '(')
342             {
343                 SubString++;
344             }
345             SubString++;
346 
347             /* Remove the macro name and opening paren */
348 
349             SubString = AsRemoveData (SubBuffer, SubString);
350 
351             NestLevel = 1;
352             while (*SubString)
353             {
354                 if (*SubString == '(')
355                 {
356                     NestLevel++;
357                 }
358                 else if (*SubString == ')')
359                 {
360                     NestLevel--;
361                 }
362 
363                 SubString++;
364 
365                 if (NestLevel == 0)
366                 {
367                     break;
368                 }
369             }
370 
371             /* Remove the closing paren */
372 
373             SubBuffer = AsRemoveData (SubString-1, SubString);
374         }
375     }
376 }
377 #endif
378 
379 /******************************************************************************
380  *
381  * FUNCTION:    AsRemoveLine
382  *
383  * DESCRIPTION: Remove every line that contains the keyword. Does not
384  *              skip comments.
385  *
386  ******************************************************************************/
387 
388 void
389 AsRemoveLine (
390     char                    *Buffer,
391     char                    *Keyword)
392 {
393     char                    *SubString;
394     char                    *SubBuffer;
395 
396 
397     SubBuffer = Buffer;
398     SubString = Buffer;
399 
400 
401     while (SubString)
402     {
403         SubString = strstr (SubBuffer, Keyword);
404 
405         if (SubString)
406         {
407             SubBuffer = SubString;
408 
409             /* Find start of this line */
410 
411             while (*SubString != '\n')
412             {
413                 SubString--;
414             }
415             SubString++;
416 
417             /* Find end of this line */
418 
419             SubBuffer = AsSkipPastChar (SubBuffer, '\n');
420             if (!SubBuffer)
421             {
422                 return;
423             }
424 
425             /* Remove the line */
426 
427             SubBuffer = AsRemoveData (SubString, SubBuffer);
428         }
429     }
430 }
431 
432 
433 /******************************************************************************
434  *
435  * FUNCTION:    AsReduceTypedefs
436  *
437  * DESCRIPTION: Eliminate certain typedefs
438  *
439  ******************************************************************************/
440 
441 void
442 AsReduceTypedefs (
443     char                    *Buffer,
444     char                    *Keyword)
445 {
446     char                    *SubString;
447     char                    *SubBuffer;
448     int                     NestLevel;
449 
450 
451     SubBuffer = Buffer;
452     SubString = Buffer;
453 
454 
455     while (SubString)
456     {
457         SubString = strstr (SubBuffer, Keyword);
458 
459         if (SubString)
460         {
461             /* Remove the typedef itself */
462 
463             SubBuffer = SubString + strlen ("typedef") + 1;
464             SubBuffer = AsRemoveData (SubString, SubBuffer);
465 
466             /* Find the opening brace of the struct or union */
467 
468             while (*SubString != '{')
469             {
470                 SubString++;
471             }
472             SubString++;
473 
474             /* Find the closing brace. Handles nested braces */
475 
476             NestLevel = 1;
477             while (*SubString)
478             {
479                 if (*SubString == '{')
480                 {
481                     NestLevel++;
482                 }
483                 else if (*SubString == '}')
484                 {
485                     NestLevel--;
486                 }
487 
488                 SubString++;
489 
490                 if (NestLevel == 0)
491                 {
492                     break;
493                 }
494             }
495 
496             /* Remove an extra line feed if present */
497 
498             if (!strncmp (SubString - 3, "\n\n", 2))
499             {
500                 *(SubString -2) = '}';
501                 SubString--;
502             }
503 
504             /* Find the end of the typedef name */
505 
506             SubBuffer = AsSkipUntilChar (SubString, ';');
507 
508             /* And remove the typedef name */
509 
510             SubBuffer = AsRemoveData (SubString, SubBuffer);
511         }
512     }
513 }
514 
515 
516 /******************************************************************************
517  *
518  * FUNCTION:    AsRemoveEmptyBlocks
519  *
520  * DESCRIPTION: Remove any C blocks (e.g., if {}) that contain no code. This
521  *              can happen as a result of removing lines such as DEBUG_PRINT.
522  *
523  ******************************************************************************/
524 
525 void
526 AsRemoveEmptyBlocks (
527     char                    *Buffer,
528     char                    *Filename)
529 {
530     char                    *SubBuffer;
531     char                    *BlockStart;
532     BOOLEAN                 EmptyBlock = TRUE;
533     BOOLEAN                 AnotherPassRequired = TRUE;
534     UINT32                  BlockCount = 0;
535 
536 
537     while (AnotherPassRequired)
538     {
539         SubBuffer = Buffer;
540         AnotherPassRequired = FALSE;
541 
542         while (*SubBuffer)
543         {
544             if (*SubBuffer == '{')
545             {
546                 BlockStart = SubBuffer;
547                 EmptyBlock = TRUE;
548 
549                 SubBuffer++;
550                 while (*SubBuffer != '}')
551                 {
552                     if ((*SubBuffer != ' ') &&
553                         (*SubBuffer != '\n'))
554                     {
555                         EmptyBlock = FALSE;
556                         break;
557                     }
558                     SubBuffer++;
559                 }
560 
561                 if (EmptyBlock)
562                 {
563                     /* Find start of the first line of the block */
564 
565                     while (*BlockStart != '\n')
566                     {
567                         BlockStart--;
568                     }
569 
570                     /* Find end of the last line of the block */
571 
572                     SubBuffer = AsSkipUntilChar (SubBuffer, '\n');
573                     if (!SubBuffer)
574                     {
575                         break;
576                     }
577 
578                     /* Remove the block */
579 
580                     SubBuffer = AsRemoveData (BlockStart, SubBuffer);
581                     BlockCount++;
582                     AnotherPassRequired = TRUE;
583                     continue;
584                 }
585             }
586 
587             SubBuffer++;
588         }
589     }
590 
591     if (BlockCount)
592     {
593         Gbl_MadeChanges = TRUE;
594         AsPrint ("Code blocks deleted", BlockCount, Filename);
595     }
596 }
597 
598 
599 /******************************************************************************
600  *
601  * FUNCTION:    AsRemoveDebugMacros
602  *
603  * DESCRIPTION: Remove all "Debug" macros -- macros that produce debug output.
604  *
605  ******************************************************************************/
606 
607 void
608 AsRemoveDebugMacros (
609     char                    *Buffer)
610 {
611     AsRemoveConditionalCompile (Buffer, "ACPI_DEBUG_OUTPUT");
612 
613     AsRemoveStatement (Buffer, "ACPI_DEBUG_PRINT",      REPLACE_WHOLE_WORD);
614     AsRemoveStatement (Buffer, "ACPI_DEBUG_PRINT_RAW",  REPLACE_WHOLE_WORD);
615     AsRemoveStatement (Buffer, "DEBUG_EXEC",            REPLACE_WHOLE_WORD);
616     AsRemoveStatement (Buffer, "FUNCTION_ENTRY",        REPLACE_WHOLE_WORD);
617     AsRemoveStatement (Buffer, "PROC_NAME",             REPLACE_WHOLE_WORD);
618     AsRemoveStatement (Buffer, "FUNCTION_TRACE",        REPLACE_SUBSTRINGS);
619     AsRemoveStatement (Buffer, "DUMP_",                 REPLACE_SUBSTRINGS);
620 
621     AsReplaceString ("return_VOID",         "return", REPLACE_WHOLE_WORD, Buffer);
622     AsReplaceString ("return_PTR",          "return", REPLACE_WHOLE_WORD, Buffer);
623     AsReplaceString ("return_ACPI_STATUS",  "return", REPLACE_WHOLE_WORD, Buffer);
624     AsReplaceString ("return_acpi_status",  "return", REPLACE_WHOLE_WORD, Buffer);
625     AsReplaceString ("return_VALUE",        "return", REPLACE_WHOLE_WORD, Buffer);
626 }
627 
628 
629 /******************************************************************************
630  *
631  * FUNCTION:    AsCleanupSpecialMacro
632  *
633  * DESCRIPTION: For special macro invocations (invoked without ";" at the end
634  *              of the lines), do the following:
635  *              1. Remove spaces appended by indent at the beginning of lines.
636  *              2. Add an empty line between two special macro invocations.
637  *
638  ******************************************************************************/
639 
640 void
641 AsCleanupSpecialMacro (
642     char                    *Buffer,
643     char                    *Keyword)
644 {
645     char                    *SubString;
646     char                    *SubBuffer;
647     char                    *CommentEnd;
648     int                     NewLine;
649     int                     NestLevel;
650 
651 
652     SubBuffer = Buffer;
653     SubString = Buffer;
654 
655     while (SubString)
656     {
657         SubString = strstr (SubBuffer, Keyword);
658 
659         if (SubString)
660         {
661             /* Find start of the macro parameters */
662 
663             while (*SubString != '(')
664             {
665                 SubString++;
666             }
667             SubString++;
668 
669             NestLevel = 1;
670             while (*SubString)
671             {
672                 if (*SubString == '(')
673                 {
674                     NestLevel++;
675                 }
676                 else if (*SubString == ')')
677                 {
678                     NestLevel--;
679                 }
680 
681                 SubString++;
682 
683                 if (NestLevel == 0)
684                 {
685                     break;
686                 }
687             }
688 
689 SkipLine:
690 
691             /* Find end of the line */
692 
693             NewLine = FALSE;
694             while (!NewLine && *SubString)
695             {
696                 if (*SubString == '\n' && *(SubString - 1) != '\\')
697                 {
698                     NewLine = TRUE;
699                 }
700                 SubString++;
701             }
702 
703             /* Find end of the line */
704 
705             if (*SubString == '#' || *SubString == '\n')
706             {
707                 goto SkipLine;
708             }
709 
710             SubBuffer = SubString;
711 
712             /* Find start of the non-space */
713 
714             while (*SubString == ' ')
715             {
716                 SubString++;
717             }
718 
719             /* Find end of the line */
720 
721             if (*SubString == '#' || *SubString == '\n')
722             {
723                 goto SkipLine;
724             }
725 
726             /* Find end of the line */
727 
728             if (*SubString == '/' || *SubString == '*')
729             {
730                 CommentEnd = strstr (SubString, "*/");
731                 if (CommentEnd)
732                 {
733                     SubString = CommentEnd + 2;
734                     goto SkipLine;
735                 }
736             }
737 
738             SubString = AsRemoveData (SubBuffer, SubString);
739         }
740     }
741 }
742