1/******************************************************************************
2 *
3 * Module Name: asconvrt - Source conversion code
4 *
5 *****************************************************************************/
6
7/******************************************************************************
8 *
9 * 1. Copyright Notice
10 *
11 * Some or all of this work - Copyright (c) 1999 - 2016, 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#include "acpisrc.h"
117
118AS_BRACE_INFO               Gbl_BraceInfo[] =
119{
120    {" if",         3},
121    {" else if",    8},
122    {" else while", 11},
123    {" else",       5},
124    {" do ",        4},
125    {NULL,          0}
126};
127
128
129/* Local prototypes */
130
131static char *
132AsMatchValidToken (
133    char                    *Buffer,
134    char                    *Filename,
135    char                    TargetChar,
136    AS_SCAN_CALLBACK        Callback);
137
138static char *
139AsCheckBracesCallback (
140    char                    *Buffer,
141    char                    *Filename,
142    UINT32                  LineNumber);
143
144static UINT32
145AsCountLines (
146    char                    *Buffer,
147    char                    *Filename);
148
149
150/* Opening signature of the Intel legal header */
151
152char        *HeaderBegin = "/******************************************************************************\n *\n * 1. Copyright Notice";
153
154UINT32      NonAnsiCommentCount;
155
156
157/******************************************************************************
158 *
159 * FUNCTION:    AsCountNonAnsiComments
160 *
161 * DESCRIPTION: Count the number of "//" comments. This type of comment is
162 *              non-ANSI C.
163 *
164 * NOTE: July 2014: Allows // within quoted strings and within normal
165 *       comments. Eliminates extraneous warnings from this utility.
166 *
167 ******************************************************************************/
168
169void
170AsCountNonAnsiComments (
171    char                    *Buffer,
172    char                    *Filename)
173{
174
175    AsMatchValidToken (Buffer, Filename, 0, NULL);
176
177    /* Error if any slash-slash comments found */
178
179    if (NonAnsiCommentCount)
180    {
181        AsPrint ("Non-ANSI // Comments Found", NonAnsiCommentCount, Filename);
182        Gbl_NonAnsiComments += NonAnsiCommentCount;
183    }
184}
185
186
187/******************************************************************************
188 *
189 * FUNCTION:    AsCheckForBraces
190 *
191 * DESCRIPTION: Check for an open brace after each if/else/do (etc.)
192 *              statement
193 *
194 ******************************************************************************/
195
196void
197AsCheckForBraces (
198    char                    *Buffer,
199    char                    *Filename)
200{
201
202    AsMatchValidToken (Buffer, Filename, 0, AsCheckBracesCallback);
203}
204
205
206/******************************************************************************
207 *
208 * FUNCTION:    AsCheckBracesCallback
209 *
210 * DESCRIPTION: Check if/else/do statements. Ensure that braces
211 *              are always used.
212 *
213 * TBD: Currently, don't check while() statements. The problem is that there
214 * are two forms: do {} while (); and while () {}.
215 *
216 ******************************************************************************/
217
218static char *
219AsCheckBracesCallback (
220    char                    *Buffer,
221    char                    *Filename,
222    UINT32                  LineNumber)
223{
224    char                    *SubBuffer = Buffer;
225    char                    *NextBrace;
226    char                    *NextSemicolon;
227    AS_BRACE_INFO           *BraceInfo;
228
229
230    for (BraceInfo = Gbl_BraceInfo; BraceInfo->Operator; BraceInfo++)
231    {
232        if (!(strncmp (BraceInfo->Operator, SubBuffer, BraceInfo->Length)))
233        {
234            SubBuffer += (BraceInfo->Length - 1);
235
236            /* Find next brace and the next semicolon */
237
238            NextBrace = AsMatchValidToken (SubBuffer, Filename, '{', NULL);
239            NextSemicolon = AsMatchValidToken (SubBuffer, Filename, ';', NULL);
240
241            /* Next brace should appear before next semicolon */
242
243            if ((!NextBrace) ||
244               (NextSemicolon && (NextBrace > NextSemicolon)))
245            {
246                Gbl_MissingBraces++;
247
248                if (!Gbl_QuietMode)
249                {
250                    printf ("Missing braces for <%s>, line %u: %s\n",
251                        BraceInfo->Operator + 1, LineNumber, Filename);
252                }
253            }
254
255            return (SubBuffer);
256        }
257    }
258
259    /* No match, just return original buffer */
260
261    return (Buffer);
262}
263
264
265/******************************************************************************
266 *
267 * FUNCTION:    AsMatchValidToken
268 *
269 * DESCRIPTION: Find the next matching token in the input buffer.
270 *
271 ******************************************************************************/
272
273static char *
274AsMatchValidToken (
275    char                    *Buffer,
276    char                    *Filename,
277    char                    TargetChar,
278    AS_SCAN_CALLBACK        Callback)
279{
280    char                    *SubBuffer = Buffer;
281    char                    *StringStart;
282    UINT32                  TotalLines;
283
284
285    TotalLines = 1;
286    NonAnsiCommentCount = 0;
287
288    /* Scan from current position up to the end if necessary */
289
290    while (*SubBuffer)
291    {
292        /* Skip normal comments */
293
294        if ((*SubBuffer == '/') &&
295            (*(SubBuffer + 1) == '*'))
296        {
297            /* Must maintain line count */
298
299            SubBuffer += 2;
300            while (strncmp ("*/", SubBuffer, 2))
301            {
302                if (*SubBuffer == '\n')
303                {
304                    TotalLines++;
305                }
306                SubBuffer++;
307            }
308
309            SubBuffer += 2;
310            continue;
311        }
312
313        /* Skip single quoted chars */
314
315        if (*SubBuffer == '\'')
316        {
317            SubBuffer++;
318            if (!(*SubBuffer))
319            {
320                break;
321            }
322
323            if (*SubBuffer == '\\')
324            {
325                SubBuffer++;
326            }
327
328            SubBuffer++;
329            continue;
330        }
331
332        /* Skip quoted strings */
333
334        if (*SubBuffer == '"')
335        {
336            StringStart = SubBuffer;
337            SubBuffer++;
338            if (!(*SubBuffer))
339            {
340                break;
341            }
342
343            while (*SubBuffer != '"')
344            {
345                if ((*SubBuffer == '\n') ||
346                    (!(*SubBuffer)))
347                {
348                    AsPrint ("Unbalanced quoted string",1, Filename);
349                    printf ("    %.32s (line %u)\n", StringStart, TotalLines);
350                    break;
351                }
352
353                /* Handle escapes within the string */
354
355                if (*SubBuffer == '\\')
356                {
357                    SubBuffer++;
358                }
359
360                SubBuffer++;
361            }
362
363            SubBuffer++;
364            continue;
365        }
366
367        /* Now we can check for a slash-slash comment */
368
369        if ((*SubBuffer == '/') &&
370            (*(SubBuffer + 1) == '/'))
371        {
372            NonAnsiCommentCount++;
373
374            /* Skip to end-of-line */
375
376            while ((*SubBuffer != '\n') &&
377                (*SubBuffer))
378            {
379                SubBuffer++;
380            }
381
382            if (!(*SubBuffer))
383            {
384                break;
385            }
386
387            if (*SubBuffer == '\n')
388            {
389                TotalLines++;
390            }
391
392            SubBuffer++;
393            continue;
394        }
395
396        /* Finally, check for a newline */
397
398        if (*SubBuffer == '\n')
399        {
400            TotalLines++;
401            SubBuffer++;
402            continue;
403        }
404
405        /* Normal character, do the user actions */
406
407        if (Callback)
408        {
409            SubBuffer = Callback (SubBuffer, Filename, TotalLines);
410        }
411
412        if (TargetChar && (*SubBuffer == TargetChar))
413        {
414            return (SubBuffer);
415        }
416
417        SubBuffer++;
418    }
419
420    return (NULL);
421}
422
423
424/******************************************************************************
425 *
426 * FUNCTION:    AsRemoveExtraLines
427 *
428 * DESCRIPTION: Remove all extra lines at the start and end of the file.
429 *
430 ******************************************************************************/
431
432void
433AsRemoveExtraLines (
434    char                    *FileBuffer,
435    char                    *Filename)
436{
437    char                    *FileEnd;
438    int                     Length;
439
440
441    /* Remove any extra lines at the start of the file */
442
443    while (*FileBuffer == '\n')
444    {
445        printf ("Removing extra line at start of file: %s\n", Filename);
446        AsRemoveData (FileBuffer, FileBuffer + 1);
447    }
448
449    /* Remove any extra lines at the end of the file */
450
451    Length = strlen (FileBuffer);
452    FileEnd = FileBuffer + (Length - 2);
453
454    while (*FileEnd == '\n')
455    {
456        printf ("Removing extra line at end of file: %s\n", Filename);
457        AsRemoveData (FileEnd, FileEnd + 1);
458        FileEnd--;
459    }
460}
461
462
463/******************************************************************************
464 *
465 * FUNCTION:    AsRemoveSpacesAfterPeriod
466 *
467 * DESCRIPTION: Remove an extra space after a period.
468 *
469 ******************************************************************************/
470
471void
472AsRemoveSpacesAfterPeriod (
473    char                    *FileBuffer,
474    char                    *Filename)
475{
476    int                     ReplaceCount = 0;
477    char                    *Possible;
478
479
480    Possible = FileBuffer;
481    while (Possible)
482    {
483        Possible = strstr (Possible, ".  ");
484        if (Possible)
485        {
486            if ((*(Possible -1) == '.')  ||
487                (*(Possible -1) == '\"') ||
488                (*(Possible -1) == '\n'))
489            {
490                Possible += 3;
491                continue;
492            }
493
494            Possible = AsReplaceData (Possible, 3, ". ", 2);
495            ReplaceCount++;
496        }
497    }
498
499    if (ReplaceCount)
500    {
501        printf ("Removed %d extra blanks after a period: %s\n",
502            ReplaceCount, Filename);
503    }
504}
505
506
507/******************************************************************************
508 *
509 * FUNCTION:    AsMatchExactWord
510 *
511 * DESCRIPTION: Check previous and next characters for whitespace
512 *
513 ******************************************************************************/
514
515BOOLEAN
516AsMatchExactWord (
517    char                    *Word,
518    UINT32                  WordLength)
519{
520    char                    NextChar;
521    char                    PrevChar;
522
523
524    NextChar = Word[WordLength];
525    PrevChar = * (Word -1);
526
527    if (isalnum ((int) NextChar) ||
528        (NextChar == '_')  ||
529        isalnum ((int) PrevChar) ||
530        (PrevChar == '_'))
531    {
532        return (FALSE);
533    }
534
535    return (TRUE);
536}
537
538
539/******************************************************************************
540 *
541 * FUNCTION:    AsPrint
542 *
543 * DESCRIPTION: Common formatted print
544 *
545 ******************************************************************************/
546
547void
548AsPrint (
549    char                    *Message,
550    UINT32                  Count,
551    char                    *Filename)
552{
553
554    if (Gbl_QuietMode)
555    {
556        return;
557    }
558
559    printf ("-- %4u %28.28s : %s\n", Count, Message, Filename);
560}
561
562
563/******************************************************************************
564 *
565 * FUNCTION:    AsTrimLines
566 *
567 * DESCRIPTION: Remove extra blanks from the end of source lines. Does not
568 *              check for tabs.
569 *
570 ******************************************************************************/
571
572void
573AsTrimLines (
574    char                    *Buffer,
575    char                    *Filename)
576{
577    char                    *SubBuffer = Buffer;
578    char                    *StartWhiteSpace = NULL;
579    UINT32                  SpaceCount = 0;
580
581
582    while (*SubBuffer)
583    {
584        while (*SubBuffer != '\n')
585        {
586            if (!*SubBuffer)
587            {
588                goto Exit;
589            }
590
591            if (*SubBuffer == ' ')
592            {
593                if (!StartWhiteSpace)
594                {
595                    StartWhiteSpace = SubBuffer;
596                }
597            }
598            else
599            {
600                StartWhiteSpace = NULL;
601            }
602
603            SubBuffer++;
604        }
605
606        if (StartWhiteSpace)
607        {
608            SpaceCount += (SubBuffer - StartWhiteSpace);
609
610            /* Remove the spaces */
611
612            SubBuffer = AsRemoveData (StartWhiteSpace, SubBuffer);
613            StartWhiteSpace = NULL;
614        }
615
616        SubBuffer++;
617    }
618
619
620Exit:
621    if (SpaceCount)
622    {
623        Gbl_MadeChanges = TRUE;
624        AsPrint ("Extraneous spaces removed", SpaceCount, Filename);
625    }
626}
627
628
629/******************************************************************************
630 *
631 * FUNCTION:    AsTrimWhitespace
632 *
633 * DESCRIPTION: Remove "excess" blank lines - any more than 2 blank lines.
634 *              this can happen during the translation when lines are removed.
635 *
636 ******************************************************************************/
637
638void
639AsTrimWhitespace (
640    char                    *Buffer)
641{
642    char                    *SubBuffer;
643    int                     ReplaceCount = 1;
644
645
646    while (ReplaceCount)
647    {
648        ReplaceCount = AsReplaceString ("\n\n\n\n", "\n\n\n",
649            REPLACE_SUBSTRINGS, Buffer);
650    }
651
652    /*
653     * Check for exactly one blank line after the copyright header
654     */
655
656    /* Find the header */
657
658    SubBuffer = strstr (Buffer, HeaderBegin);
659    if (!SubBuffer)
660    {
661        return;
662    }
663
664    /* Find the end of the header */
665
666    SubBuffer = strstr (SubBuffer, "*/");
667    SubBuffer = AsSkipPastChar (SubBuffer, '\n');
668
669    /* Replace a double blank line with a single */
670
671    if (!strncmp (SubBuffer, "\n\n", 2))
672    {
673        AsReplaceData (SubBuffer, 2, "\n", 1);
674        AcpiOsPrintf ("Found multiple blank lines after copyright\n");
675    }
676
677    /* If no blank line after header, insert one */
678
679    else if (*SubBuffer != '\n')
680    {
681        AsInsertData (SubBuffer, "\n", 1);
682        AcpiOsPrintf ("Inserted blank line after copyright\n");
683    }
684}
685
686
687/******************************************************************************
688 *
689 * FUNCTION:    AsReplaceHeader
690 *
691 * DESCRIPTION: Replace the default Intel legal header with a new header
692 *
693 ******************************************************************************/
694
695void
696AsReplaceHeader (
697    char                    *Buffer,
698    char                    *NewHeader)
699{
700    char                    *SubBuffer;
701    char                    *TokenEnd;
702
703
704    /* Find the original header */
705
706    SubBuffer = strstr (Buffer, HeaderBegin);
707    if (!SubBuffer)
708    {
709        return;
710    }
711
712    /* Find the end of the original header */
713
714    TokenEnd = strstr (SubBuffer, "*/");
715    TokenEnd = AsSkipPastChar (TokenEnd, '\n');
716
717    /* Delete old header, insert new one */
718
719    AsReplaceData (SubBuffer, TokenEnd - SubBuffer,
720        NewHeader, strlen (NewHeader));
721}
722
723
724/******************************************************************************
725 *
726 * FUNCTION:    AsReplaceString
727 *
728 * DESCRIPTION: Replace all instances of a target string with a replacement
729 *              string. Returns count of the strings replaced.
730 *
731 ******************************************************************************/
732
733int
734AsReplaceString (
735    char                    *Target,
736    char                    *Replacement,
737    UINT8                   Type,
738    char                    *Buffer)
739{
740    char                    *SubString1;
741    char                    *SubString2;
742    char                    *SubBuffer;
743    int                     TargetLength;
744    int                     ReplacementLength;
745    int                     ReplaceCount = 0;
746
747
748    TargetLength = strlen (Target);
749    ReplacementLength = strlen (Replacement);
750
751    SubBuffer = Buffer;
752    SubString1 = Buffer;
753
754    while (SubString1)
755    {
756        /* Find the target string */
757
758        SubString1 = strstr (SubBuffer, Target);
759        if (!SubString1)
760        {
761            return (ReplaceCount);
762        }
763
764        /*
765         * Check for translation escape string -- means to ignore
766         * blocks of code while replacing
767         */
768        if (Gbl_IgnoreTranslationEscapes)
769        {
770            SubString2 = NULL;
771        }
772        else
773        {
774            SubString2 = strstr (SubBuffer, AS_START_IGNORE);
775        }
776
777        if ((SubString2) &&
778            (SubString2 < SubString1))
779        {
780            /* Find end of the escape block starting at "Substring2" */
781
782            SubString2 = strstr (SubString2, AS_STOP_IGNORE);
783            if (!SubString2)
784            {
785                /* Didn't find terminator */
786
787                return (ReplaceCount);
788            }
789
790            /* Move buffer to end of escape block and continue */
791
792            SubBuffer = SubString2;
793        }
794
795        /* Do the actual replace if the target was found */
796
797        else
798        {
799            if ((Type & REPLACE_MASK) == REPLACE_WHOLE_WORD)
800            {
801                if (!AsMatchExactWord (SubString1, TargetLength))
802                {
803                    SubBuffer = SubString1 + 1;
804                    continue;
805                }
806            }
807
808            SubBuffer = AsReplaceData (SubString1, TargetLength,
809                Replacement, ReplacementLength);
810
811            if ((Type & EXTRA_INDENT_C) &&
812                (!Gbl_StructDefs))
813            {
814                SubBuffer = AsInsertData (SubBuffer, "        ", 8);
815            }
816
817            ReplaceCount++;
818        }
819    }
820
821    return (ReplaceCount);
822}
823
824
825/******************************************************************************
826 *
827 * FUNCTION:    AsConvertToLineFeeds
828 *
829 * DESCRIPTION: Convert all CR/LF pairs to LF only.
830 *
831 ******************************************************************************/
832
833void
834AsConvertToLineFeeds (
835    char                    *Buffer)
836{
837    char                    *SubString;
838    char                    *SubBuffer;
839
840
841    SubBuffer = Buffer;
842    SubString = Buffer;
843
844    while (SubString)
845    {
846        /* Find the target string */
847
848        SubString = strstr (SubBuffer, "\r\n");
849        if (!SubString)
850        {
851            return;
852        }
853
854        SubBuffer = AsReplaceData (SubString, 1, NULL, 0);
855    }
856}
857
858
859/******************************************************************************
860 *
861 * FUNCTION:    AsInsertCarriageReturns
862 *
863 * DESCRIPTION: Convert lone LFs to CR/LF pairs.
864 *
865 ******************************************************************************/
866
867void
868AsInsertCarriageReturns (
869    char                    *Buffer)
870{
871    char                    *SubString;
872    char                    *SubBuffer;
873
874
875    SubBuffer = Buffer;
876    SubString = Buffer;
877
878    while (SubString)
879    {
880        /* Find the target string */
881
882        SubString = strstr (SubBuffer, "\n");
883        if (!SubString)
884        {
885            return;
886        }
887
888        SubBuffer = AsInsertData (SubString, "\r", 1);
889        SubBuffer += 1;
890    }
891}
892
893
894/******************************************************************************
895 *
896 * FUNCTION:    AsBracesOnSameLine
897 *
898 * DESCRIPTION: Move opening braces up to the same line as an if, for, else,
899 *              or while statement (leave function opening brace on separate
900 *              line).
901 *
902 ******************************************************************************/
903
904void
905AsBracesOnSameLine (
906    char                    *Buffer)
907{
908    char                    *SubBuffer = Buffer;
909    char                    *Beginning;
910    char                    *StartOfThisLine;
911    char                    *Next;
912    BOOLEAN                 BlockBegin = TRUE;
913
914
915    while (*SubBuffer)
916    {
917        /* Ignore comments */
918
919        if ((SubBuffer[0] == '/') &&
920            (SubBuffer[1] == '*'))
921        {
922            SubBuffer = strstr (SubBuffer, "*/");
923            if (!SubBuffer)
924            {
925                return;
926            }
927
928            SubBuffer += 2;
929            continue;
930        }
931
932        /* Ignore quoted strings */
933
934        if (*SubBuffer == '\"')
935        {
936            SubBuffer++;
937            SubBuffer = AsSkipPastChar (SubBuffer, '\"');
938            if (!SubBuffer)
939            {
940                return;
941            }
942        }
943
944        if (!strncmp ("\n}", SubBuffer, 2))
945        {
946            /*
947             * A newline followed by a closing brace closes a function
948             * or struct or initializer block
949             */
950            BlockBegin = TRUE;
951        }
952
953        /*
954         * Move every standalone brace up to the previous line
955         * Check for digit will ignore initializer lists surrounded by braces.
956         * This will work until we we need more complex detection.
957         */
958        if ((*SubBuffer == '{') && !isdigit ((int) SubBuffer[1]))
959        {
960            if (BlockBegin)
961            {
962                BlockBegin = FALSE;
963            }
964            else
965            {
966                /*
967                 * Backup to previous non-whitespace
968                 */
969                Beginning = SubBuffer - 1;
970                while ((*Beginning == ' ')   ||
971                       (*Beginning == '\n'))
972                {
973                    Beginning--;
974                }
975
976                StartOfThisLine = Beginning;
977                while (*StartOfThisLine != '\n')
978                {
979                    StartOfThisLine--;
980                }
981
982                /*
983                 * Move the brace up to the previous line, UNLESS:
984                 *
985                 * 1) There is a conditional compile on the line (starts with '#')
986                 * 2) Previous line ends with an '=' (Start of initializer block)
987                 * 3) Previous line ends with a comma (part of an init list)
988                 * 4) Previous line ends with a backslash (part of a macro)
989                 */
990                if ((StartOfThisLine[1] != '#') &&
991                    (*Beginning != '\\') &&
992                    (*Beginning != '/') &&
993                    (*Beginning != '{') &&
994                    (*Beginning != '=') &&
995                    (*Beginning != ','))
996                {
997                    Beginning++;
998                    SubBuffer++;
999
1000                    Gbl_MadeChanges = TRUE;
1001
1002#ifdef ADD_EXTRA_WHITESPACE
1003                    AsReplaceData (Beginning, SubBuffer - Beginning, " {\n", 3);
1004#else
1005                    /* Find non-whitespace start of next line */
1006
1007                    Next = SubBuffer + 1;
1008                    while ((*Next == ' ')   ||
1009                           (*Next == '\t'))
1010                    {
1011                        Next++;
1012                    }
1013
1014                    /* Find non-whitespace start of this line */
1015
1016                    StartOfThisLine++;
1017                    while ((*StartOfThisLine == ' ')   ||
1018                           (*StartOfThisLine == '\t'))
1019                    {
1020                        StartOfThisLine++;
1021                    }
1022
1023                    /*
1024                     * Must be a single-line comment to need more whitespace
1025                     * Even then, we don't need more if the previous statement
1026                     * is an "else".
1027                     */
1028                    if ((Next[0] == '/')  &&
1029                        (Next[1] == '*')  &&
1030                        (Next[2] != '\n') &&
1031
1032                        (!strncmp (StartOfThisLine, "else if", 7)     ||
1033                         !strncmp (StartOfThisLine, "else while", 10) ||
1034                          strncmp (StartOfThisLine, "else", 4)))
1035                    {
1036                        AsReplaceData (Beginning, SubBuffer - Beginning, " {\n", 3);
1037                    }
1038                    else
1039                    {
1040                        AsReplaceData (Beginning, SubBuffer - Beginning, " {", 2);
1041                    }
1042#endif
1043                }
1044            }
1045        }
1046
1047        SubBuffer++;
1048    }
1049}
1050
1051
1052/******************************************************************************
1053 *
1054 * FUNCTION:    AsTabify4
1055 *
1056 * DESCRIPTION: Convert the text to tabbed text. Alignment of text is
1057 *              preserved.
1058 *
1059 ******************************************************************************/
1060
1061void
1062AsTabify4 (
1063    char                    *Buffer)
1064{
1065    char                    *SubBuffer = Buffer;
1066    char                    *NewSubBuffer;
1067    UINT32                  SpaceCount = 0;
1068    UINT32                  Column = 0;
1069
1070
1071    while (*SubBuffer)
1072    {
1073        if (*SubBuffer == '\n')
1074        {
1075            Column = 0;
1076        }
1077        else
1078        {
1079            Column++;
1080        }
1081
1082        /* Ignore comments */
1083
1084        if ((SubBuffer[0] == '/') &&
1085            (SubBuffer[1] == '*'))
1086        {
1087            SubBuffer = strstr (SubBuffer, "*/");
1088            if (!SubBuffer)
1089            {
1090                return;
1091            }
1092
1093            SubBuffer += 2;
1094            continue;
1095        }
1096
1097        /* Ignore quoted strings */
1098
1099        if (*SubBuffer == '\"')
1100        {
1101            SubBuffer++;
1102            SubBuffer = AsSkipPastChar (SubBuffer, '\"');
1103            if (!SubBuffer)
1104            {
1105                return;
1106            }
1107            SpaceCount = 0;
1108        }
1109
1110        if (*SubBuffer == ' ')
1111        {
1112            SpaceCount++;
1113
1114            if (SpaceCount >= 4)
1115            {
1116                SpaceCount = 0;
1117
1118                NewSubBuffer = (SubBuffer + 1) - 4;
1119                *NewSubBuffer = '\t';
1120                NewSubBuffer++;
1121
1122                /* Remove the spaces */
1123
1124                SubBuffer = AsRemoveData (NewSubBuffer, SubBuffer + 1);
1125            }
1126
1127            if ((Column % 4) == 0)
1128            {
1129                SpaceCount = 0;
1130            }
1131        }
1132        else
1133        {
1134            SpaceCount = 0;
1135        }
1136
1137        SubBuffer++;
1138    }
1139}
1140
1141
1142/******************************************************************************
1143 *
1144 * FUNCTION:    AsTabify8
1145 *
1146 * DESCRIPTION: Convert the text to tabbed text. Alignment of text is
1147 *              preserved.
1148 *
1149 ******************************************************************************/
1150
1151void
1152AsTabify8 (
1153    char                    *Buffer)
1154{
1155    char                    *SubBuffer = Buffer;
1156    char                    *NewSubBuffer;
1157    char                    *CommentEnd = NULL;
1158    UINT32                  SpaceCount = 0;
1159    UINT32                  Column = 0;
1160    UINT32                  TabCount = 0;
1161    UINT32                  LastLineTabCount = 0;
1162    UINT32                  LastLineColumnStart = 0;
1163    UINT32                  ThisColumnStart = 0;
1164    UINT32                  ThisTabCount =  0;
1165    char                    *FirstNonBlank = NULL;
1166
1167
1168    while (*SubBuffer)
1169    {
1170        if (*SubBuffer == '\n')
1171        {
1172            /* This is a standalone blank line */
1173
1174            FirstNonBlank = NULL;
1175            Column = 0;
1176            SpaceCount = 0;
1177            TabCount = 0;
1178            SubBuffer++;
1179            continue;
1180        }
1181
1182        if (!FirstNonBlank)
1183        {
1184            /* Find the first non-blank character on this line */
1185
1186            FirstNonBlank = SubBuffer;
1187            while (*FirstNonBlank == ' ')
1188            {
1189                FirstNonBlank++;
1190            }
1191
1192            /*
1193             * This mechanism limits the difference in tab counts from
1194             * line to line. It helps avoid the situation where a second
1195             * continuation line (which was indented correctly for tabs=4) would
1196             * get indented off the screen if we just blindly converted to tabs.
1197             */
1198            ThisColumnStart = FirstNonBlank - SubBuffer;
1199
1200            if (LastLineTabCount == 0)
1201            {
1202                ThisTabCount = 0;
1203            }
1204            else if (ThisColumnStart == LastLineColumnStart)
1205            {
1206                ThisTabCount = LastLineTabCount -1;
1207            }
1208            else
1209            {
1210                ThisTabCount = LastLineTabCount + 1;
1211            }
1212        }
1213
1214        Column++;
1215
1216        /* Check if we are in a comment */
1217
1218        if ((SubBuffer[0] == '*') &&
1219            (SubBuffer[1] == '/'))
1220        {
1221            SpaceCount = 0;
1222            SubBuffer += 2;
1223
1224            if (*SubBuffer == '\n')
1225            {
1226                if (TabCount > 0)
1227                {
1228                    LastLineTabCount = TabCount;
1229                    TabCount = 0;
1230                }
1231
1232                FirstNonBlank = NULL;
1233                LastLineColumnStart = ThisColumnStart;
1234                SubBuffer++;
1235            }
1236
1237            continue;
1238        }
1239
1240        /* Check for comment open */
1241
1242        if ((SubBuffer[0] == '/') &&
1243            (SubBuffer[1] == '*'))
1244        {
1245            /* Find the end of the comment, it must exist */
1246
1247            CommentEnd = strstr (SubBuffer, "*/");
1248            if (!CommentEnd)
1249            {
1250                return;
1251            }
1252
1253            /* Toss the rest of this line or single-line comment */
1254
1255            while ((SubBuffer < CommentEnd) &&
1256                   (*SubBuffer != '\n'))
1257            {
1258                SubBuffer++;
1259            }
1260
1261            if (*SubBuffer == '\n')
1262            {
1263                if (TabCount > 0)
1264                {
1265                    LastLineTabCount = TabCount;
1266                    TabCount = 0;
1267                }
1268
1269                FirstNonBlank = NULL;
1270                LastLineColumnStart = ThisColumnStart;
1271            }
1272
1273            SpaceCount = 0;
1274            continue;
1275        }
1276
1277        /* Ignore quoted strings */
1278
1279        if ((!CommentEnd) && (*SubBuffer == '\"'))
1280        {
1281            SubBuffer++;
1282            SubBuffer = AsSkipPastChar (SubBuffer, '\"');
1283            if (!SubBuffer)
1284            {
1285                return;
1286            }
1287
1288            SpaceCount = 0;
1289        }
1290
1291        if (*SubBuffer != ' ')
1292        {
1293            /* Not a space, skip to end of line */
1294
1295            SubBuffer = AsSkipUntilChar (SubBuffer, '\n');
1296            if (!SubBuffer)
1297            {
1298                return;
1299            }
1300            if (TabCount > 0)
1301            {
1302                LastLineTabCount = TabCount;
1303                TabCount = 0;
1304            }
1305
1306            FirstNonBlank = NULL;
1307            LastLineColumnStart = ThisColumnStart;
1308            Column = 0;
1309            SpaceCount = 0;
1310        }
1311        else
1312        {
1313            /* Another space */
1314
1315            SpaceCount++;
1316
1317            if (SpaceCount >= 4)
1318            {
1319                /* Replace this group of spaces with a tab character */
1320
1321                SpaceCount = 0;
1322
1323                NewSubBuffer = SubBuffer - 3;
1324
1325                if (TabCount <= ThisTabCount ? (ThisTabCount +1) : 0)
1326                {
1327                    *NewSubBuffer = '\t';
1328                    NewSubBuffer++;
1329                    SubBuffer++;
1330                    TabCount++;
1331                }
1332
1333                /* Remove the spaces */
1334
1335                SubBuffer = AsRemoveData (NewSubBuffer, SubBuffer);
1336                continue;
1337            }
1338        }
1339
1340        SubBuffer++;
1341    }
1342}
1343
1344
1345/******************************************************************************
1346 *
1347 * FUNCTION:    AsCountLines
1348 *
1349 * DESCRIPTION: Count the number of lines in the input buffer. Also count
1350 *              the number of long lines (lines longer than 80 chars).
1351 *
1352 ******************************************************************************/
1353
1354static UINT32
1355AsCountLines (
1356    char                    *Buffer,
1357    char                    *Filename)
1358{
1359    char                    *SubBuffer = Buffer;
1360    char                    *EndOfLine;
1361    UINT32                  LineCount = 0;
1362    UINT32                  LongLineCount = 0;
1363
1364
1365    while (*SubBuffer)
1366    {
1367        EndOfLine = AsSkipUntilChar (SubBuffer, '\n');
1368        if (!EndOfLine)
1369        {
1370            Gbl_TotalLines += LineCount;
1371            return (LineCount);
1372        }
1373
1374        if ((EndOfLine - SubBuffer) > 80)
1375        {
1376            LongLineCount++;
1377            VERBOSE_PRINT (("long: %.80s\n", SubBuffer));
1378        }
1379
1380        LineCount++;
1381        SubBuffer = EndOfLine + 1;
1382    }
1383
1384    if (LongLineCount)
1385    {
1386        VERBOSE_PRINT (("%u Lines longer than 80 found in %s\n",
1387            LongLineCount, Filename));
1388
1389        Gbl_LongLines += LongLineCount;
1390    }
1391
1392    Gbl_TotalLines += LineCount;
1393    return (LineCount);
1394}
1395
1396
1397/******************************************************************************
1398 *
1399 * FUNCTION:    AsCountTabs
1400 *
1401 * DESCRIPTION: Simply count the number of tabs in the input file buffer
1402 *
1403 ******************************************************************************/
1404
1405void
1406AsCountTabs (
1407    char                    *Buffer,
1408    char                    *Filename)
1409{
1410    UINT32                  i;
1411    UINT32                  TabCount = 0;
1412
1413
1414    for (i = 0; Buffer[i]; i++)
1415    {
1416        if (Buffer[i] == '\t')
1417        {
1418            TabCount++;
1419        }
1420    }
1421
1422    if (TabCount)
1423    {
1424        AsPrint ("Tabs found", TabCount, Filename);
1425        Gbl_Tabs += TabCount;
1426    }
1427
1428    AsCountLines (Buffer, Filename);
1429}
1430
1431
1432/******************************************************************************
1433 *
1434 * FUNCTION:    AsCountSourceLines
1435 *
1436 * DESCRIPTION: Count the number of C source lines. Defined by 1) not a
1437 *              comment, and 2) not a blank line.
1438 *
1439 ******************************************************************************/
1440
1441void
1442AsCountSourceLines (
1443    char                    *Buffer,
1444    char                    *Filename)
1445{
1446    char                    *SubBuffer = Buffer;
1447    UINT32                  LineCount = 0;
1448    UINT32                  WhiteCount = 0;
1449    UINT32                  CommentCount = 0;
1450
1451
1452    while (*SubBuffer)
1453    {
1454        /* Detect comments (// comments are not used, non-ansii) */
1455
1456        if ((SubBuffer[0] == '/') &&
1457            (SubBuffer[1] == '*'))
1458        {
1459            SubBuffer += 2;
1460
1461            /* First line of multi-line comment is often just whitespace */
1462
1463            if (SubBuffer[0] == '\n')
1464            {
1465                WhiteCount++;
1466                SubBuffer++;
1467            }
1468            else
1469            {
1470                CommentCount++;
1471            }
1472
1473            /* Find end of comment */
1474
1475            while (SubBuffer[0] && SubBuffer[1] &&
1476                !(((SubBuffer[0] == '*') &&
1477                    (SubBuffer[1] == '/'))))
1478            {
1479                if (SubBuffer[0] == '\n')
1480                {
1481                    CommentCount++;
1482                }
1483
1484                SubBuffer++;
1485            }
1486        }
1487
1488        /* A linefeed followed by a non-linefeed is a valid source line */
1489
1490        else if ((SubBuffer[0] == '\n') &&
1491                 (SubBuffer[1] != '\n'))
1492        {
1493            LineCount++;
1494        }
1495
1496        /* Two back-to-back linefeeds indicate a whitespace line */
1497
1498        else if ((SubBuffer[0] == '\n') &&
1499                 (SubBuffer[1] == '\n'))
1500        {
1501            WhiteCount++;
1502        }
1503
1504        SubBuffer++;
1505    }
1506
1507    /* Adjust comment count for legal header */
1508
1509    if (Gbl_HeaderSize < CommentCount)
1510    {
1511        CommentCount -= Gbl_HeaderSize;
1512        Gbl_HeaderLines += Gbl_HeaderSize;
1513    }
1514
1515    Gbl_SourceLines += LineCount;
1516    Gbl_WhiteLines += WhiteCount;
1517    Gbl_CommentLines += CommentCount;
1518
1519    VERBOSE_PRINT (("%u Comment %u White %u Code %u Lines in %s\n",
1520        CommentCount, WhiteCount, LineCount,
1521        LineCount + WhiteCount + CommentCount, Filename));
1522}
1523
1524
1525/******************************************************************************
1526 *
1527 * FUNCTION:    AsInsertPrefix
1528 *
1529 * DESCRIPTION: Insert struct or union prefixes
1530 *
1531 ******************************************************************************/
1532
1533void
1534AsInsertPrefix (
1535    char                    *Buffer,
1536    char                    *Keyword,
1537    UINT8                   Type)
1538{
1539    char                    *SubString;
1540    char                    *SubBuffer;
1541    char                    *EndKeyword;
1542    int                     InsertLength;
1543    char                    *InsertString;
1544    int                     TrailingSpaces;
1545    char                    LowerKeyword[128];
1546    int                     KeywordLength;
1547
1548
1549    switch (Type)
1550    {
1551    case SRC_TYPE_STRUCT:
1552
1553        InsertString = "struct ";
1554        break;
1555
1556    case SRC_TYPE_UNION:
1557
1558        InsertString = "union ";
1559        break;
1560
1561    default:
1562
1563        return;
1564    }
1565
1566    strcpy (LowerKeyword, Keyword);
1567    AcpiUtStrlwr (LowerKeyword);
1568
1569    SubBuffer = Buffer;
1570    SubString = Buffer;
1571    InsertLength = strlen (InsertString);
1572    KeywordLength = strlen (Keyword);
1573
1574
1575    while (SubString)
1576    {
1577        /* Find an instance of the keyword */
1578
1579        SubString = strstr (SubBuffer, LowerKeyword);
1580        if (!SubString)
1581        {
1582            return;
1583        }
1584
1585        SubBuffer = SubString;
1586
1587        /* Must be standalone word, not a substring */
1588
1589        if (AsMatchExactWord (SubString, KeywordLength))
1590        {
1591            /* Make sure the keyword isn't already prefixed with the insert */
1592
1593            if (!strncmp (SubString - InsertLength, InsertString, InsertLength))
1594            {
1595                /* Add spaces if not already at the end-of-line */
1596
1597                if (*(SubBuffer + KeywordLength) != '\n')
1598                {
1599                    /* Already present, add spaces after to align structure members */
1600
1601#if 0
1602/* ONLY FOR C FILES */
1603                    AsInsertData (SubBuffer + KeywordLength, "        ", 8);
1604#endif
1605                }
1606                goto Next;
1607            }
1608
1609            /* Make sure the keyword isn't at the end of a struct/union */
1610            /* Note: This code depends on a single space after the brace */
1611
1612            if (*(SubString - 2) == '}')
1613            {
1614                goto Next;
1615            }
1616
1617            /* Prefix the keyword with the insert string */
1618
1619            Gbl_MadeChanges = TRUE;
1620
1621            /* Is there room for insertion */
1622
1623            EndKeyword = SubString + strlen (LowerKeyword);
1624
1625            TrailingSpaces = 0;
1626            while (EndKeyword[TrailingSpaces] == ' ')
1627            {
1628                TrailingSpaces++;
1629            }
1630
1631            /*
1632             * Use "if (TrailingSpaces > 1)" if we want to ignore casts
1633             */
1634            SubBuffer = SubString + InsertLength;
1635
1636            if (TrailingSpaces > InsertLength)
1637            {
1638                /* Insert the keyword */
1639
1640                memmove (SubBuffer, SubString, KeywordLength);
1641
1642                /* Insert the keyword */
1643
1644                memmove (SubString, InsertString, InsertLength);
1645            }
1646            else
1647            {
1648                AsInsertData (SubString, InsertString, InsertLength);
1649            }
1650        }
1651
1652Next:
1653        SubBuffer += KeywordLength;
1654    }
1655}
1656
1657#ifdef ACPI_FUTURE_IMPLEMENTATION
1658/******************************************************************************
1659 *
1660 * FUNCTION:    AsTrimComments
1661 *
1662 * DESCRIPTION: Finds 3-line comments with only a single line of text
1663 *
1664 ******************************************************************************/
1665
1666void
1667AsTrimComments (
1668    char                    *Buffer,
1669    char                    *Filename)
1670{
1671    char                    *SubBuffer = Buffer;
1672    char                    *Ptr1;
1673    char                    *Ptr2;
1674    UINT32                  LineCount;
1675    UINT32                  ShortCommentCount = 0;
1676
1677
1678    while (1)
1679    {
1680        /* Find comment open, within procedure level */
1681
1682        SubBuffer = strstr (SubBuffer, "    /*");
1683        if (!SubBuffer)
1684        {
1685            goto Exit;
1686        }
1687
1688        /* Find comment terminator */
1689
1690        Ptr1 = strstr (SubBuffer, "*/");
1691        if (!Ptr1)
1692        {
1693            goto Exit;
1694        }
1695
1696        /* Find next EOL (from original buffer) */
1697
1698        Ptr2 = strstr (SubBuffer, "\n");
1699        if (!Ptr2)
1700        {
1701            goto Exit;
1702        }
1703
1704        /* Ignore one-line comments */
1705
1706        if (Ptr1 < Ptr2)
1707        {
1708            /* Normal comment, ignore and continue; */
1709
1710            SubBuffer = Ptr2;
1711            continue;
1712        }
1713
1714        /* Examine multi-line comment */
1715
1716        LineCount = 1;
1717        while (Ptr1 > Ptr2)
1718        {
1719            /* Find next EOL */
1720
1721            Ptr2++;
1722            Ptr2 = strstr (Ptr2, "\n");
1723            if (!Ptr2)
1724            {
1725                goto Exit;
1726            }
1727
1728            LineCount++;
1729        }
1730
1731        SubBuffer = Ptr1;
1732
1733        if (LineCount <= 3)
1734        {
1735            ShortCommentCount++;
1736        }
1737    }
1738
1739
1740Exit:
1741
1742    if (ShortCommentCount)
1743    {
1744        AsPrint ("Short Comments found", ShortCommentCount, Filename);
1745    }
1746}
1747#endif
1748
1749#ifdef ACPI_UNUSED_FUNCTIONS
1750/******************************************************************************
1751 *
1752 * FUNCTION:    AsCheckAndSkipLiterals
1753 *
1754 * DESCRIPTION: Generic routine to skip comments and quoted string literals.
1755 *              Keeps a line count.
1756 *
1757 ******************************************************************************/
1758
1759static char *
1760AsCheckAndSkipLiterals (
1761    char                    *Buffer,
1762    UINT32                  *TotalLines);
1763
1764
1765static char *
1766AsCheckAndSkipLiterals (
1767    char                    *Buffer,
1768    UINT32                  *TotalLines)
1769{
1770    UINT32                  NewLines = 0;
1771    char                    *SubBuffer = Buffer;
1772    char                    *LiteralEnd;
1773
1774
1775    /* Ignore comments */
1776
1777    if ((SubBuffer[0] == '/') &&
1778        (SubBuffer[1] == '*'))
1779    {
1780        LiteralEnd = strstr (SubBuffer, "*/");
1781        SubBuffer += 2;     /* Get past comment opening */
1782
1783        if (!LiteralEnd)
1784        {
1785            return (SubBuffer);
1786        }
1787
1788        while (SubBuffer < LiteralEnd)
1789        {
1790            if (*SubBuffer == '\n')
1791            {
1792                NewLines++;
1793            }
1794
1795            SubBuffer++;
1796        }
1797
1798        SubBuffer += 2;     /* Get past comment close */
1799    }
1800
1801    /* Ignore quoted strings */
1802
1803    else if (*SubBuffer == '\"')
1804    {
1805        SubBuffer++;
1806        LiteralEnd = AsSkipPastChar (SubBuffer, '\"');
1807        if (!LiteralEnd)
1808        {
1809            return (SubBuffer);
1810        }
1811    }
1812
1813    if (TotalLines)
1814    {
1815        (*TotalLines) += NewLines;
1816    }
1817    return (SubBuffer);
1818}
1819#endif
1820