xref: /netbsd-src/sys/external/bsd/acpica/dist/tools/acpisrc/asremove.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /******************************************************************************
2  *
3  * Module Name: asremove - Source conversion - removal functions
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2018, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "acpisrc.h"
45 
46 /* 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     char                    *SubSubString;
446     int                     NestLevel;
447 
448 
449     SubBuffer = Buffer;
450     SubString = Buffer;
451 
452     while (SubString)
453     {
454         SubString = strstr (SubBuffer, Keyword);
455 
456         if (SubString)
457         {
458             SubSubString = SubString + strlen (Keyword);
459 
460             /* skip spaces */
461 
462             while (strchr(" \t\r\n", *SubSubString))
463             {
464                 SubSubString++;
465             }
466 
467             /* skip type name */
468 
469             while (!strchr(" \t\r\n", *SubSubString))
470             {
471                 SubSubString++;
472             }
473 
474             /* skip spaces */
475 
476             while (strchr(" \t\r\n", *SubSubString))
477             {
478                 SubSubString++;
479             }
480 
481             if (*SubSubString == '{')
482             {
483                 /* Remove the typedef itself */
484 
485                 SubBuffer = SubString + strlen ("typedef") + 1;
486                 SubBuffer = AsRemoveData (SubString, SubBuffer);
487 
488                 /* Find the opening brace of the struct or union */
489 
490                 while (*SubString != '{')
491                 {
492                     SubString++;
493                 }
494                 SubString++;
495 
496                 /* Find the closing brace. Handles nested braces */
497 
498                 NestLevel = 1;
499                 while (*SubString)
500                 {
501                     if (*SubString == '{')
502                     {
503                         NestLevel++;
504                     }
505                     else if (*SubString == '}')
506                     {
507                         NestLevel--;
508                     }
509 
510                     SubString++;
511 
512                     if (NestLevel == 0)
513                     {
514                         break;
515                     }
516                 }
517 
518                 /* Remove an extra line feed if present */
519 
520                 if (!strncmp (SubString - 3, "\n\n", 2))
521                 {
522                     *(SubString -2) = '}';
523                     SubString--;
524                 }
525 
526                 /* Find the end of the typedef name */
527 
528                 SubBuffer = AsSkipUntilChar (SubString, ';');
529 
530                 /* And remove the typedef name */
531 
532                 SubBuffer = AsRemoveData (SubString, SubBuffer);
533             }
534             else
535             {
536                 /* Skip the entire definition */
537 
538                 SubString = strchr (SubString, ';') + 1;
539                 SubBuffer = SubString;
540             }
541         }
542     }
543 }
544 
545 
546 /******************************************************************************
547  *
548  * FUNCTION:    AsRemoveEmptyBlocks
549  *
550  * DESCRIPTION: Remove any C blocks (e.g., if {}) that contain no code. This
551  *              can happen as a result of removing lines such as DEBUG_PRINT.
552  *
553  ******************************************************************************/
554 
555 void
556 AsRemoveEmptyBlocks (
557     char                    *Buffer,
558     char                    *Filename)
559 {
560     char                    *SubBuffer;
561     char                    *BlockStart;
562     BOOLEAN                 EmptyBlock = TRUE;
563     BOOLEAN                 AnotherPassRequired = TRUE;
564     UINT32                  BlockCount = 0;
565 
566 
567     while (AnotherPassRequired)
568     {
569         SubBuffer = Buffer;
570         AnotherPassRequired = FALSE;
571 
572         while (*SubBuffer)
573         {
574             if (*SubBuffer == '{')
575             {
576                 BlockStart = SubBuffer;
577                 EmptyBlock = TRUE;
578 
579                 SubBuffer++;
580                 while (*SubBuffer != '}')
581                 {
582                     if ((*SubBuffer != ' ') &&
583                         (*SubBuffer != '\n'))
584                     {
585                         EmptyBlock = FALSE;
586                         break;
587                     }
588 
589                     SubBuffer++;
590                 }
591 
592                 if (EmptyBlock)
593                 {
594                     /* Find start of the first line of the block */
595 
596                     while (*BlockStart != '\n')
597                     {
598                         BlockStart--;
599                     }
600 
601                     /* Find end of the last line of the block */
602 
603                     SubBuffer = AsSkipUntilChar (SubBuffer, '\n');
604                     if (!SubBuffer)
605                     {
606                         break;
607                     }
608 
609                     /* Remove the block */
610 
611                     SubBuffer = AsRemoveData (BlockStart, SubBuffer);
612                     BlockCount++;
613                     AnotherPassRequired = TRUE;
614                     continue;
615                 }
616             }
617 
618             SubBuffer++;
619         }
620     }
621 
622     if (BlockCount)
623     {
624         Gbl_MadeChanges = TRUE;
625         AsPrint ("Code blocks deleted", BlockCount, Filename);
626     }
627 }
628 
629 
630 /******************************************************************************
631  *
632  * FUNCTION:    AsRemoveDebugMacros
633  *
634  * DESCRIPTION: Remove all "Debug" macros -- macros that produce debug output.
635  *
636  ******************************************************************************/
637 
638 void
639 AsRemoveDebugMacros (
640     char                    *Buffer)
641 {
642     AsRemoveConditionalCompile (Buffer, "ACPI_DEBUG_OUTPUT");
643 
644     AsRemoveStatement (Buffer, "ACPI_DEBUG_PRINT",      REPLACE_WHOLE_WORD);
645     AsRemoveStatement (Buffer, "ACPI_DEBUG_PRINT_RAW",  REPLACE_WHOLE_WORD);
646     AsRemoveStatement (Buffer, "DEBUG_EXEC",            REPLACE_WHOLE_WORD);
647     AsRemoveStatement (Buffer, "FUNCTION_ENTRY",        REPLACE_WHOLE_WORD);
648     AsRemoveStatement (Buffer, "PROC_NAME",             REPLACE_WHOLE_WORD);
649     AsRemoveStatement (Buffer, "FUNCTION_TRACE",        REPLACE_SUBSTRINGS);
650     AsRemoveStatement (Buffer, "DUMP_",                 REPLACE_SUBSTRINGS);
651 
652     AsReplaceString ("return_VOID",         "return", REPLACE_WHOLE_WORD, Buffer);
653     AsReplaceString ("return_PTR",          "return", REPLACE_WHOLE_WORD, Buffer);
654     AsReplaceString ("return_STR",          "return", REPLACE_WHOLE_WORD, Buffer);
655     AsReplaceString ("return_ACPI_STATUS",  "return", REPLACE_WHOLE_WORD, Buffer);
656     AsReplaceString ("return_acpi_status",  "return", REPLACE_WHOLE_WORD, Buffer);
657     AsReplaceString ("return_VALUE",        "return", REPLACE_WHOLE_WORD, Buffer);
658 }
659 
660 
661 /******************************************************************************
662  *
663  * FUNCTION:    AsCleanupSpecialMacro
664  *
665  * DESCRIPTION: For special macro invocations (invoked without ";" at the end
666  *              of the lines), do the following:
667  *              1. Remove spaces appended by indent at the beginning of lines.
668  *              2. Add an empty line between two special macro invocations.
669  *
670  ******************************************************************************/
671 
672 void
673 AsCleanupSpecialMacro (
674     char                    *Buffer,
675     char                    *Keyword)
676 {
677     char                    *SubString;
678     char                    *SubBuffer;
679     char                    *CommentEnd;
680     int                     NewLine;
681     int                     NestLevel;
682 
683 
684     SubBuffer = Buffer;
685     SubString = Buffer;
686 
687     while (SubString)
688     {
689         SubString = strstr (SubBuffer, Keyword);
690 
691         if (SubString)
692         {
693             /* Find start of the macro parameters */
694 
695             while (*SubString != '(')
696             {
697                 SubString++;
698             }
699 
700             SubString++;
701 
702             NestLevel = 1;
703             while (*SubString)
704             {
705                 if (*SubString == '(')
706                 {
707                     NestLevel++;
708                 }
709                 else if (*SubString == ')')
710                 {
711                     NestLevel--;
712                 }
713 
714                 SubString++;
715 
716                 if (NestLevel == 0)
717                 {
718                     break;
719                 }
720             }
721 
722 SkipLine:
723 
724             /* Find end of the line */
725 
726             NewLine = FALSE;
727             while (!NewLine && *SubString)
728             {
729                 if (*SubString == '\n' && *(SubString - 1) != '\\')
730                 {
731                     NewLine = TRUE;
732                 }
733 
734                 SubString++;
735             }
736 
737             /* Find end of the line */
738 
739             if (*SubString == '#' || *SubString == '\n')
740             {
741                 goto SkipLine;
742             }
743 
744             SubBuffer = SubString;
745 
746             /* Find start of the non-space */
747 
748             while (*SubString == ' ')
749             {
750                 SubString++;
751             }
752 
753             /* Find end of the line */
754 
755             if (*SubString == '#' || *SubString == '\n')
756             {
757                 goto SkipLine;
758             }
759 
760             /* Find end of the line */
761 
762             if (*SubString == '/' || *SubString == '*')
763             {
764                 CommentEnd = strstr (SubString, "*/");
765                 if (CommentEnd)
766                 {
767                     SubString = CommentEnd + 2;
768                     goto SkipLine;
769                 }
770             }
771 
772             SubString = AsRemoveData (SubBuffer, SubString);
773         }
774     }
775 }
776