|
|
/*++
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 <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <common.ver>
//
// 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); }
|