Changeset 206

Show
Ignore:
Timestamp:
09/01/07 21:22:03 (1 year ago)
Author:
smjg
Message:

Replaced an ancient version of dfilter

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/dfilter.d

    r16 r206  
    1 // dfilter.d - modifications by James Dunne 
    2 // original author unknown/forgotten by me (feel free to give credit) 
    3  
    4 // These modifications allow version (identifier) { } else { } blocks 
    5 // to be replaced with corresponding C preprocessor #ifdef blocks which 
    6 // doxygen recognizes and interprets.  The identifiers are translated into 
    7 // all uppercase with a VERSION_ prefix.  An example should illustrate: 
    8  
    9 // version (server) { 
    10 //   code1 
    11 // } else version (client) { 
    12 //   code2 
    13 // } else { 
    14 //   code3 
    15 // } 
    16  
    17 // becomes: 
    18  
    19 // #ifdef VERSION_SERVER 
    20 //   code1 
    21 // #elif VERSION_CLIENT 
    22 //   code2 
    23 // #else 
    24 //   code3 
    25 // #endif 
    26  
    27 // Modifications have also been made to support D interfaces conversion 
    28 // into C++ classes. 
    29  
    30 import std.file, std.ctype, std.c.stdio, std.string; 
    31  
    32 char [] data; /* Data. */ 
    33 char *c; /* Current point. */ 
    34 char *s; /* Previous filter point. */ 
    35 char *e; /* End of the data. */ 
    36 char *p; /* Start of this token. */ 
    37  
    38 /* Read in a token. */ 
    39 char [] token () 
    40 
     1/***********************************************************************\ 
     2*                               dfilter.d                               * 
     3*                                                                       * 
     4*                    D code filter for Doxygen 1.4.2                    * 
     5*                                                                       * 
     6*     Portions written by Hauke Duden, Stewart Gordon, James Dunne,     * 
     7*                 probably various anonymous authors....                * 
     8\***********************************************************************/ 
     9import std.file, std.ctype, std.string, std.c.stdio, std.stdio, std.cstream; 
     10 
     11char[] data;    // Program code 
     12char* current;  // Current point 
     13char* previous; // Previous filter point 
     14char* end;      // End of the data 
     15char* ptoken;   // Start of this token 
     16 
     17// Read in a token 
     18char[] token() { 
    4119restart: 
    42     p = c
    43  
    44     if (c >= e
     20    ptoken = current
     21 
     22    if (current >= end
    4523        return null; 
    4624 
    47     if (isalpha (*c) || *c == '_') 
    48     { 
    49         for (c ++; c < e; c ++) 
    50             if (!isalnum (*c) && *c != '_') 
     25    if (isalpha(*current) || *current == '_') { 
     26        for (current++; current < end; current++) 
     27            if (!isalnum(*current) && *current != '_') 
    5128                break; 
    5229 
    53         return p [0 .. cast(int)(c - p)]; 
    54     } 
    55  
    56     if (*c == ' ' || *c == '\r' || *c == '\n' || *c == '\t') 
    57    
    58         c ++; 
     30        return ptoken[0 .. cast(int) (current - ptoken)]; 
     31    } 
     32 
     33    if (*current == ' ' || *current == '\r' || *current == '\n' 
     34         || *current == '\t')
     35        current++; 
    5936        goto restart; 
    6037    } 
    6138 
    62     if (*c == '"') 
    63     { 
    64         for (c ++; c < e; c ++) 
    65             if (*c == '\\') 
    66                 c ++; 
    67             else if (*c == '"') 
    68             { 
    69                 c ++; 
     39    if (*current == '"') { 
     40        for (current++; current < end; current++) 
     41            if (*current == '\\') { 
     42                current++; 
     43            } else if (*current == '"') { 
     44                current++; 
    7045                break; 
    7146            } 
     
    7348    } 
    7449 
    75     if (*c == '\'') 
    76     { 
    77         for (c ++; c < e; c ++) 
    78             if (*c == '\'') 
    79            
    80                 c ++; 
     50    if (*current == '\'') { 
     51       for (current++; current < end; current++) 
     52           if (*current == '\\') { 
     53               current++; 
     54            } else if (*current == '\'')
     55                current++; 
    8156                break; 
    8257            } 
     
    8459    } 
    8560 
    86     if (c < e - 1) 
    87     { 
    88         if (*c == '/' && c [1] == '/') 
    89         { 
    90             for (c += 2; ; c ++) 
    91                 if (c >= e || *c == '\n') 
    92                 { 
    93                     c ++; 
     61    if (current < end - 1) { 
     62        if (current[0..2] == "//") { 
     63            for (current += 2; ; current++) 
     64                if (current >= end || *current == '\n') { 
     65                    current++; 
    9466                    goto restart; 
    9567                } 
    9668        } 
    97          
    98         if (*c == '/' && c [1] == '*') 
    99         { 
    100             for (c += 2; ; c ++) 
    101                 if (c >= e - 1 || (*c == '*' && c [1] == '/')) 
    102                 { 
    103                     c += 2; 
     69 
     70        if (current[0..2] == "/*") { 
     71            for (current += 2; ; current++) 
     72                if (current >= end - 1 
     73                      || (current[0..2] == "*/")) { 
     74                    current += 2; 
    10475                    goto restart; 
    10576                } 
    10677        } 
    10778 
    108         if (*c == '/' && c [1] == '+') 
    109         { 
     79        if (current[0..2] == "/+") { 
     80           char* commentStart = current; 
    11081            int depth = 1; 
    11182 
    112             for (c += 2; ; c ++) 
    113                 if (c >= e - 1) 
    114                     goto restart; 
    115                 else if (*c == '/' && c [1] == '+') 
    116                 { 
    117                     c += 2; 
    118                     depth ++; 
    119                 } 
    120                 else if (*c == '+' && c [1] == '/') 
    121                 { 
    122                     c += 2; 
    123                     depth --; 
    124                     if (!depth) 
     83            for (current += 2; ; current++) { 
     84                if (current >= end - 1) { 
     85                    throw new Error("Unterminated /+...+/ comment"); 
     86                } else if (current[0..2] == "/+") { 
     87                    current++; 
     88                    depth++; 
     89                } else if (current[0..2] == "+/") { 
     90                    current++; 
     91                    depth--; 
     92                    if (!depth) { 
     93                        /*  remove comment 
     94                         *  can be kept once Doxygen understands them 
     95                         */ 
     96                        commentStart[0..end-current] 
     97                          = current[0..end-current].dup; 
     98                        end -= current - commentStart; 
     99                        current = commentStart; 
     100                        current[0] = ' '; 
    125101                        goto restart; 
    126                 } 
     102                    } 
     103                } 
     104            } 
    127105        } 
    128106    } 
    129107 
    130     c ++; 
    131     return p [0 .. 1]; 
    132 
    133  
    134 /* Print all text to this point and set s to the current point. */ 
    135 void flush (char *p) 
    136 
    137     fwrite (s, cast(int)(p - s), 1, stdout); 
    138     s = c; 
    139 
    140  
    141 /* Consume a "{ ... }" or "(xxx) { ... }" block. */ 
    142 void skipBlock (char *p) 
    143 
    144     char *o = s; 
    145  
    146     flush (p); 
     108    current++; 
     109    return ptoken[0..1]; 
     110
     111 
     112// Print all text to this point, and set previous to the current point 
     113void flush(char* p) { 
     114    std.c.stdio.fwrite(previous, cast(int) (p - previous), 1, stdout); 
     115    previous = current; 
     116
     117 
     118// Print all text to a set point, which becomes the new previous point 
     119void flushTo(char* p) { 
     120    std.c.stdio.fwrite(previous, cast(int) (p - previous), 1, stdout); 
     121    previous = p; 
     122
     123 
     124// Consume a "{ ... }" or "(xxx) { ... }" block 
     125void skipBlock(char* p) { 
     126    char* o = previous; 
     127 
     128    flush(p); 
    147129 
    148130    int depth = 0; 
    149     char [] t = token (); 
    150  
    151     if (t == "(") 
    152     { 
    153         while (1) 
    154         { 
    155             t = token (); 
     131    char[] t = token(); 
     132 
     133    if (t == "(") { 
     134        while (1) { 
     135            t = token(); 
    156136            if (t == ")" || t == null) 
    157137                break; 
    158         }  
    159         t = token (); 
    160     } 
    161  
    162     if (t != "{") 
    163     { 
    164         s = p; 
    165         flush (c); 
     138        } 
     139        t = token(); 
     140    } 
     141 
     142    if (t != "{") { 
     143        previous = p; 
     144        flush(current); 
    166145        return; 
    167146    } 
    168147 
    169     while (1) 
    170     { 
     148    while (1) { 
    171149        if (t == null) 
    172150            break; 
    173151        if (t == "{") 
    174             depth ++; 
    175         if (t == "}") 
    176         { 
    177             depth --; 
     152            depth++; 
     153        if (t == "}") { 
     154            depth--; 
    178155            if (depth == 0) 
    179156                break; 
    180157        } 
    181158 
    182         t = token (); 
    183     } 
    184  
    185     s = c; 
    186 
    187  
    188 int main (char [] [] args) 
    189 
    190     if (args.length == 1) 
    191     { 
    192         printf ("%.*s FILENAME\n\nPreprocesses the file in preparation for Doxygen.\n", args [0]); 
     159        t = token(); 
     160    } 
     161 
     162    previous = current; 
     163
     164 
     165 
     166int main(char[][] args) { 
     167    if (args.length == 1) { 
     168        writefln("Dfilter for Doxygen 1.4.2 
     169%s FILENAME 
     170 
     171Preprocesses the file in preparation for Doxygen.", args[0]); 
    193172        return 1; 
    194173    } 
    195      
    196     data = cast(char []) read (args [1]); 
    197     c = s = data; 
    198     e = s + data.length; 
    199  
    200     char [] t; 
    201     char [] [] protectRecord; 
    202     char [] protect = "public"; 
    203     char [] [] brackets; 
    204     char [] nextOpenBracket; 
    205     char [] nextSemiColon; 
    206     bit insideBrackets, elseif; 
    207      
    208     while (1) 
    209     { 
    210         t = token (); 
    211         if (t == null) 
    212         { 
    213             flush (c); 
    214             return 0; 
    215         } 
    216  
    217         switch (t) 
    218         { 
    219             /* Remove these keywords. */ 
    220             case "body": 
    221                 flush (p); 
    222                 s = c; 
    223                 break; 
    224  
    225             /* Remove these blocks. */ 
    226             case "unittest": 
    227             case "invariant": 
    228             case "in": 
    229             case "out": 
    230                 skipBlock (p); 
    231                 break; 
    232  
    233             /* Remove "keyword:" but only if it is followed with a colon. */ 
    234             case "override": 
    235             case "abstract": 
    236             case "final": 
    237                 flush (p); 
    238                 if ((t = token ()) == ":") 
    239                     s = c; 
    240                 break; 
    241  
    242             case ";": 
    243                 flush (c); 
    244                 printf ("%.*s", nextSemiColon); 
    245                 nextSemiColon = null; 
    246                 break; 
    247  
    248             /* "keyword" without "keyword:" into "keyword: ... { ... } antikeyword:" */ 
    249             case "public": 
    250             case "private": 
    251             case "protected": 
    252                 flush (p); 
    253                 if (token () == ":") 
    254                 { 
    255                     printf ("%.*s", t); 
    256                     protect = t; 
    257                     break; 
    258                 } 
    259  
    260                 if (t != protect) 
    261                 { 
    262                     printf ("%.*s: ", t); 
    263                     s = p; 
    264                     nextOpenBracket = protect ~ ":"; 
    265                     nextSemiColon = protect ~ ":"; 
    266                 } 
    267                 break; 
    268              
    269             /* Modify into "package". */ 
    270             /*Not necessary anymore 
    271                 case "module": 
    272                 flush (p); 
    273                 printf ("package ", nextSemiColon); 
    274                 s = c; 
    275                 break;*/ 
    276              
    277             /* Modify into import X.Y.*. */ 
    278             /* Not necessary anymore 
    279             case "import": 
    280                 flush (p); 
    281                 printf ("import ", nextSemiColon); 
    282  
    283                 while ((t = token ()) != null) 
    284                 { 
    285                     if (t == ";") 
    286                     { 
    287                         printf (";"); 
    288                         break; 
    289                     } 
    290                     else 
    291                         printf ("%.*s", t); 
    292                 } 
    293                 s = c; 
    294                 break;*/ 
    295  
    296             /* Change "version (...) { }" into "#ifdef ... and #endif" */ 
    297             case "version": { 
    298                     char *o = s; 
    299                     flush (p); 
    300  
    301                     char [] [] ver; 
    302  
     174 
     175    try { 
     176        debug (filename) derr.writefln("Filtering file %s", args[1]); 
     177        data = cast(char[]) read(args[1]); 
     178 
     179        // translate line breaks (to make output more readable for debugging) 
     180        data = replace(data, "\r\n", "\n"); 
     181        data = replace(data, "\r", "\n"); 
     182 
     183        current = previous = data.ptr; 
     184        end = previous + data.length; 
     185 
     186        char[] t; 
     187        bool elseif, readingContent; 
     188 
     189        while ((t = token()) != null) { 
     190            debug { 
     191                derr.writefln("Token '%s', block level %d", 
     192                  t, attrStack.length); 
     193                derr.writefln("Pending write: '%s'", 
     194                  previous[0..current - previous]); 
     195                debug (step) { 
     196                    getch(); 
     197                } 
     198            } 
     199 
     200            // remove private blocks if they are on the module level 
     201            if (attrStack.length == 0 && t == "private") { 
     202                debug { 
     203                    fputs("entered remove module-level private block\n", stderr); 
     204                } 
     205                flushTo(ptoken); 
     206 
     207                // FIXME: this doesn't work for constructs of the form 
     208                // private: 
     209                // public XXX; 
     210                // <more private data> 
     211 
     212                bool endReached = false; 
     213                bool breakAfterDecl = true; 
     214                uint tokenCount = 0; 
     215                int blockLevel = 0; 
     216 
     217                while (!endReached) { 
     218                    t = token(); 
     219                    if (t == null) 
     220                        return 0; 
     221 
     222                    debug derr.writefln("Private token '%s', block level %d", 
     223                      t, blockLevel); 
     224 
     225                    tokenCount++; 
     226 
     227                    switch (t) { 
     228                        case ":": 
     229                            if (tokenCount == 1) 
     230                                /*  do not break after next declaration; 
     231                                 *  instead we search for the next public 
     232                                 *  statement 
     233                                 */ 
     234                                breakAfterDecl = false; 
     235                            break; 
     236                        case ";": 
     237                            if (blockLevel == 0 && breakAfterDecl) 
     238                                endReached = true; 
     239                            break; 
     240                        case "{": 
     241                            blockLevel++; 
     242                            break; 
     243                        case "}": 
     244                            blockLevel--; 
     245                            if (blockLevel == 0 && breakAfterDecl) 
     246                                endReached = true; 
     247                            break; 
     248                        case "public": 
     249                            if (blockLevel == 0) { 
     250                                writef("%s", t); 
     251                                endReached = true; 
     252                            } 
     253                            break; 
     254                        default: 
     255                            break; 
     256                    } 
     257                } 
     258 
     259                previous=current; 
     260                debug { 
     261                    fputs("exited remove module-level private block\n", stderr); 
     262                } 
     263            } 
     264            else switch (t) { 
     265                // remove these keywords 
     266                case "body": 
     267                    flush(ptoken); 
     268                    previous = current; 
     269                    break; 
     270 
     271                // remove these blocks 
     272                case "unittest": 
     273                case "invariant": 
     274                case "in": 
     275                case "out": 
     276                    skipBlock(ptoken); 
     277                    break; 
     278 
     279                // record attributes to support attr: or attr { ... } syntax 
     280                case "export": 
     281                    currentAttr.protect = PROT.EXPORT; 
     282                    break; 
     283                case "public": 
     284                    currentAttr.protect = PROT.PUBLIC; 
     285                    break; 
     286                case "protected": 
     287                    currentAttr.protect = PROT.PROTECTED; 
     288                    break; 
     289                case "package": 
     290                    currentAttr.protect = PROT.PACKAGE; 
     291                    break; 
     292                case "private": 
     293                    currentAttr.protect = PROT.PRIVATE; 
     294                    break; 
     295                case "deprecated": 
     296                    currentAttr.attr = ATTR.DEPRECATED; 
     297                    break; 
     298                case "static": 
     299                    currentAttr.attr = ATTR.STATIC; 
     300                    break; 
     301                case "abstract": 
     302                    currentAttr.attr = ATTR.ABSTRACT; 
     303                    break; 
     304                case "final": 
     305                    currentAttr.attr = ATTR.FINAL; 
     306                    break; 
     307                case "override": 
     308                    currentAttr.attr = ATTR.OVERRIDE; 
     309                    break; 
     310                case "const": 
     311                    currentAttr.attr = ATTR.CONST; 
     312                    break; 
     313                case "auto": 
     314                    currentAttr.attr = ATTR.AUTO; 
     315                    break; 
     316                case "synchronized": 
     317                    currentAttr.attr = ATTR.SYNCHRONIZED; 
     318                    break; 
     319 
     320                case ":": 
     321                    if (!readingContent) { 
     322                        currentBlockAttr = currentAttr; 
     323                        previous = current; 
     324                    } 
     325                    break; 
     326 
     327                case ";": 
     328                    if (readingContent) { 
     329                        flush(current); 
     330                        currentAttr = currentBlockAttr; 
     331                        readingContent = false; 
     332                    } 
     333                    break; 
     334 
     335                case "{": 
     336                    if (readingContent) { 
     337                        // is function/structure body 
     338                        flush(current); 
     339                        pushContentBlock(); 
     340                        readingContent = false; 
     341                    } else { 
     342                        // is attribute block 
     343                        pushAttrBlock(); 
     344                        flush(ptoken); 
     345                    } 
     346                    break; 
     347 
     348                case "}": 
     349                    if (currentAttr.isContentBlock) { 
     350                        flush(current); 
     351                    } else { 
     352                        flush(ptoken); 
     353                    } 
     354                    currentAttr = currentBlockAttr 
     355                      = attrStack[attrStack.length-1]; 
     356                    attrStack.length = attrStack.length - 1; 
     357                    readingContent = false; 
     358                    break; 
     359 
     360                // Change "version (...) { }" into "#ifdef ... and #endif" 
     361                case "version": { 
     362                    char *o = previous; 
     363                    flush(ptoken); 
     364 
     365                    char[][] ver; 
    303366                    int depth = 0; 
    304                     char [] t = token (); 
     367 
     368                    t = token(); 
    305369 
    306370                    ver.length = 0; 
    307                     if (t == "(") 
    308                     { 
    309                         while (1) 
    310                         { 
    311                             t = token (); 
     371                    if (t == "(") { 
     372                        while (1) { 
     373                            t = token(); 
    312374                            if (t == ")" || t == null) 
    313375                                break; 
     
    315377                            ver[length - 1] = t; 
    316378                        } 
    317                         t = token (); 
     379                        t = token(); 
    318380                    } 
    319381 
    320382                    if (elseif) { 
    321                         printf ("\n#elif VERSION_%.*s\n", std.string.toupper(join(ver, ""))); 
     383                        writefln("\n#elif VERSION_%s", 
     384                          std.string.toupper(join(ver, ""))); 
    322385                    } else { 
    323                         printf ("\n#ifdef VERSION_%.*s\n", std.string.toupper(join(ver, ""))); 
     386                        writefln("\n#ifdef VERSION_%s", 
     387                          std.string.toupper(join(ver, ""))); 
    324388                    } 
    325389                    elseif = false; 
    326390 
    327391                    if (t == "{") { 
    328                         char *savec = c; 
    329                         while (1) 
    330                         { 
     392                        char *savec = current; 
     393                        while (1) { 
    331394                            if (t == null) 
    332395                                break; 
    333396                            if (t == "{") 
    334                                 depth ++; 
    335                             if (t == "}") 
    336                             { 
    337                                 depth --; 
     397                                depth++; 
     398                            if (t == "}") { 
     399                                depth--; 
    338400                                if (depth == 0) { 
    339401                                    // We found the last '}', now remove it! 
    340                                     *(c-1) = 0x01; 
    341                                     c = savec; 
     402                                    *(current-1) = 0x01; 
     403                                    current = savec; 
    342404                                    break; 
    343405                                } 
    344406                            } 
    345407 
    346                             t = token (); 
     408                            t = token(); 
    347409                        } 
    348410 
    349                         s = c
     411                        previous = current
    350412                    } else { 
    351                         s = p
     413                        previous = ptoken
    352414 
    353415                        // Parse until the next semicolon: 
     
    359421                            t = token(); 
    360422                        } 
    361                         flush (c); 
    362                         printf("\n#endif\n"); 
    363                         s = c; 
    364                     } 
    365                     break; 
    366                 } 
    367  
    368             case "\x01": 
    369                 flush(p); 
    370  
    371                 if ((t = token ()) != "else") { 
    372                     printf("\n#endif\n"); 
    373                     c = p; 
    374                     break; 
    375                 } 
    376  
    377                 if ((t = token()) != "version") { 
    378                     elseif = false; 
    379                     printf("\n#else\n"); 
    380                     char *savec = c; 
    381                     int depth = 0; 
    382  
    383                     while (1) { 
    384                         if (t == null) 
    385                             break; 
    386                         if (t == "{") 
    387                             depth ++; 
    388                         if (t == "}") 
    389                         { 
    390                             depth --; 
    391                             if (depth == 0) { 
    392                                 // We found the last '}', now mark it! 
    393                                 *(c-1) = 0x01; 
     423                        flush(current); 
     424                        writefln("\n#endif"); 
     425                        previous = current; 
     426                    } 
     427                    break; 
     428                } 
     429 
     430                // marked end of version block 
     431                case "\x01": 
     432                    flush(ptoken); 
     433 
     434                    if ((t = token()) != "else") { 
     435                        writefln("\n#endif"); 
     436                        current = ptoken; 
     437                        break; 
     438                    } 
     439 
     440                    if ((t = token()) != "version") { 
     441                        elseif = false; 
     442                        writefln("\n#else"); 
     443                        char *savec = current; 
     444                        int depth = 0; 
     445 
     446                        while (1) { 
     447                            if (t == null) 
    394448                                break; 
     449                            if (t == "{") 
     450                                depth++; 
     451                            if (t == "}") { 
     452                                depth--; 
     453                                if (depth == 0) { 
     454                                    // We found the last '}', now mark it! 
     455                                    *(current-1) = 0x01; 
     456                                    break; 
     457                                } 
    395458                            } 
     459 
     460                            t = token(); 
    396461                        } 
    397  
    398                         t = token (); 
    399                     } 
    400                     p = savec; 
    401                 } else { 
    402                     elseif = true; 
    403                 } 
    404                 s = c = p; 
    405                 break; 
    406  
    407             /* Remove "extern (...)". */ 
    408             case "extern": 
    409                 flush (p); 
    410                 if ((t = token ()) != "(") 
    411                 { 
    412                     c = p; 
    413                     break; 
    414                 } 
    415  
    416                 while ((t = token ()) != null) 
    417                     if (t == ")") 
     462                        ptoken = savec; 
     463                    } else { 
     464                        elseif = true; 
     465                    } 
     466                    previous = current = ptoken; 
     467                    break; 
     468 
     469                // Remove "extern (...)" and "align (...)" 
     470                case "extern": 
     471                case "align": 
     472                case "pragma": 
     473                    flush(ptoken); 
     474                    if ((t = token()) != "(") { 
     475                        current = ptoken; 
    418476                        break; 
    419                 s = c; 
    420                 break; 
    421  
    422             /* "alias" into "typedef". */ 
    423             case "alias": 
    424                 flush (p); 
    425                 printf ("typedef"); 
    426                 s = c; 
    427                 break; 
    428  
    429             /* "instance" into "typedef". */ 
    430             case "instance": 
    431                 flush (p); 
    432                 printf ("typedef"); 
    433                 s = c; 
    434  
    435                 while ((t = token ()) != null) 
    436                     if (t == "(") 
    437                     { 
    438                         flush (p); 
    439                         printf ("<"); 
    440                         s = c; 
    441                     } 
    442                     else if (t == ")") 
    443                     { 
    444                         flush (p); 
    445                         printf (">"); 
    446                         s = c; 
    447                         break; 
    448                     } 
    449  
    450                 break; 
    451  
    452             case "{": 
    453                 brackets ~= nextOpenBracket; 
    454                 nextOpenBracket = null; 
    455                 break; 
    456  
    457             /* "}" into "};" */ 
    458             case "}": 
    459                 if (protectRecord.length) 
    460                 { 
    461                     protect = protectRecord [protectRecord.length - 1]; 
    462                     protectRecord.length = protectRecord.length - 1; 
    463                 } 
    464  
    465                 flush (c); 
    466                 printf (";"); 
    467                 if (brackets.length && brackets [brackets.length - 1]) 
    468                 { 
    469                     printf (" %.*s", brackets [brackets.length - 1]); 
    470                     brackets = brackets [0 .. brackets.length - 1]; 
    471                 } 
    472                 break; 
    473  
    474             /* "class ... {" into "class ... { public:". */ 
    475             /* 
    476             Not necessary anymore 
    477             case "class": 
    478             */ 
    479             case "interface": 
    480             { 
    481                 bit colon = false; 
    482  
    483                 flush (p); 
    484  
    485                 printf ("class"); 
    486  
    487                 protectRecord ~= protect; 
    488                 protect = "public"; 
    489  
    490                 while ((t = token ()) != null) 
    491                 { 
    492                 restart: 
    493                     if (t == ":" && !colon) 
    494                     { 
    495                         colon = true; 
    496                         t = token (); 
    497                         if (t != "public" && t != "private" && t != "protected") 
    498                         { 
    499                             flush (p); 
    500                             s = p; 
    501                             printf ("public "); 
    502                             goto restart; 
     477                    } 
     478 
     479                    while ((t = token()) != null) 
     480                        if (t == ")") 
     481                            break; 
     482                    previous = current; 
     483                    break; 
     484 
     485                // "alias" into "typedef" 
     486                case "alias": 
     487                    flush(ptoken); 
     488                    writef("%s typedef", currentAttr.toString); 
     489                    readingContent = true; 
     490                    previous = current; 
     491                    break; 
     492 
     493                // "template name (x)" into "template namespace name <x>" 
     494                case "template": 
     495                    flush(current); 
     496 
     497                    readingContent = true; 
     498                    writef("%s class", currentAttr.toString); 
     499 
     500                    while ((t = token()) != null) 
     501                        if (t == "(") { 
     502                            flush(ptoken); 
     503                            writef("<"); 
     504                            previous = current; 
     505                        } else if (t == ")") { 
     506                            flush(ptoken); 
     507                            writef(">"); 
     508                            previous = current; 
     509                            break; 
    503510                        } 
    504                     } 
    505                     else if (t == ";") 
    506                         break; 
    507                     else if (t == "{") 
    508                     { 
    509                         flush (c);       
    510                         printf (" public:"); 
    511                         break; 
    512                     } 
    513                 } 
    514                 break; 
     511 
     512                    while ((t = token()) != null) 
     513                        if (t == "{") { 
     514                            pushContentBlock(); 
     515                            readingContent = false; 
     516                            flush(current); 
     517                            break; 
     518                        } else if (t == ";") 
     519                            break; 
     520                    break; 
     521 
     522                /* "delegate (...) name" into "(*name) (...)". */ 
     523                case "function": 
     524                case "delegate": 
     525                    flush(ptoken); 
     526                    previous = current; 
     527 
     528                    readingContent = true; 
     529                    writef("%s ", currentAttr.toString);