1 /******************************************************************************
2  *
3  * Module Name: asremove - Source conversion - removal functions
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2021, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************
115  *
116  * Alternatively, you may choose to be licensed under the terms of the
117  * following license:
118  *
119  * Redistribution and use in source and binary forms, with or without
120  * modification, are permitted provided that the following conditions
121  * are met:
122  * 1. Redistributions of source code must retain the above copyright
123  *    notice, this list of conditions, and the following disclaimer,
124  *    without modification.
125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126  *    substantially similar to the "NO WARRANTY" disclaimer below
127  *    ("Disclaimer") and any redistribution must be conditioned upon
128  *    including a substantially similar Disclaimer requirement for further
129  *    binary redistribution.
130  * 3. Neither the names of the above-listed copyright holders nor the names
131  *    of any contributors may be used to endorse or promote products derived
132  *    from this software without specific prior written permission.
133  *
134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145  *
146  * Alternatively, you may choose to be licensed under the terms of the
147  * GNU General Public License ("GPL") version 2 as published by the Free
148  * Software Foundation.
149  *
150  *****************************************************************************/
151 
152 #include "acpisrc.h"
153 
154 /* Local prototypes */
155 
156 void
157 AsRemoveStatement (
158     char                    *Buffer,
159     char                    *Keyword,
160     UINT32                  Type);
161 
162 
163 /******************************************************************************
164  *
165  * FUNCTION:    AsRemoveStatement
166  *
167  * DESCRIPTION: Remove all statements that contain the given keyword.
168  *              Limitations:  Removes text from the start of the line that
169  *              contains the keyword to the next semicolon. Currently
170  *              doesn't ignore comments.
171  *
172  ******************************************************************************/
173 
174 void
175 AsRemoveStatement (
176     char                    *Buffer,
177     char                    *Keyword,
178     UINT32                  Type)
179 {
180     char                    *SubString;
181     char                    *SubBuffer;
182     int                     KeywordLength;
183 
184 
185     KeywordLength = strlen (Keyword);
186     SubBuffer = Buffer;
187     SubString = Buffer;
188 
189     while (SubString)
190     {
191         SubString = strstr (SubBuffer, Keyword);
192 
193         if (SubString)
194         {
195             SubBuffer = SubString;
196 
197             if ((Type == REPLACE_WHOLE_WORD) &&
198                 (!AsMatchExactWord (SubString, KeywordLength)))
199             {
200                 SubBuffer++;
201                 continue;
202             }
203 
204             /* Find start of this line */
205 
206             while (*SubString != '\n')
207             {
208                 SubString--;
209             }
210             SubString++;
211 
212             /* Find end of this statement */
213 
214             SubBuffer = AsSkipPastChar (SubBuffer, ';');
215             if (!SubBuffer)
216             {
217                 return;
218             }
219 
220             /* Find end of this line */
221 
222             SubBuffer = AsSkipPastChar (SubBuffer, '\n');
223             if (!SubBuffer)
224             {
225                 return;
226             }
227 
228             /* If next line is blank, remove it too */
229 
230             if (*SubBuffer == '\n')
231             {
232                 SubBuffer++;
233             }
234 
235             /* Remove the lines */
236 
237             SubBuffer = AsRemoveData (SubString, SubBuffer);
238         }
239     }
240 }
241 
242 
243 /******************************************************************************
244  *
245  * FUNCTION:    AsRemoveConditionalCompile
246  *
247  * DESCRIPTION: Remove a "#ifdef" statement, and all text that it encompasses.
248  *              Limitations: cannot handle nested ifdefs.
249  *
250  ******************************************************************************/
251 
252 void
253 AsRemoveConditionalCompile (
254     char                    *Buffer,
255     char                    *Keyword)
256 {
257     char                    *SubString;
258     char                    *SubBuffer;
259     char                    *IfPtr;
260     char                    *EndifPtr;
261     char                    *ElsePtr;
262     char                    *Comment;
263     int                     KeywordLength;
264 
265 
266     KeywordLength = strlen (Keyword);
267     SubString = Buffer;
268 
269     while (SubString)
270     {
271         SubBuffer = strstr (SubString, Keyword);
272         if (!SubBuffer)
273         {
274             return;
275         }
276 
277         /*
278          * Check for translation escape string -- means to ignore
279          * blocks of code while replacing
280          */
281         if (Gbl_IgnoreTranslationEscapes)
282         {
283             Comment = NULL;
284         }
285         else
286         {
287             Comment = strstr (SubString, AS_START_IGNORE);
288         }
289 
290         if ((Comment) &&
291             (Comment < SubBuffer))
292         {
293             SubString = strstr (Comment, AS_STOP_IGNORE);
294             if (!SubString)
295             {
296                 return;
297             }
298 
299             SubString += 3;
300             continue;
301         }
302 
303         /* Check for ordinary comment */
304 
305         Comment = strstr (SubString, "/*");
306 
307         if ((Comment) &&
308             (Comment < SubBuffer))
309         {
310             SubString = strstr (Comment, "*/");
311             if (!SubString)
312             {
313                 return;
314             }
315 
316             SubString += 2;
317             continue;
318         }
319 
320         SubString = SubBuffer;
321         if (!AsMatchExactWord (SubString, KeywordLength))
322         {
323             SubString++;
324             continue;
325         }
326 
327         /* Find start of this line */
328 
329         while (*SubString != '\n' && (SubString > Buffer))
330         {
331             SubString--;
332         }
333 
334         SubString++;
335 
336         /* Find the "#ifxxxx" */
337 
338         IfPtr = strstr (SubString, "#if");
339         if (!IfPtr)
340         {
341             return;
342         }
343 
344         if (IfPtr > SubBuffer)
345         {
346             /* Not the right #if */
347 
348             SubString = SubBuffer + strlen (Keyword);
349             continue;
350         }
351 
352         /* Find closing #endif or #else */
353 
354         EndifPtr = strstr (SubBuffer, "#endif");
355         if (!EndifPtr)
356         {
357             /* There has to be an #endif */
358 
359             return;
360         }
361 
362         ElsePtr = strstr (SubBuffer, "#else");
363         if ((ElsePtr) &&
364             (EndifPtr > ElsePtr))
365         {
366             /* This #ifdef contains an #else clause */
367             /* Find end of this line */
368 
369             SubBuffer = AsSkipPastChar (ElsePtr, '\n');
370             if (!SubBuffer)
371             {
372                 return;
373             }
374 
375             /* Remove the #ifdef .... #else code */
376 
377             AsRemoveData (SubString, SubBuffer);
378 
379             /* Next, we will remove the #endif statement */
380 
381             EndifPtr = strstr (SubString, "#endif");
382             if (!EndifPtr)
383             {
384                 /* There has to be an #endif */
385 
386                 return;
387             }
388 
389             SubString = EndifPtr;
390         }
391 
392         /* Remove the ... #endif part */
393         /* Find end of this line */
394 
395         SubBuffer = AsSkipPastChar (EndifPtr, '\n');
396         if (!SubBuffer)
397         {
398             return;
399         }
400 
401         /* Remove the lines */
402 
403         (void) AsRemoveData (SubString, SubBuffer);
404     }
405 }
406 
407 
408 #ifdef _OBSOLETE_FUNCTIONS
409 /******************************************************************************
410  *
411  * FUNCTION:    AsRemoveMacro
412  *
413  * DESCRIPTION: Remove every line that contains the keyword. Does not
414  *              skip comments.
415  *
416  ******************************************************************************/
417 
418 NOTE: This function is no longer used and is commented out for now.
419 
420 Also, it appears to have one or more bugs in it. It can incorrectly remove
421 lines of code, producing some garbage.
422 
423 void
424 AsRemoveMacro (
425     char                    *Buffer,
426     char                    *Keyword)
427 {
428     char                    *SubString;
429     char                    *SubBuffer;
430     int                     NestLevel;
431 
432 
433     SubBuffer = Buffer;
434     SubString = Buffer;
435 
436     while (SubString)
437     {
438         SubString = strstr (SubBuffer, Keyword);
439 
440         if (SubString)
441         {
442             SubBuffer = SubString;
443 
444             /* Find start of the macro parameters */
445 
446             while (*SubString != '(')
447             {
448                 SubString++;
449             }
450             SubString++;
451 
452             /* Remove the macro name and opening paren */
453 
454             SubString = AsRemoveData (SubBuffer, SubString);
455 
456             NestLevel = 1;
457             while (*SubString)
458             {
459                 if (*SubString == '(')
460                 {
461                     NestLevel++;
462                 }
463                 else if (*SubString == ')')
464                 {
465                     NestLevel--;
466                 }
467 
468                 SubString++;
469 
470                 if (NestLevel == 0)
471                 {
472                     break;
473                 }
474             }
475 
476             /* Remove the closing paren */
477 
478             SubBuffer = AsRemoveData (SubString-1, SubString);
479         }
480     }
481 }
482 #endif
483 
484 /******************************************************************************
485  *
486  * FUNCTION:    AsRemoveLine
487  *
488  * DESCRIPTION: Remove every line that contains the keyword. Does not
489  *              skip comments.
490  *
491  ******************************************************************************/
492 
493 void
494 AsRemoveLine (
495     char                    *Buffer,
496     char                    *Keyword)
497 {
498     char                    *SubString;
499     char                    *SubBuffer;
500 
501 
502     SubBuffer = Buffer;
503     SubString = Buffer;
504 
505     while (SubString)
506     {
507         SubString = strstr (SubBuffer, Keyword);
508 
509         if (SubString)
510         {
511             SubBuffer = SubString;
512 
513             /* Find start of this line */
514 
515             while (*SubString != '\n')
516             {
517                 SubString--;
518             }
519             SubString++;
520 
521             /* Find end of this line */
522 
523             SubBuffer = AsSkipPastChar (SubBuffer, '\n');
524             if (!SubBuffer)
525             {
526                 return;
527             }
528 
529             /* Remove the line */
530 
531             SubBuffer = AsRemoveData (SubString, SubBuffer);
532         }
533     }
534 }
535 
536 
537 /******************************************************************************
538  *
539  * FUNCTION:    AsReduceTypedefs
540  *
541  * DESCRIPTION: Eliminate certain typedefs
542  *
543  ******************************************************************************/
544 
545 void
546 AsReduceTypedefs (
547     char                    *Buffer,
548     char                    *Keyword)
549 {
550     char                    *SubString;
551     char                    *SubBuffer;
552     char                    *SubSubString;
553     int                     NestLevel;
554 
555 
556     SubBuffer = Buffer;
557     SubString = Buffer;
558 
559     while (SubString)
560     {
561         SubString = strstr (SubBuffer, Keyword);
562 
563         if (SubString)
564         {
565             SubSubString = SubString + strlen (Keyword);
566 
567             /* skip spaces */
568 
569             while (strchr(" \t\r\n", *SubSubString))
570             {
571                 SubSubString++;
572             }
573 
574             /* skip type name */
575 
576             while (!strchr(" \t\r\n", *SubSubString))
577             {
578                 SubSubString++;
579             }
580 
581             /* skip spaces */
582 
583             while (strchr(" \t\r\n", *SubSubString))
584             {
585                 SubSubString++;
586             }
587 
588             if (*SubSubString == '{')
589             {
590                 /* Remove the typedef itself */
591 
592                 SubBuffer = SubString + strlen ("typedef") + 1;
593                 (void) AsRemoveData (SubString, SubBuffer);
594 
595                 /* Find the opening brace of the struct or union */
596 
597                 while (*SubString != '{')
598                 {
599                     SubString++;
600                 }
601                 SubString++;
602 
603                 /* Find the closing brace. Handles nested braces */
604 
605                 NestLevel = 1;
606                 while (*SubString)
607                 {
608                     if (*SubString == '{')
609                     {
610                         NestLevel++;
611                     }
612                     else if (*SubString == '}')
613                     {
614                         NestLevel--;
615                     }
616 
617                     SubString++;
618 
619                     if (NestLevel == 0)
620                     {
621                         break;
622                     }
623                 }
624 
625                 /* Remove an extra line feed if present */
626 
627                 if (!strncmp (SubString - 3, "\n\n", 2))
628                 {
629                     *(SubString -2) = '}';
630                     SubString--;
631                 }
632 
633                 /* Find the end of the typedef name */
634 
635                 SubBuffer = AsSkipUntilChar (SubString, ';');
636 
637                 /* And remove the typedef name */
638 
639                 SubBuffer = AsRemoveData (SubString, SubBuffer);
640             }
641             else
642             {
643                 /* Skip the entire definition */
644 
645                 SubString = strchr (SubString, ';') + 1;
646                 SubBuffer = SubString;
647             }
648         }
649     }
650 }
651 
652 
653 /******************************************************************************
654  *
655  * FUNCTION:    AsRemoveEmptyBlocks
656  *
657  * DESCRIPTION: Remove any C blocks (e.g., if {}) that contain no code. This
658  *              can happen as a result of removing lines such as DEBUG_PRINT.
659  *
660  ******************************************************************************/
661 
662 void
663 AsRemoveEmptyBlocks (
664     char                    *Buffer,
665     char                    *Filename)
666 {
667     char                    *SubBuffer;
668     char                    *BlockStart;
669     BOOLEAN                 EmptyBlock = TRUE;
670     BOOLEAN                 AnotherPassRequired = TRUE;
671     UINT32                  BlockCount = 0;
672 
673 
674     while (AnotherPassRequired)
675     {
676         SubBuffer = Buffer;
677         AnotherPassRequired = FALSE;
678 
679         while (*SubBuffer)
680         {
681             if (*SubBuffer == '{')
682             {
683                 BlockStart = SubBuffer;
684                 EmptyBlock = TRUE;
685 
686                 SubBuffer++;
687                 while (*SubBuffer != '}')
688                 {
689                     if ((*SubBuffer != ' ') &&
690                         (*SubBuffer != '\n'))
691                     {
692                         EmptyBlock = FALSE;
693                         break;
694                     }
695 
696                     SubBuffer++;
697                 }
698 
699                 if (EmptyBlock)
700                 {
701                     /* Find start of the first line of the block */
702 
703                     while (*BlockStart != '\n')
704                     {
705                         BlockStart--;
706                     }
707 
708                     /* Find end of the last line of the block */
709 
710                     SubBuffer = AsSkipUntilChar (SubBuffer, '\n');
711                     if (!SubBuffer)
712                     {
713                         break;
714                     }
715 
716                     /* Remove the block */
717 
718                     SubBuffer = AsRemoveData (BlockStart, SubBuffer);
719                     BlockCount++;
720                     AnotherPassRequired = TRUE;
721                     continue;
722                 }
723             }
724 
725             SubBuffer++;
726         }
727     }
728 
729     if (BlockCount)
730     {
731         Gbl_MadeChanges = TRUE;
732         AsPrint ("Code blocks deleted", BlockCount, Filename);
733     }
734 }
735 
736 
737 /******************************************************************************
738  *
739  * FUNCTION:    AsRemoveDebugMacros
740  *
741  * DESCRIPTION: Remove all "Debug" macros -- macros that produce debug output.
742  *
743  ******************************************************************************/
744 
745 void
746 AsRemoveDebugMacros (
747     char                    *Buffer)
748 {
749     AsRemoveConditionalCompile (Buffer, "ACPI_DEBUG_OUTPUT");
750 
751     AsRemoveStatement (Buffer, "ACPI_DEBUG_PRINT",      REPLACE_WHOLE_WORD);
752     AsRemoveStatement (Buffer, "ACPI_DEBUG_PRINT_RAW",  REPLACE_WHOLE_WORD);
753     AsRemoveStatement (Buffer, "DEBUG_EXEC",            REPLACE_WHOLE_WORD);
754     AsRemoveStatement (Buffer, "FUNCTION_ENTRY",        REPLACE_WHOLE_WORD);
755     AsRemoveStatement (Buffer, "PROC_NAME",             REPLACE_WHOLE_WORD);
756     AsRemoveStatement (Buffer, "FUNCTION_TRACE",        REPLACE_SUBSTRINGS);
757     AsRemoveStatement (Buffer, "DUMP_",                 REPLACE_SUBSTRINGS);
758 
759     AsReplaceString ("return_VOID",         "return", REPLACE_WHOLE_WORD, Buffer);
760     AsReplaceString ("return_PTR",          "return", REPLACE_WHOLE_WORD, Buffer);
761     AsReplaceString ("return_STR",          "return", REPLACE_WHOLE_WORD, Buffer);
762     AsReplaceString ("return_ACPI_STATUS",  "return", REPLACE_WHOLE_WORD, Buffer);
763     AsReplaceString ("return_acpi_status",  "return", REPLACE_WHOLE_WORD, Buffer);
764     AsReplaceString ("return_VALUE",        "return", REPLACE_WHOLE_WORD, Buffer);
765 }
766 
767 
768 /******************************************************************************
769  *
770  * FUNCTION:    AsCleanupSpecialMacro
771  *
772  * DESCRIPTION: For special macro invocations (invoked without ";" at the end
773  *              of the lines), do the following:
774  *              1. Remove spaces appended by indent at the beginning of lines.
775  *              2. Add an empty line between two special macro invocations.
776  *
777  ******************************************************************************/
778 
779 void
780 AsCleanupSpecialMacro (
781     char                    *Buffer,
782     char                    *Keyword)
783 {
784     char                    *SubString;
785     char                    *SubBuffer;
786     char                    *CommentEnd;
787     int                     NewLine;
788     int                     NestLevel;
789 
790 
791     SubBuffer = Buffer;
792     SubString = Buffer;
793 
794     while (SubString)
795     {
796         SubString = strstr (SubBuffer, Keyword);
797 
798         if (SubString)
799         {
800             /* Find start of the macro parameters */
801 
802             while (*SubString != '(')
803             {
804                 SubString++;
805             }
806 
807             SubString++;
808 
809             NestLevel = 1;
810             while (*SubString)
811             {
812                 if (*SubString == '(')
813                 {
814                     NestLevel++;
815                 }
816                 else if (*SubString == ')')
817                 {
818                     NestLevel--;
819                 }
820 
821                 SubString++;
822 
823                 if (NestLevel == 0)
824                 {
825                     break;
826                 }
827             }
828 
829 SkipLine:
830 
831             /* Find end of the line */
832 
833             NewLine = FALSE;
834             while (!NewLine && *SubString)
835             {
836                 if (*SubString == '\n' && *(SubString - 1) != '\\')
837                 {
838                     NewLine = TRUE;
839                 }
840 
841                 SubString++;
842             }
843 
844             /* Find end of the line */
845 
846             if (*SubString == '#' || *SubString == '\n')
847             {
848                 goto SkipLine;
849             }
850 
851             SubBuffer = SubString;
852 
853             /* Find start of the non-space */
854 
855             while (*SubString == ' ')
856             {
857                 SubString++;
858             }
859 
860             /* Find end of the line */
861 
862             if (*SubString == '#' || *SubString == '\n')
863             {
864                 goto SkipLine;
865             }
866 
867             /* Find end of the line */
868 
869             if (*SubString == '/' || *SubString == '*')
870             {
871                 CommentEnd = strstr (SubString, "*/");
872                 if (CommentEnd)
873                 {
874                     SubString = CommentEnd + 2;
875                     goto SkipLine;
876                 }
877             }
878 
879             SubString = AsRemoveData (SubBuffer, SubString);
880         }
881     }
882 }
883