home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / HPACK78S.ZIP / data / mangle.c < prev    next >
C/C++ Source or Header  |  1992-10-21  |  16KB  |  556 lines

  1. /* Heavy BFI converter to mangle source code for non-ANSI compilers.
  2.    Don't even try to run this on code which doesn't follow the HPACK
  3.    formatting conventions - it will probably hang since I couldn't be
  4.    bothered doing all sorts of fancy checking.  It does the job and no
  5.    more */
  6.  
  7. #include <ctype.h>
  8. #include <defs.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12.  
  13. char inBuffer[ 255 ];
  14. FILE *outFile;
  15.  
  16. BOOLEAN doVoid = FALSE, doElif = FALSE, doUnindent = FALSE;
  17. BOOLEAN doCont = FALSE, doStrcat = FALSE, doVoidPtr = FALSE;
  18. BOOLEAN doConst = FALSE, doPragma = FALSE, doPrototype = FALSE;
  19. BOOLEAN doFunction = FALSE, doMaxProto = FALSE;
  20. BOOLEAN doEnum = FALSE;
  21.  
  22. /* Output count spaces if necessary */
  23.  
  24. static void spaces( int count )
  25.     {
  26.     int i = 0;
  27.  
  28.     if( doUnindent )
  29.         return;
  30.     while( count-- )
  31.         putc( inBuffer[ i++ ], outFile );
  32.     }
  33.  
  34. /* Unprotoize a string (eg "int foo, char *bar" -> "int, char *") */
  35.  
  36. static void unprotoize( char *string, int length )
  37.     {
  38.     int commaIndex = 0, nameStart;
  39.  
  40.     /* Check for pure void function - the de-voider hasn't hacked it yet */
  41.     if( !strncmp( string, "void )", 6 ) )
  42.         {
  43.         memmove( string - 1, string + 5, strlen( string ) );
  44.         return;
  45.         }
  46.  
  47.     while( commaIndex < length )
  48.         {
  49.         /* Find end of next name in string */
  50.         for( ; commaIndex < length && \
  51.              string[ commaIndex ] != ',' && string[ commaIndex ] != ')';
  52.              commaIndex++ );
  53.         if( string[ commaIndex ] == ')' )
  54.             commaIndex--;        /* Special case: last arg */
  55.  
  56.         /* Find start of next name in string */
  57.         for( nameStart = commaIndex - 1; \
  58.              nameStart && !( string[ nameStart ] == ' ' || string[ nameStart ] == '*' ); \
  59.              nameStart-- );
  60.         while( string[ nameStart ] == '*' )
  61.             nameStart++;                /* Don't zap '*' */
  62.  
  63.         /* Zap out name. NB take advantage of multiple fenceposts from above */
  64.         memmove( string + nameStart, string + commaIndex, strlen( string + commaIndex ) + 1 );
  65.         length -= commaIndex - nameStart;
  66.         }
  67.     }
  68.  
  69. /* Unfunctionize a string (eg int foo( int a, int b ) -> int foo( a, b ) int a; int b;) */
  70.  
  71. char argTable[ 20 ][ 40 ];    /* Table to hold args */
  72. int maxArg = 0;                /* Current high-water mark in argTable */
  73.  
  74. static void unfunctionize( char *string, int length )
  75.     {
  76.     int startIndex = 0, commaIndex = 0, nameStart, lastCommaIndex, offset = 0;
  77.     char *strPos;
  78.  
  79.     /* Check if it's a pure void fn. (the de-voider hasn't attacked it yet) */
  80.     if( !strncmp( string, "void )", 6 ) )
  81.         return;
  82.  
  83.     maxArg = 0;
  84.     while( startIndex < length )
  85.         {
  86.         /* Find end of next name in string */
  87.         for( ; commaIndex < length && \
  88.              string[ commaIndex ] != ',' && string[ commaIndex ] != ')';
  89.              commaIndex++ );
  90.         if( string[ commaIndex ] == ')' )
  91.             commaIndex--;        /* Special case: last arg */
  92.  
  93.         /* Find start of next name in string */
  94.         for( nameStart = commaIndex - 1; \
  95.              nameStart && !( string[ nameStart ] == ' ' || string[ nameStart ] == '*' ); \
  96.              nameStart-- );
  97.  
  98.         /* Find start of type in string */
  99.         for( lastCommaIndex = nameStart - 1; \
  100.              lastCommaIndex && string[ lastCommaIndex ] != ','; \
  101.              lastCommaIndex-- );
  102.         if( string[ lastCommaIndex ] == ',' )
  103.             lastCommaIndex += 2;
  104.  
  105.         /* Check for special case of ellipses */
  106.         if( string[ lastCommaIndex ] == '.' )
  107.             {
  108.             memmove( string + lastCommaIndex - 2, string + nameStart, strlen( string + commaIndex ) );
  109.             break;
  110.             }
  111.  
  112.         /* Store declaration for later */
  113.         *argTable[ maxArg ] = '\t';
  114.         strncpy( argTable[ maxArg ] + 1, string + lastCommaIndex, commaIndex - lastCommaIndex );
  115.         strcpy( argTable[ maxArg++ ] + commaIndex - lastCommaIndex + 1, ";\n" );
  116.  
  117.         /* Zap out type. NB take advantage of multiple fenceposts from above */
  118.         if( string[ commaIndex - 1 ] == ']' )
  119.             {
  120.             memmove( string + commaIndex - 2, string + commaIndex, strlen( string + commaIndex ) + 1 );
  121.             offset = 2;
  122.             }
  123.         memmove( string + startIndex, string + nameStart + 1, strlen( string + nameStart ) );
  124.         length -= ( nameStart + 1 ) - lastCommaIndex + offset;
  125.         startIndex += commaIndex - nameStart + 1 - offset;
  126.         commaIndex -= offset;
  127.         offset = 0;
  128.         }
  129.  
  130.     /* Zap any 'const's' and 'void *'s in the argTable if necessary */
  131.     if( doConst )
  132.         for( nameStart = 0; nameStart < maxArg; nameStart++ )
  133.             if( !strncmp( argTable[ nameStart ] + 1, "const ", 6 ) )
  134.                 memmove( argTable[ nameStart ] + 1, argTable[ nameStart ] + 7, strlen( argTable[ nameStart ] ) );
  135.     if( doVoidPtr )
  136.         for( nameStart = 0; nameStart < maxArg; nameStart++ )
  137.             if( ( strPos = strstr( argTable[ nameStart ] + 1, "void *" ) ) != NULL )
  138.                 strncpy( strPos, "char", 4 );
  139.     }
  140.  
  141. /* Turn an enumerated type into a series of #defines */
  142.  
  143. void doUnenum( char *string, int length, const BOOLEAN hasTypedef )
  144.     {
  145.     int index = 0, endIndex = 0, value = 0;
  146.     char ch;
  147.  
  148.     if( hasTypedef )
  149.         {
  150.         string += 15;
  151.         length -= 15;        /* Skip "typedef enum { " */
  152.         }
  153.     else
  154.         {
  155.         string += 7;
  156.         length -= 7;        /* Skip "enum { " */
  157.         }
  158.  
  159.     while( index < length )
  160.         {
  161.         /* Find next enumeration */
  162.         while( ( ch = string[ endIndex ] ) != ' ' && ch != '\t' && ch )
  163.             endIndex++;
  164.         string[ ( string[ endIndex - 1 ] == ',' ) ? endIndex - 1 : endIndex ] = '\0';
  165.  
  166.         /* Check if it has a value */
  167.         if( string[ endIndex + 1 ] == '=' )
  168.             {
  169.             endIndex += 3;
  170.             value = atoi( string + endIndex );
  171.             while( ( ch = string[ endIndex ] ) != ' ' && ch != '\t' )
  172.                 endIndex++;
  173.             }
  174.  
  175.         fprintf( outFile, "#define %s\t%d\n", string + index, value++ );
  176.  
  177.         index = ++endIndex;            /* Skip space */
  178.         }
  179.  
  180.     /* Check if we have to declare an equivalent integer type */
  181.     if( hasTypedef )
  182.         {
  183.         while( string[ endIndex ] != ';' )
  184.             endIndex++;
  185.         string[ endIndex ] = '\0';
  186.         fprintf( outFile, "\n#define %s\tint\n", string + index + 2 );    /* +2 = "} " */
  187.         }
  188.     }
  189.  
  190. void main( int argc, char *argv[] )
  191.     {
  192.     FILE *inFile;
  193.     int index, endIndex, elifCount = 0;
  194.     BOOLEAN inElifBlock = FALSE, hasHash = FALSE, isMacroCont = FALSE;
  195.     char *strPtr, ch;
  196.  
  197.     /* Check args */
  198.     if( argc != 3 )
  199.         {
  200.         puts( "Usage: MANGLE -cefiknprstvw <warez>" );
  201.         exit( ERROR );
  202.         }
  203.  
  204.     /* Handle options */
  205.     if( !strcmp( argv[ 1 ], "-ward" ) )
  206.         doCont = doElif = doUnindent = doConst = doVoidPtr = doStrcat = \
  207.         doVoid = doPragma = doPrototype = doFunction = doMaxProto = \
  208.         doEnum = TRUE;
  209.     if( strchr( argv[ 1 ], 'c' ) )
  210.         doCont = TRUE;
  211.     if( strchr( argv[ 1 ], 'e' ) )
  212.         doElif = TRUE;
  213.     if( strchr( argv[ 1 ], 'f' ) )
  214.         doFunction = TRUE;
  215.     if( strchr( argv[ 1 ], 'i' ) )
  216.         doUnindent = TRUE;
  217.     if( strchr( argv[ 1 ], 'k' ) )
  218.         doConst = TRUE;
  219.     if( strchr( argv[ 1 ], 'n' ) )
  220.         doEnum = TRUE;
  221.     if( strchr( argv[ 1 ], 'p' ) )
  222.         doVoidPtr = TRUE;
  223.     if( strchr( argv[ 1 ], 'r' ) )
  224.         doPragma = TRUE;
  225.     if( strchr( argv[ 1 ], 's' ) )
  226.         doStrcat = TRUE;
  227.     if( strchr( argv[ 1 ], 't' ) )
  228.         doPrototype = TRUE;
  229.     if( strchr( argv[ 1 ], 'v' ) )
  230.         doVoid = TRUE;
  231.     if( strchr( argv[ 1 ], 'w' ) )
  232.         doMaxProto = TRUE;
  233.  
  234.     /* Yo dude, got any warez? */
  235.     if( ( inFile = fopen( argv[ 2 ], "r" ) ) == NULL )
  236.         {
  237.         printf( "No warez: %s\n", argv[ 2 ] );
  238.         exit( ERROR );
  239.         }
  240. #ifdef TEST_VERSION
  241.     outFile = stdout;
  242. #else
  243.     if( ( outFile = fopen( "tmp.$$$", "w" ) ) == NULL )
  244.         {
  245.         printf( "Can't open output file" );
  246.         exit( ERROR );
  247.         }
  248. #endif /* TEST_VERSION */
  249.  
  250. #if defined( __MSDOS__ ) && !defined( TEST_VERSION )
  251.     /* DOS will happily reopen the same file multiple times, so we have to
  252.        create a lockfile... */
  253.     {
  254.     char lockFilename[ 80 ];
  255.     FILE *lockFilePtr;
  256.     int i;
  257.     char ch;
  258.  
  259.     strcpy( lockFilename, argv[ 2 ] );
  260.     for( i = strlen( lockFilename ); \
  261.          i && lockFilename[ i ] != '.' && lockFilename[ i ] != '\\';
  262.          i-- );
  263.     if( lockFilename[ i ] != '.' )
  264.         strcpy( lockFilename + strlen( lockFilename ), ".~~~" );
  265.     else
  266.         {
  267.         /* Preserve 1-letter suffix */
  268.         if( ( ch = lockFilename[ i + 1 ] ) == '~' )
  269.             {
  270.             /* This may be a lockfile we're processing */
  271.             fclose( outFile );
  272.             unlink( "tmp.$$$" );
  273.             exit( ERROR );
  274.             }
  275.         strcpy( lockFilename + i, ".~~~" );
  276.         lockFilename[ i + 3 ] = ch;
  277.         }
  278.  
  279.     if( ( lockFilePtr = fopen( lockFilename, "r" ) ) != NULL )
  280.         {
  281.         /* Don't process same file twice */
  282.         fclose( lockFilePtr );
  283.         fclose( outFile );
  284.         unlink( "tmp.$$$" );
  285.         exit( ERROR );
  286.         }
  287.  
  288.     /* Create the lockfile */
  289.     lockFilePtr = fopen( lockFilename, "w" );
  290.     fclose( lockFilePtr );
  291.     }
  292. #endif /* __MSDOS__ && !TEST_VERSION */
  293.  
  294.     /* Mangle the file one line at a time */
  295.     while( fgets( inBuffer, 250, inFile ) != NULL )
  296.         {
  297.         if( inBuffer[ strlen( inBuffer ) - 1 ] == '\n' )
  298.             inBuffer[ strlen( inBuffer ) - 1 ] = '\0';
  299.  
  300.         /* Skip blank lines now */
  301.         if( !*inBuffer )
  302.             {
  303.             putc( '\n', outFile );
  304.             continue;
  305.             }
  306.  
  307.         for( index = 0; \
  308.              index < 250 && ( ch = inBuffer[ index ] ) == '\0' || ch == ' ' || ch == '\t'; \
  309.              index++ );
  310.  
  311.         /* Skip garbage at start of line */
  312.         while( !strncmp( inBuffer + index, "inline ", 7 ) || \
  313.                !strncmp( inBuffer + index, "static ", 7 ) || \
  314.                !strncmp( inBuffer + index, "extern ", 7 ) )
  315.             index += 7;
  316.  
  317.         /* Check for preprocessor stuff */
  318.         if( inBuffer[ index ] == '#' )
  319.             {
  320.             /* Check for #pragma */
  321.             if( doPragma && !strncmp( inBuffer + index, "#pragma", 7 ) )
  322.                 /* Skip it */
  323.                 continue;
  324.  
  325.             hasHash = TRUE;            /* Tassy green */
  326.             if( doElif && !strncmp( inBuffer + index, "#elif", 5 ) )
  327.                 {
  328.                 inElifBlock = TRUE;
  329.                 elifCount++;
  330.                 memmove( inBuffer + index, inBuffer + index + 2, strlen( inBuffer ) );
  331.                 spaces( index );
  332.                 fputs( "#else\n", outFile );
  333.                 strncpy( inBuffer + index, "#if ", 4 );
  334.                 }
  335.             else
  336.                 if( inElifBlock && !strncmp( inBuffer + index, "#endif", 6 ) )
  337.                     {
  338.                     while( elifCount-- )
  339.                         {
  340.                         spaces( index );
  341.                         fputs( "#endif\n", outFile );
  342.                         }
  343.                     elifCount = 0;
  344.                     inElifBlock = FALSE;
  345.                     }
  346.  
  347.             /* Get rid of indenting of '#...' */
  348.             spaces( index );
  349.             fputs( inBuffer + index, outFile );
  350.             putc( '\n', outFile );
  351.             continue;
  352.             }
  353.  
  354.         /* Check for function prototypes.  We check for:
  355.            <noise> + <type> + opt-'*' + <single_word> + '(' + ... + ')'
  356.            and delete the '...' part */
  357.         if( doPrototype )
  358.             {
  359.             int subIndex = index;
  360.  
  361.             /* Do serious BFI search for return type */
  362.             if( !strncmp( inBuffer + index, "int ", 4 ) || \
  363.                 !strncmp( inBuffer + index, "char ", 5 ) || \
  364.                 !strncmp( inBuffer + index, "long ", 5 ) || \
  365.                 !strncmp( inBuffer + index, "void ", 5 ) || \
  366.                 !strncmp( inBuffer + index, "BYTE ", 5 ) || \
  367.                 !strncmp( inBuffer + index, "WORD ", 5 ) || \
  368.                 !strncmp( inBuffer + index, "LONG ", 5 ) || \
  369.                 !strncmp( inBuffer + index, "BOOLEAN ", 8 ) || \
  370.                 !strncmp( inBuffer + index, "DATA_STATUS ", 12 ) || \
  371.                 !strncmp( inBuffer + index, "DIR ", 4 ) || \
  372.                 !strncmp( inBuffer + index, "DIRECT ", 7 ) || \
  373.                 !strncmp( inBuffer + index, "ATTR ", 5 ) || \
  374.                 !strncmp( inBuffer + index, "FILEHDRLIST ", 12 ) || \
  375.                 !strncmp( inBuffer + index, "DIRHDRLIST ", 11 ) )
  376.                 {
  377.                 /* Skip to start of function name */
  378.                 while( inBuffer[ subIndex++ ] != ' ' );
  379.                 if( inBuffer[ subIndex ] == '*' )
  380.                     subIndex++;
  381.  
  382.                 while( ( ch = inBuffer[ subIndex++ ] ) != '\0' && \
  383.                        ( ( ch >= 'A' && ch <= 'Z' ) || \
  384.                          ( ch >= 'a' && ch <= 'z' ) || \
  385.                          ( ch >= '0' && ch <= '9' ) || ch == '_' ) );
  386.  
  387.                 if( ch == '(' )
  388.                     {
  389.                     int endIndex = subIndex, subSubIndex;
  390.  
  391.                     /* We've matched <noise> <type> opt-'*' <single-word> */
  392.                     while( ( ch = inBuffer[ endIndex++ ] ) != '\0' && \
  393.                            ch != ')' && ch != '\\' );
  394.  
  395.                     /* Check for multi-line function */
  396.                     if( ch == '\\' )
  397.                         {
  398.                         fgets( inBuffer + endIndex - 1, 250, inFile );
  399.                         inBuffer[ strlen( inBuffer ) - 1 ] = '\0';
  400.                         for( subSubIndex = endIndex; \
  401.                              inBuffer[ subSubIndex ] == ' ' || \
  402.                              inBuffer[ subSubIndex ] == '\t';
  403.                              subSubIndex++ );
  404.                         memmove( inBuffer + endIndex - 1, inBuffer + subSubIndex, strlen( inBuffer + subSubIndex ) + 1 );
  405.                         for( endIndex = subSubIndex; \
  406.                              inBuffer[ endIndex ] && inBuffer[ endIndex ] != ')'; \
  407.                              endIndex++ );
  408.                         endIndex++;            /* Skip ')' */
  409.                         }
  410.  
  411.                     if( inBuffer[ endIndex ] == ';' )
  412.                         {
  413.                         /* It's a prototype (finally!), zap it */
  414.                         if( doPrototype )
  415.                             if( doMaxProto )
  416.                                 memmove( inBuffer + subIndex, inBuffer + endIndex - 1, \
  417.                                          strlen( inBuffer + endIndex ) + 2 );
  418.                             else
  419.                                 unprotoize( inBuffer + subIndex + 1, endIndex - subIndex - 3 );
  420.                         }
  421.                     else
  422.                         {
  423.                         /* It's a function, convert to K&R style */
  424.                         if( doFunction )
  425.                             unfunctionize( inBuffer + subIndex + 1, endIndex - subIndex - 3 );
  426.                         }
  427.                     }
  428.                 }
  429.             }
  430.  
  431.         /* Check for 'const's */
  432.         if( doConst )
  433.             while( ( strPtr = strstr( inBuffer + index, "const" ) ) != NULL )
  434.                 strcpy( strPtr, strPtr + 6 );
  435.  
  436.         /* Check for 'void' return types */
  437.         if( !strncmp( inBuffer + index, "void *", 6 ) )
  438.             {
  439.             /* Change 'void *' return to 'char *' */
  440.             if( doVoidPtr )
  441.                 strncpy( inBuffer + index, "char", 4 );
  442.             }
  443.         else
  444.             if( doVoid && !strncmp( inBuffer + index, "void", 4 ) )
  445.                 {
  446.                 /* Change void return to int */
  447.                 memmove( inBuffer + index, inBuffer + index + 1, strlen( inBuffer ) );
  448.                 strncpy( inBuffer + index, "int", 3 );
  449.                 }
  450.  
  451.         /* Change 'void *' into 'char *' */
  452.         if( ( strPtr = strstr( inBuffer + index, "void *" ) ) != NULL )
  453.             {
  454.             if( doVoidPtr )
  455.                 strncpy( strPtr, "char", 4 );
  456.             }
  457.         else
  458.             /* Change foo( void ) into foo() */
  459.             if( doVoid && ( strPtr = strstr( inBuffer + index, "void" ) ) != NULL )
  460.                 memmove( strPtr - 1, strPtr + 5, strlen( strPtr ) );
  461.  
  462.         /* Check for enums */
  463.         if( doEnum )
  464.             if( !strncmp( inBuffer + index, "enum ", 5 ) || \
  465.                 !strncmp( inBuffer + index, "typedef enum ", 13 ) )
  466.                 {
  467.                 int endIndex = index, subSubIndex;
  468.                 BOOLEAN hasTypedef = strncmp( inBuffer + index, "enum ", 5 );
  469.  
  470.                 /* Find end of declaration or continuation char */
  471.                 while( ( ch = inBuffer[ endIndex ] ) != '\0' && \
  472.                        ch != '}' && ch != '\\' )
  473.                     endIndex++;
  474.  
  475.                 /* Check for multi-line declaration */
  476.                 if( ch == '\\' )
  477.                     {
  478.                     fgets( inBuffer + endIndex, 250, inFile );
  479.                     inBuffer[ strlen( inBuffer ) ] = '\0';
  480.                     for( subSubIndex = endIndex; \
  481.                          inBuffer[ subSubIndex ] == ' ' || \
  482.                          inBuffer[ subSubIndex ] == '\t';
  483.                          subSubIndex++ );
  484.                     memmove( inBuffer + endIndex, inBuffer + subSubIndex, strlen( inBuffer + subSubIndex ) + 1 );
  485.                     for( endIndex = subSubIndex; \
  486.                          inBuffer[ endIndex ] && inBuffer[ endIndex ] != '}'; \
  487.                          endIndex++ );
  488.                     }
  489.  
  490.                 doUnenum( inBuffer + index, endIndex, hasTypedef );
  491.                 continue;
  492.                 }
  493.  
  494.         /* Check for continuation character strings */
  495.         for( endIndex = strlen( inBuffer );
  496.              endIndex && ( ch = inBuffer[ endIndex ] ) == ' ' || ch == '\t';
  497.              endIndex-- );
  498.         if( endIndex )
  499.             endIndex--;
  500.         if( inBuffer[ endIndex ] == '\\' )
  501.             {
  502.             /* Check for macro with continuation chars */
  503.             if( hasHash )
  504.                 isMacroCont = TRUE;
  505.             if( isMacroCont )
  506.                 {
  507.                 /* Leave it alone */
  508.                 fputs( inBuffer, outFile );
  509.                 putc( '\n', outFile );
  510.                 continue;
  511.                 }
  512.  
  513.             /* Check for string continuation */
  514.             if( endIndex > 2 && inBuffer[ endIndex - 2 ] == '\"' )
  515.                 {
  516.                 if( doStrcat )
  517.                     {
  518.                     endIndex -= 2;
  519.                     fgets( inBuffer + endIndex, 250, inFile );
  520.                     inBuffer[ endIndex + strlen( inBuffer + endIndex ) - 1 ] = '\0';
  521.                     for( index = endIndex; inBuffer[ index ] != '\"'; \
  522.                          index++ );
  523.                     memmove( inBuffer + endIndex, inBuffer + index + 1, strlen( inBuffer ) );
  524.                     }
  525.                 }
  526.             else
  527.                 if( doCont )
  528.                     /* Zap '\' at end of line */
  529.                     inBuffer[ endIndex ] = '\0';
  530.             }
  531.  
  532.         hasHash = FALSE;        /* Been raided.... */
  533.         isMacroCont = FALSE;
  534.         fputs( inBuffer, outFile );
  535.         putc( '\n', outFile );
  536.  
  537.         /* If there are function args floating around, output them now */
  538.         if( maxArg )
  539.             {
  540.             for( index = 0; index < maxArg; index++ )
  541.                 fputs( argTable[ index ], outFile );
  542.             maxArg = 0;
  543.             }
  544.         }
  545.  
  546.     /* Close files */
  547.     fclose( inFile );
  548.     fclose( outFile );
  549.  
  550. #ifndef TEST_VERSION
  551.     /* Delete old file and rename new one */
  552.     unlink( argv[ 2 ] );
  553.     rename( "tmp.$$$", argv[ 2 ] );
  554. #endif /* TEST_VERSION */
  555.     }
  556.