|
|
/****************************** 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; }
|