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