/*++ Copyright (c) 1992 Microsoft Corporation Module Name: hextract.c Abstract: This is the main module for a header the file extractor. Author: Andre Vachon (andreva) 13-Feb-1992 Mark Lucovsky (markl) 28-Jan-1991 Revision History: --*/ #include #include #include #include #include #include // // Function declarations // int ProcessParameters( int argc, char *argv[] ); void ProcessSourceFile( void ); void ProcessLine( char *s ); // // Global Data // unsigned char LineFiltering = 0; char *LineTag; char *ExcludeLineTag; char *MultiLineTagStart; char *MultiLineTagEnd; char *CommentDelimiter = "//"; char *OutputFileName; char *SourceFileName; char **SourceFileList; int SourceFileCount; FILE *SourceFile, *OutputFile; #define STRING_BUFFER_SIZE 1024 char StringBuffer[STRING_BUFFER_SIZE]; #define BUILD_VER_COMMENT "/*++ BUILD Version: " #define BUILD_VER_COMMENT_LENGTH (sizeof( BUILD_VER_COMMENT )-1) int OutputVersion = 0; #define szVERSION "1.3" char const szUsage[] = "Microsoft (R) HEXTRACT Version " szVERSION " (NT)\n" VER_LEGALCOPYRIGHT_STR ". All rights reserved.\n" "\n" "Usage: HEXTRACT [options] filename1 [filename2 ...]\n" "\n" "Options:\n" " -f - filtering is turned on:\n" " ULONG, UCHAR, USHORT & NTSTATUS are\n" " replaced with DWORD, BYTE, WORD & DWORD.\n" " -f2 - Same as -f except ULONGLONG and ULONG_PTR\n" " isn't converted\n" " -o filename - required existing output filename;\n" " output is appended to filename\n" " -xt string - supplies the tag for excluding one line\n" " -lt string - supplies the tag for extracting one line\n" " -bt string1 string2 - supplies the starting and ending tags for\n" " extracting multiple lines\n" " filename1 [filename2 ...] - supplies files from which the definitions\n" " are extracted\n" "\n" "To be parsed properly, the tag strings must be located within a comment\n" "delimited by //\n" ; int __cdecl main( argc, argv ) int argc; char *argv[]; { char achver[BUILD_VER_COMMENT_LENGTH]; if (!ProcessParameters(argc, argv) || NULL == OutputFileName) { fprintf(stderr, szUsage); return 1; } if ( (OutputFile = fopen(OutputFileName,"r+")) == 0) { fprintf(stderr,"HEXTRACT: Unable to open output file %s for update access\n",OutputFileName); return 1; } if (fseek(OutputFile, 0L, SEEK_END) == -1) { fprintf(stderr, "HEXTRACT: Unable to seek to end of %s\n", OutputFileName); return 1; } OutputVersion = 0; #ifdef HEXTRACT_DEBUG fprintf( stderr, "%s\n%s\n%s\n%s\n", LineTag, ExcludeLineTag, MultiLineTagStart, MultiLineTagEnd); #endif while ( SourceFileCount-- ) { SourceFileName = *SourceFileList++; if ( (SourceFile = fopen(SourceFileName,"r")) == 0) { fprintf(stderr,"HEXTRACT: Unable to open source file %s for read access\n",SourceFileName); return 1; } ProcessSourceFile(); fclose(SourceFile); } if (fseek(OutputFile, 0L, SEEK_SET) == -1) { fprintf(stderr, "HEXTRACT: Unable to seek to start of %s\n", OutputFileName); return 1; } if (1 == fread(achver, BUILD_VER_COMMENT_LENGTH, 1, OutputFile) && !strncmp(achver, BUILD_VER_COMMENT, BUILD_VER_COMMENT_LENGTH)) { if (fseek(OutputFile, (long)BUILD_VER_COMMENT_LENGTH, SEEK_SET) == -1) { fprintf(stderr, "HEXTRACT: Unable to seek past comments in %s\n", OutputFileName); return 1; } fprintf(OutputFile, "%04d", OutputVersion); } if (fseek(OutputFile, 0L, SEEK_END) == -1) { fprintf(stderr, "HEXTRACT: Unable to seek to end of %s\n", OutputFileName); return 1; } fclose(OutputFile); return( 0 ); } int ProcessParameters( int argc, char *argv[] ) { char c, *p; while (--argc) { p = *++argv; // // if we have a delimiter for a parameter, case throught the valid // parameter. Otherwise, the rest of the parameters are the list of // input files. // if (*p == '/' || *p == '-') { // // Switch on all the valid delimiters. If we don't get a valid // one, return with an error. // c = *++p; switch (toupper( c )) { case 'F': c = *++p; if ( (toupper ( c )) == '2') LineFiltering = 2; else LineFiltering = 1; break; case 'O': argc--, argv++; OutputFileName = *argv; break; case 'L': c = *++p; if ( (toupper ( c )) != 'T') return 0; argc--, argv++; LineTag = *argv; break; case 'B': c = *++p; if ( (toupper ( c )) != 'T') return 0; argc--, argv++; MultiLineTagStart = *argv; argc--, argv++; MultiLineTagEnd = *argv; break; case 'X': c = *++p; if ( (toupper ( c )) != 'T') return 0; argc--, argv++; ExcludeLineTag = *argv; break; default: return 0; } } else { // // Make the assumptionthat we have a valid command line if and // only if we have a list of filenames. // SourceFileList = argv; SourceFileCount = argc; return 1; } } return 0; } void ProcessSourceFile( void ) { char *s; char *comment; char *tag; char *test; s = fgets(StringBuffer,STRING_BUFFER_SIZE,SourceFile); if (s) { if (!strncmp( s, BUILD_VER_COMMENT, BUILD_VER_COMMENT_LENGTH )) { OutputVersion += atoi( s + BUILD_VER_COMMENT_LENGTH ); } } while ( s ) { // // Check for a block with delimiters // if (NULL != MultiLineTagStart) { comment = strstr(s,CommentDelimiter); if ( comment ) { tag = strstr(comment,MultiLineTagStart); if ( tag ) { // // Now that we have found an opening tag, check each // following line for the closing tag, and then include it // in the ouput. // s = fgets(StringBuffer,STRING_BUFFER_SIZE,SourceFile); while ( s ) { int fProcess = 1; comment = strstr(s,CommentDelimiter); if ( comment ) { tag = strstr(comment,MultiLineTagEnd); if ( tag ) { goto bottom; } if (NULL != ExcludeLineTag && strstr(comment,ExcludeLineTag)) { fProcess = 0; } } if (fProcess) { ProcessLine(s); } s = fgets(StringBuffer,STRING_BUFFER_SIZE,SourceFile); } fprintf(stderr, "HEXTRACT: %s without matching %s in %s\n", MultiLineTagStart, MultiLineTagEnd, OutputFileName); exit(1); } } } // // Check for a single line to output. // if (NULL != LineTag) { comment = strstr(s,CommentDelimiter); if ( comment ) { tag = strstr(comment,LineTag); if ( tag ) { *comment++ = '\n'; *comment = '\0'; ProcessLine(s); goto bottom; } } } bottom: s = fgets(StringBuffer,STRING_BUFFER_SIZE,SourceFile); } } void ProcessLine( char *s ) { char *t; char *s1; if (LineFiltering) { s1 = s; // // This should be replaced by a data file describing an input token // and an output token which would be used for the filtering. // while (t = strstr(s1,"ULONG")) { if (LineFiltering == 2) { if (!memcmp(t, "ULONGLONG", 9)) { s1+=9; } else if (!memcmp(t, "ULONG_PTR", 9)) { s1+=9; } else { memcpy(t,"DWORD",5); } } else { memcpy(t,"DWORD",5); } } while (t = strstr(s,"UCHAR")) memcpy(t,"BYTE ",5); while (t = strstr(s,"USHORT")) memcpy(t,"WORD ",6); while (t = strstr(s,"NTSTATUS")) memcpy(t,"DWORD ",8); } fputs(s,OutputFile); }