windows-nt/Source/XPSP1/NT/sdktools/hsplit/hsplit.c
2020-09-26 16:20:57 +08:00

602 lines
18 KiB
C

/****************************** Module Header ******************************\
* Module Name: hsplit.c
*
* Structure parser - struct field name-offset tabel generator.
*
* Copyright (c) 1985-96, Microsoft Corporation
*
* 09/05/96 GerardoB Created
\***************************************************************************/
#include "hsplit.h"
/*
* Maximum size of tags (gphst) table including possible user defined tags
*/
#define HSTAGTABLESIZE (sizeof(ghstPredefined) + ((32 - HST_MASKBITCOUNT) * sizeof(HSTAG)))
/***************************************************************************\
* hsAddTag
*
\***************************************************************************/
PHSTAG hsAddTag (char * pszTag, DWORD dwMask)
{
PHSTAG phst;
DWORD dwTagSize;
/*
* Make sure we still have mask bits to uniquely identified this tag
*/
if (((dwMask | HST_EXTRACT) == HST_EXTRACT) && (gdwLastTagMask == HST_MAXMASK)) {
hsLogMsg(HSLM_ERROR, "Too many user defined tags. Max allowed: %d", 32 - HST_MASKBITCOUNT);
return NULL;
}
/*
* Create the table the first time around.
*/
if (gphst == ghstPredefined) {
gphst = (PHSTAG) LocalAlloc(LPTR, HSTAGTABLESIZE);
if (gphst == NULL) {
hsLogMsg(HSLM_APIERROR, "LocalAlloc");
hsLogMsg(HSLM_ERROR, "hsAddTag Allocation failed. Size:%#lx", HSTAGTABLESIZE);
return NULL;
}
CopyMemory(gphst, &ghstPredefined, sizeof(ghstPredefined));
}
/*
* If the string is in the table, we update the mask.
*/
dwTagSize = strlen(pszTag);
phst = hsFindTagInList(gphst, pszTag, dwTagSize);
if (phst == NULL) {
/*
* New string. Find next available entry in the table
*/
phst = gphst;
while (phst->dwLabelSize != 0) {
phst++;
}
}
/*
* Initialize it
*/
phst->dwLabelSize = dwTagSize;
phst->pszLabel = pszTag;
/*
* If generating a mask, use the next available bit in the tag mask
* else use the one supplied by the caller
*/
if ((dwMask | HST_EXTRACT) == HST_EXTRACT) {
gdwLastTagMask *= 2;
phst->dwMask = (gdwLastTagMask | dwMask);
} else {
phst->dwMask = dwMask;
}
/*
* Add this tag's mask to the filter mask so lines mark with this tag
* will be included
*/
gdwFilterMask |= (phst->dwMask & HST_USERTAGSMASK);
return phst;
}
/***************************************************************************\
* hsIsSwitch
*
\***************************************************************************/
__inline BOOL hsIsSwitch(char c)
{
return (c == '/') || (c == '-');
}
/***************************************************************************\
* hsAddUserDefinedTag
*
\***************************************************************************/
BOOL hsAddUserDefinedTag(DWORD* pdwMask, int* pargc, char*** pargv)
{
DWORD dwRetMask = *pdwMask;
PHSTAG phst;
if (*pargc < 2) {
return FALSE; // invalid switch
}
/*
* Allow multiple tags to be specified for one switch
* i.e., -t tag1 <tag2 tag2....>
*/
do {
(*pargc)--, (*pargv)++;
/*
* Add tag to table
*/
phst = hsAddTag(**pargv, *pdwMask);
if (phst == NULL) {
return 0;
}
dwRetMask |= phst->dwMask;
} while ((*pargc >= 2) && !hsIsSwitch(**(*pargv + 1)));
/*
* save the new mask
*/
*pdwMask = dwRetMask;
return TRUE;
}
/***************************************************************************\
* hsAddExtractFile
*
\***************************************************************************/
BOOL hsAddExtractFile(char* pszExtractFile, DWORD dwMask, BOOL bAppend)
{
PHSEXTRACT pe;
pe = LocalAlloc(LPTR, sizeof(HSEXTRACT));
if (pe == NULL) {
return FALSE;
}
pe->pszFile = pszExtractFile;
pe->dwMask = dwMask;
pe->hfile = CreateFile(pszExtractFile, GENERIC_WRITE, 0, NULL,
(bAppend ? OPEN_EXISTING : CREATE_ALWAYS),
FILE_ATTRIBUTE_NORMAL, NULL);
if (pe->hfile == INVALID_HANDLE_VALUE) {
hsLogMsg(HSLM_APIERROR | HSLM_NOLINE, "CreateFile failed for file %s",
pszExtractFile);
LocalFree(pe);
return FALSE;
}
if (bAppend) {
if (0xFFFFFFFF == SetFilePointer (pe->hfile, 0, 0, FILE_END)) {
hsLogMsg(HSLM_APIERROR | HSLM_NOLINE, "SetFilePointer failed for file %s",
pszExtractFile);
CloseHandle(pe->hfile);
LocalFree(pe);
return FALSE;
}
}
/*
* link it in the list of extract files
*/
pe->pNext = gpExtractFile;
gpExtractFile = pe;
return TRUE;
}
/***************************************************************************\
* hsProcessParameters
*
\***************************************************************************/
int hsProcessParameters(int argc, LPSTR argv[])
{
char c, *p;
DWORD dwMask;
int argcParm = argc;
PHSTAG phst;
/*
* Compatibility. Assume default project the first time this
* function is called
*/
if (!(gdwOptions & HSO_APPENDOUTPUT)) {
gdwOptions |= HSO_OLDPROJSW_N;
}
/*
* Loop through parameters.
*/
while (--argc) {
p = *++argv;
if (hsIsSwitch(*p)) {
while (c = *++p) {
switch (toupper(c)) {
/*
* Compatibility.
* Chicago/Nashvilled header.
*/
case '4':
gdwOptions &= ~HSO_OLDPROJSW;
gdwOptions |= HSO_OLDPROJSW_4;
break;
/*
* Old bt2 and btb switches to replace internal and
* both block tags.
*/
case 'B':
p++;
if (toupper(*p++) != 'T') {
goto InvalidSwitch;
}
if (toupper(*p) == 'B') {
dwMask = HST_BOTH | HST_USERBOTHBLOCK;
gdwOptions |= HSO_USERBOTHBLOCK;
} else if (*p == '2') {
dwMask = HST_INTERNAL | HST_USERINTERNALBLOCK;
gdwOptions |= HSO_USERINTERNALBLOCK;
} else {
goto InvalidSwitch;
}
if (argc < 3) {
goto InvalidSwitch;
}
/*
* Add these strings as tags and mark them as blocks
*/
argc--, argv++;
phst = hsAddTag(*argv, HST_BEGIN | dwMask);
if (phst == NULL) {
return 0;
}
argc--, argv++;
phst = hsAddTag(*argv, HST_END | dwMask);
if (phst == NULL) {
return 0;
}
break;
/*
* Tag marker
*/
case 'C':
if (argc < 2) {
goto InvalidSwitch;
}
argc--, argv++;
gpszTagMarker = *argv;
*gszMarkerCharAndEOL = *gpszTagMarker;
gdwTagMarkerSize = strlen(gpszTagMarker);
if (gdwTagMarkerSize == 0) {
goto InvalidSwitch;
}
break;
/*
* Compatibility.
* NT SUR header
*/
case 'E':
gdwOptions &= ~HSO_OLDPROJSW;
gdwOptions |= HSO_OLDPROJSW_E;
break;
/*
* Input file
*/
case 'I':
if (argc < 2) {
goto InvalidSwitch;
}
argc--, argv++;
gpszInputFile = *argv;
goto ProcessInputFile;
break;
/*
* Extract file
*/
case 'X':
{
char* pszExtractFile;
BOOL bAppend = FALSE;
if (toupper(*(p+1)) == 'A') {
p++;
bAppend = TRUE;
}
if (argc < 3) {
goto InvalidSwitch;
}
argc--, argv++;
pszExtractFile = *argv;
dwMask = HST_EXTRACT;
if (!hsAddUserDefinedTag(&dwMask, &argc, &argv))
goto InvalidSwitch;
hsAddExtractFile(pszExtractFile, dwMask, bAppend);
break;
}
/*
* Old lt2 and ltb switches to replace internal and
* both tags.
*/
case 'L':
p++;
if (toupper(*p++) != 'T') {
goto InvalidSwitch;
}
if (toupper(*p) == 'B') {
dwMask = HST_BOTH | HST_USERBOTHTAG;
gdwOptions |= HSO_USERBOTHTAG;
} else if (*p == '2') {
dwMask = HST_INTERNAL | HST_USERINTERNALTAG;
gdwOptions |= HSO_USERINTERNALTAG;
} else {
goto InvalidSwitch;
}
if (!hsAddUserDefinedTag(&dwMask, &argc, &argv))
goto InvalidSwitch;
break;
/*
* Compatibility.
* NT header
*/
case 'N':
gdwOptions &= ~HSO_OLDPROJSW;
gdwOptions |= HSO_OLDPROJSW_N;
break;
/*
* Ouput files
*/
case 'O':
if (argc < 3) {
goto InvalidSwitch;
}
argc--, argv++;
gpszPublicFile = *argv;
argc--, argv++;
gpszInternalFile = *argv;
break;
/*
* Compatibility.
* NT SURPlus header
*/
case 'P':
gdwOptions &= ~HSO_OLDPROJSW;
gdwOptions |= HSO_OLDPROJSW_P;
break;
/*
* Split only. Process internal/both tags only. Tags
* including other tags as well (i.e., internal_NT)
* are treated as untagged.
*/
case 'S':
gdwOptions |= HSO_SPLITONLY;
break;
/*
* User defined tags.
*/
case 'T':
switch (toupper(*++p)) {
/*
* Include lines mark with this tag
*/
case 'A':
dwMask = 0;
break;
/*
* Ignore lines marked with this tag (i.e, treated
* as untagged)
*/
case 'I':
dwMask = HST_IGNORE;
break;
/*
* Skip lines marked with this tag (i.e., not
* included in header files)
*/
case 'S':
dwMask = HST_SKIP;
break;
default:
goto InvalidSwitch;
}
if (!hsAddUserDefinedTag(&dwMask, &argc, &argv))
goto InvalidSwitch;
break;
/*
* Version
*/
case 'V':
if (argc < 2) {
goto InvalidSwitch;
}
argc--, argv++;
if (!hsVersionFromString (*argv, strlen(*argv), &gdwVersion)) {
goto InvalidSwitch;
}
break;
/*
* Unknown tags are to be skipped, as opposed to ignored.
*/
case 'U':
gdwOptions |= HSO_SKIPUNKNOWN;
break;
/*
* Invalid switch
*/
default:
InvalidSwitch:
hsLogMsg(HSLM_ERROR | HSLM_NOLINE, "Invalid switch or parameter: %c", c);
// Fall through
/*
* Help
*/
case '?':
goto PrintHelp;
} /* switch (toupper(c)) */
} /* while (c = *++p) */
} else { /* hsIsSwitch(*p) { */
/*
* No switch specified. Process this input file
*/
gpszInputFile = *argv;
break;
}
} /* while (--argc) */
ProcessInputFile:
/*
* Make sure we got input and ouput files.
*/
if ((gpszInputFile == NULL)
|| (gpszPublicFile == NULL)
|| (gpszInternalFile == NULL)) {
hsLogMsg(HSLM_ERROR | HSLM_NOLINE, "Missing input or ouput file");
goto PrintHelp;
}
/*
* Add compatibility tags for default projects (first call only)
*/
if ((gdwOptions & HSO_OLDPROJSW) && !(gdwOptions & HSO_APPENDOUTPUT)) {
if (!(gdwOptions & HSO_OLDPROJSW_4)) {
phst = hsAddTag(gszNT, 0);
if (phst == NULL) {
return 0;
}
phst->dwMask |= HST_MAPOLD;
dwMask = phst->dwMask;
}
if (gdwOptions & HSO_OLDPROJSW_E) {
hsAddTag(gszCairo, dwMask);
hsAddTag(gszSur, dwMask);
hsAddTag(gszWin40, dwMask);
hsAddTag(gsz35, dwMask);
} else if (gdwOptions & HSO_OLDPROJSW_P) {
hsAddTag(gszWin40, dwMask);
hsAddTag(gszWin40a, dwMask);
hsAddTag(gszCairo, dwMask);
hsAddTag(gszSur, dwMask);
hsAddTag(gszSurplus, dwMask);
hsAddTag(gsz35, dwMask);
} else if (gdwOptions & HSO_OLDPROJSW_4) {
gdwOptions |= HSO_INCINTERNAL;
phst = hsAddTag(gszChicago, 0);
if (phst == NULL) {
return 0;
}
phst->dwMask |= HST_MAPOLD;
dwMask = phst->dwMask;
hsAddTag(gszNashville, dwMask);
hsAddTag(gszWin40, dwMask);
hsAddTag(gszWin40a, dwMask);
} else if (!(gdwOptions & HSO_APPENDOUTPUT)) {
gdwOptions |= HSO_OLDPROJSW_N;
}
} /* (gdOptions & HSO_OLDPROJW) */
/*
* Compatibility. If doing split only, don't include internal tags
* in public file
*/
if (gdwOptions & HSO_SPLITONLY) {
gdwOptions &= ~HSO_INCINTERNAL;
}
return argcParm - argc;
PrintHelp:
hsLogMsg(HSLM_DEFAULT, "Header Split Utility. Version 2.1");
hsLogMsg(HSLM_NOLABEL, "Usage: hsplit [options] <-o PublicFile InternalFile> [-i] File1 [-i] File2...");
hsLogMsg(HSLM_NOLABEL, "\t[-4] Generate chicago/nashville headers");
hsLogMsg(HSLM_NOLABEL, "\t[-bt2 BeginStr EndStr] Replace begin_internal/end_internal - Obsolete");
hsLogMsg(HSLM_NOLABEL, "\t[-btb BeginStr EndStr] Replace begin_both/end_both tags - Obsolete");
hsLogMsg(HSLM_NOLABEL, "\t[-c TagMarker] Replace tag marker. default \";\"");
hsLogMsg(HSLM_NOLABEL, "\t[-e] Generate NT sur headers");
hsLogMsg(HSLM_NOLABEL, "\t[[-i] file1 file2 ..] Input files - Required");
hsLogMsg(HSLM_NOLABEL, "\t[-lt2 str] Replace internal tag - Obsolete");
hsLogMsg(HSLM_NOLABEL, "\t[-ltb str] Replace both tag - Obsolete");
hsLogMsg(HSLM_NOLABEL, "\t[-n] Generate NT headers - default");
hsLogMsg(HSLM_NOLABEL, "\t[-x[a] ExtractHeader ExtractTag] Extract files and tags files");
hsLogMsg(HSLM_NOLABEL, "\t[-o PublicHeader InternalHeader] Output files - Required");
hsLogMsg(HSLM_NOLABEL, "\t[-p] Generate NT surplus headers");
hsLogMsg(HSLM_NOLABEL, "\t[-s] Process internal and both tags only");
hsLogMsg(HSLM_NOLABEL, "\t[-ta tag1 tag2 ..] Include lines using these tags");
hsLogMsg(HSLM_NOLABEL, "\t[-ti tag1 tag2 ..] Ignore these tags");
hsLogMsg(HSLM_NOLABEL, "\t[-ts tag1 tag2 ..] Skip lines using these tags");
hsLogMsg(HSLM_NOLABEL, "\t[-u] Skip unknown tags. Default: ignore");
hsLogMsg(HSLM_NOLABEL, "\t[-v] Version number. Default: LATEST_WIN32_WINNT_VERSION");
hsLogMsg(HSLM_NOLABEL, "\r\nTags Format:");
hsLogMsg(HSLM_NOLABEL, "\t<TagMarker>[begin/end][_public/internal][[_tag1][_tag2]...][_if_(str)_version | _version]");
return 0;
}
/***************************************************************************\
* main
*
\***************************************************************************/
int __cdecl main (int argc, char *argv[])
{
int argcProcessed;
/*
* Each loop processes one input file
*/
do {
argcProcessed = hsProcessParameters(argc, argv);
if (argcProcessed == 0) {
break;
}
if (!hsOpenWorkingFiles()
|| !hsSplit()) {
return TRUE;
}
hsCloseWorkingFiles();
gdwOptions |= HSO_APPENDOUTPUT;
argc -= argcProcessed;
argv += argcProcessed;
} while (argc > 1);
return FALSE;
}