home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 17
/
CD_ASCQ_17_101194.iso
/
vrac
/
cvtini.zip
/
CVTINI.C
next >
Wrap
C/C++ Source or Header
|
1994-08-26
|
22KB
|
873 lines
/* Copyright (C) 1994 by Premia Corporation. All rights reserved. */
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>
#include <io.h> // needed only for call to _access
#define COPYCOMMENTS // copy lines that are commented out
#define SEC_DEFAULTKMAP (1)
#define SEC_KMAPASSIGN (2)
#define SEC_LIBPRELOAD (3)
#define SEC_HELP (4)
#define SEC_COMPILER (5)
#define SEC_RIBBON (6)
#define SEC_MENU (7)
#define SEC_HELPER (8)
// iniAction values
#define IA_COPY (0x001) // Copy this line
#define IA_CHECKNAME (0x002) // Check against the valid list and warn if necessary
#define IA_WARNSECTION (0x004) // Warn about the section
#define IA_COMMENTOUT (0x008) // Comment out this line in the output, if COPY is set
#define IA_CONVERT (0x010) // Change the name if it's in the conversion map; comment out otherwise.
#define IA_CHECKALL (0x020) // Check all strings on the input line (for key bindings)
#define IA_ADDSECTION (0x040) // Create a needed section because there wasn't one already
#define IA_NOCHECK (0x080) // Don't check this line (primarily for comments)
// iniError values
#define IE_BADAPI (0x0001) // API call not supported in Fusion
#define IE_CHANGEDAPI (0x0002) // API call that acts differently in Fusion
#define IE_NOCONVERSION (0x0004) // Library or keymap that couldn't be converted
#define IE_OKCONVERSION (0x0008) // Library or keymap that was converted
#define IE_COMMENTEDOUT (0x0010) // unsupported item commented out in output
#define IE_OTHERSECTION (0x0020) // item in unsupported section (not currently handled)
#define IE_HASHELPER (0x0040) // Input file already has [Helper] section
#define IE_HASLDRAW (0x0080) // Output file already has LibPreload=cwvldraw.dll
#define IE_HASCTL3D (0x0100) // Output file already has LibPreload=cwvctl3d.dll
#define IE_HELPERERROR (0x0200) // [Helper] section couldn't be added
#define IE_BADDEFKMAP (0x0400) // Couldn't convert DefaultKeymap--cwvcua used instead.
#define HELPERNAME ("[Helper]")
#define HELPERSTUFF ("Browse=0\nExactMatch=0\nUse_MSVC_Help=0\nCWHelpSearchPath=C:\\CWVC;C:\\MSVC\\HELP\n")
#define PRSTR(x) ((x)?(x):"<null>")
#define IOBUSIZ (1024) // max. length of input line (including null byte)
char *strRepStr (char *targPat, char *repPat, char *inStr);
static char *nexttok (const char *str, char *buf, const char *sep);
char *strSave (char *str);
char *convertName (char *call);
int checkName (char *call);
char *strSave (char *str);
char *stripDecorations (char *str, char *preBuf, char *sufBuf,
const char *baubles);
char *reDecorate (char *str, char *preBuf, char *sufBuf);
int dispatch (char *sectionName, char *lineBuf,
char *apiCall, int action);
int convertIni (char *fileName);
void blurb (char *progName, char *inputFile, int errorLevel);
// characters outside of library/API/keymap/section names
const char *symbolWhitespace = " \t\n;\"'<,>.`~!@#$%^&*()-+={}[]:?/|\\";
// characters outside of input tokens
const char *inputWhitespace = " \t=\n\"',.()";
long cvtOutputLineNumber = 1;
FILE *cvtFpIn, *cvtFpOut, *cvtFpErr;
/*
* Probably want to change this to write to a named file
* and send error and warning messages to stdout so they
* can be redirected easily.
*/
main(int c, char **v)
{
char *inputName = NULL;
int errorLevel;
int confirm (char *fileName);
if (!v[1])
{
cvtFpIn = stdin;
inputName = "Standard input";
}
else
{
if (!(cvtFpIn = fopen(v[1], "r")))
{
perror(v[1]);
exit(-1);
}
inputName = v[1];
if (v[2])
{
if (!_access(v[2], 0)) // file exists
{
if (!confirm(v[2]))
exit(-1);
}
if (!(cvtFpOut = fopen(v[2], "w")))
{
perror(v[2]);
fclose(cvtFpIn);
exit(-1);
}
}
else
cvtFpOut = stdout;
}
if (cvtFpOut == stdout)
cvtFpErr = stderr;
else
cvtFpErr = stdout;
errorLevel = convertIni(inputName);
blurb(v[0], inputName, errorLevel);
if (cvtFpIn != stdin)
fclose(cvtFpIn);
if (cvtFpOut != stdout)
fclose(cvtFpOut);
exit(0);
}
int
confirm(char *fileName)
{
int c;
fprintf(stderr, "%s exists. Do you want to overwrite it? ", fileName);
while ((c = getchar()) != EOF && toupper(c) != 'Y' && toupper(c) != 'N')
;
if (c == EOF || c == 'n' || c == 'N')
return(0);
return(1);
}
/*
* Have a little heart-to-heart with the user advising them that
* their system flags weren't checked (so that some unsupported
* flags may be getting set with SysSetDefault and such).
*/
void
blurb(char *progName, char *inputFile, int errorLevel)
{
fprintf(cvtFpErr, "\n\t%s has converted %s\n", progName, inputFile);
fprintf(cvtFpErr, "\tfor use with Fusion.\n");
if (!errorLevel)
{
fprintf(cvtFpErr, "\tThe conversion was entirely successful\n\n.");
return;
}
if (errorLevel & IE_BADAPI)
{
fprintf(cvtFpErr, "\n\t%s contained one or more calls to\n", inputFile);
fprintf(cvtFpErr, "\tCodewright functions not supported in Fusion.\n");
}
if (errorLevel & IE_CHANGEDAPI)
{
fprintf(cvtFpErr, "\n\t%s contained one or more calls to\n", inputFile);
fprintf(cvtFpErr, "\tCodewright functions that have different meaning in Fusion.\n");
}
if (errorLevel & IE_NOCONVERSION)
{
fprintf(cvtFpErr, "\n\t%s contained one or more references to\n", inputFile);
fprintf(cvtFpErr, "\tCodewright libraries or keymaps that have no equivalent in Fusion.\n");
fprintf(cvtFpErr, "\tAny functions contained in those libraries or keymaps\n");
fprintf(cvtFpErr, "\twill be unavailable unless you relink them for Fusion.\n");
}
if (errorLevel & IE_OKCONVERSION)
{
fprintf(cvtFpErr, "\n\t%s contained one or more references to\n", inputFile);
fprintf(cvtFpErr, "\tCodewright libraries or keymaps that were converted\n");
fprintf(cvtFpErr, "\tto their Fusion equivalents.\n");
}
if (errorLevel & IE_COMMENTEDOUT)
{
fprintf(cvtFpErr, "\n\tItems in %s that were not consistent with\n", inputFile);
fprintf(cvtFpErr, "\tFusion, and that could not be converted to Fusion equivalents,\n");
fprintf(cvtFpErr, "\twere copied to the new file as comments. These items appear\n");
fprintf(cvtFpErr, "\tin the output file preceded by ';cvt: '.\n");
}
if (errorLevel & IE_BADDEFKMAP)
{
fprintf(cvtFpErr, "\n\tThe default keymap in %s could not be\n", inputFile);
fprintf(cvtFpErr, "\tconverted to a Fusion equivalent. Cwvcua was substituted instead.\n");
}
if (!(errorLevel & IE_HASHELPER))
{
fprintf(cvtFpErr, "\n\tThere was no [Helper] section in %s,\n", inputFile);
fprintf(cvtFpErr, "\tso a default was supplied. Check the paths in that section\n");
fprintf(cvtFpErr, "\tto verify that they are appropriate for your setup.\n");
}
if (errorLevel)
fprintf(cvtFpErr, "\n\tConsult your Fusion Companion Reference for more information.\n");
fprintf(cvtFpErr, "\n");
}
int
convertIni(char *fileName)
{
static char iobu[IOBUSIZ];
static char tokbu[IOBUSIZ];
char *p;
char *iop;
char *sectionName = NULL;
int sectionType = 0;
int iniAction = 0;
int errorLevel = 0;
char *outStr;
while (fgets(iobu, IOBUSIZ, cvtFpIn))
{
if (feof(cvtFpIn))
break;
if (!(iop = nexttok(iobu, tokbu, inputWhitespace)) || !strlen(tokbu))
continue;
if (tokbu[0] == ';') // the line is commented out
#ifdef COPYCOMMENTS
continue;
#else
dispatch(NULL, iobu, NULL, IA_COPY);
#endif
iniAction = 0;
if ((p = strchr(iobu, '\r')) || (p = strchr(iobu, '\n')))
*p = 0;
if (tokbu[0] == '[') // section header
{
if (p = strchr(tokbu, ']'))
{
p[1] = 0;
// iniAction = 0;
if (sectionName)
free(sectionName);
sectionName = strSave(tokbu);
if (!_stricmp(sectionName, "[DefaultKeymap]"))
sectionType = SEC_DEFAULTKMAP;
else if (!_stricmp(sectionName, "[KmapAssign]"))
sectionType = SEC_KMAPASSIGN;
else if (!_stricmp(sectionName, "[LibPreLoad]"))
sectionType = SEC_LIBPRELOAD;
else if (!_stricmp(sectionName, "[Help]"))
{
sectionType = SEC_HELP;
iniAction = IA_WARNSECTION;
}
else if (!_stricmp(sectionName, "[Helper]"))
{
sectionType = SEC_HELPER;
errorLevel = IE_HASHELPER;
}
else if (!_stricmp(sectionName, "[Compiler]"))
{
sectionType = SEC_COMPILER;
iniAction = IA_WARNSECTION;
}
else if (!_stricmp(sectionName, "[Ribbon]"))
{
sectionType = SEC_RIBBON;
iniAction = IA_WARNSECTION;
}
else if (!_stricmp(sectionName, "[Menu]"))
{
sectionType = SEC_MENU;
iniAction = IA_WARNSECTION;
}
else
sectionType = -1; // something unspecified
// copy the line
errorLevel |= dispatch(NULL, sectionName, NULL, iniAction | IA_COPY);
}
continue;
}
outStr = NULL;
switch(sectionType)
{
case SEC_DEFAULTKMAP:
nexttok(iop, tokbu, inputWhitespace); // no default keymap?!
iniAction = IA_COPY | IA_CONVERT;
break;
case SEC_KMAPASSIGN:
iniAction = IA_COPY | IA_CHECKALL;
break;
case SEC_LIBPRELOAD:
nexttok(iop, tokbu, inputWhitespace); // empty LibPreload is OK
iniAction = IA_COPY | IA_CONVERT;
break;
case SEC_HELP:
case SEC_COMPILER:
case SEC_RIBBON:
case SEC_MENU:
iniAction = IA_COPY | IA_COMMENTOUT | IA_WARNSECTION;
break;
case 0: // no section
iniAction = IA_COPY | IA_COMMENTOUT | IA_WARNSECTION;
break;
default: // other section
iniAction = IA_COPY | IA_CHECKNAME;
break;
}
if (sectionType == SEC_DEFAULTKMAP) // critical section
{
int tmpError = 0;
tmpError = dispatch(sectionName, iobu, tokbu, iniAction);
if (tmpError & IE_NOCONVERSION)
{
char *p;
if (p = strRepStr(tokbu, "cwvcua", iobu))
{
tmpError = dispatch(sectionName, p, NULL, IA_COPY);
free(p);
}
errorLevel |= IE_BADDEFKMAP;
}
else
{
errorLevel |= tmpError;
}
}
else
{
#if 0
char *p;
if (p = strchr(tokbu))
{
*p++ = 0;
errorLevel |= dispatch(sectionName, iobu, tokbu, IA_COPY | IA_CONVERT);
}
#endif
errorLevel |= dispatch(sectionName, iobu, tokbu, iniAction);
}
}
if (!(errorLevel & IE_HASHELPER))
errorLevel |= dispatch(HELPERNAME, HELPERSTUFF, NULL, IA_ADDSECTION);
return(errorLevel);
}
/*
* There are four things that can happen to a line of input:
* 1) it can get ignored
* 2) it can get copied to output
* 3) it can get turned into a comment and copied to output
* 4) it can undergo a substring substitution and get copied to output
*/
int
dispatch(char *sectionName, char *lineBuf, char *apiCall, int action)
{
char *lineOut = lineBuf;
char *newAPICall = NULL;
char *strip;
char suf[256];
char pre[256];
int checkErr;
int errorLevel = 0;
// If we're emitting a section name, precede with a blank line
// Assume that lineeOut doesn't change when sectionName is NULL.
if (lineOut && !sectionName && (action & IA_COPY))
{
fprintf(cvtFpOut, "\n");
++cvtOutputLineNumber;
}
if (!sectionName && (action & IA_WARNSECTION))
{
fprintf(cvtFpErr, "Line %ld: %s is not a standard section in Fusion\n",
cvtOutputLineNumber, PRSTR(lineBuf));
errorLevel |= IE_OTHERSECTION;
}
// apiCall may be of the form library[.dll]:apiname.
// Find the API call in there and check it.
if (action & IA_CHECKNAME)
{
char *p;
if (p = strchr(apiCall, ':'))
{
action |= IA_CONVERT;
p++;
}
else
p = apiCall;
strip = stripDecorations(p, pre, suf, symbolWhitespace);
if ((checkErr = checkName(strip)) > 1)
{
fprintf(cvtFpErr, "Line %ld: '%s' is not supported in Fusion\n",
cvtOutputLineNumber, PRSTR(strip));
action |= (IA_COPY | IA_COMMENTOUT);
errorLevel |= IE_BADAPI;
}
else if (checkErr == 1)
{
fprintf(cvtFpErr,
"Line %ld: '%s' has special meaning in Fusion--see Companion Reference\n",
cvtOutputLineNumber, PRSTR(strip));
action |= (IA_COPY | IA_COMMENTOUT);
errorLevel |= IE_CHANGEDAPI;
}
else
action |= IA_COPY;
free(strip);
}
if (action & IA_CHECKALL)
{
int erroneous = 0;
// reuse strip and suf here
for (strip = lineBuf;
strip = nexttok(strip, suf, " \t;\"'<,>.`~!@#$%^&*()-+={}[]:?/|\\"); )
{
if ((checkErr = checkName(suf)) > 1)
{
fprintf(cvtFpErr, "Line %ld: '%s' is not supported in Fusion\n",
cvtOutputLineNumber, PRSTR(suf));
erroneous = 1;
errorLevel |= IE_BADAPI;
}
else if (checkErr == 1)
{
fprintf(cvtFpErr,
"Line %ld: '%s' has special meaning in Fusion--see Companion Reference\n",
cvtOutputLineNumber, PRSTR(suf));
erroneous = 1;
errorLevel |= IE_CHANGEDAPI;
}
}
if (erroneous)
action |= (IA_COPY | IA_COMMENTOUT);
else
action |= IA_COPY;
}
// apiCall may be of the form library[.dll]:apiname.
// Find the library name in there and check/convert it.
// Or it may be a keymap, so ignore the above.
if (action & IA_CONVERT)
{
char *p;
char buf[128];
if ((p = strchr(apiCall, '.')) || (p = strchr(apiCall, ':')))
{
strncpy(buf, apiCall, p - apiCall);
buf[p - apiCall] = 0;
}
else
strcpy(buf, apiCall);
strip = stripDecorations(buf, pre, suf, symbolWhitespace);
if (!(newAPICall = convertName(strip)))
{
fprintf(cvtFpErr, "Line %ld: '%s' has no equivalent in Fusion\n",
cvtOutputLineNumber, PRSTR(strip));
action |= (IA_COPY | IA_COMMENTOUT);
errorLevel |= IE_NOCONVERSION;
}
else
{
fprintf(cvtFpErr, "Line %ld: '%s' has been replaced with '%s'\n",
cvtOutputLineNumber, buf, PRSTR(newAPICall));
action |= IA_COPY;
lineOut = strRepStr(strip, newAPICall, lineBuf);
errorLevel |= IE_OKCONVERSION;
}
free(strip);
}
if (lineOut && (action & IA_COPY))
{
char *p;
if (action & IA_COMMENTOUT)
{
fprintf(cvtFpOut, ";cvt: ");
errorLevel |= IE_COMMENTEDOUT;
}
fprintf(cvtFpOut, "%s\n", PRSTR(lineOut));
// account for the newline in the above fprintf
++cvtOutputLineNumber;
// sync line numbers in case lineOut had newlines in it
for (p = lineOut; p = strchr(p, '\n'); ++p)
++cvtOutputLineNumber;
}
if (action & IA_ADDSECTION)
{
fprintf(cvtFpOut, "\n%s\n", PRSTR(sectionName));
fprintf(cvtFpOut, "%s\n", PRSTR(lineOut));
}
if (lineOut && lineOut != lineBuf)
free(lineOut);
return(errorLevel);
}
char *
strSave(char *str)
{
int len;
char *memp = NULL;
if (str)
if (memp = malloc((len = strlen(str)) + 1))
{
strncpy(memp, str, len);
memp[len] = 0;
}
return(memp);
}
/* Look for the next substring in <base> which is delimited by characters
* in the string <sep>. If it's there, copy it into <buf> and return
* a pointer to the next starting point in <base>. Otherwise, or on
* bad arguments, return NULL. The stdlib function strtok() has similar
* functionality, but it's less convenient and not reentrant.
*
*/
static char *
nexttok(const char *str, char *buf, const char *sep)
{
char *bufBase = buf;
// Handle aberrant arguments and the end-of-input case
if (buf)
*buf = 0;
if (!str || !*str)
return(NULL);
if (!sep)
sep = "";
// Skip any leading separators.
while (*str && strchr(sep, *str))
++str;
if (!*str) // no valid token characters in the input stream
return(NULL);
if (buf)
{
while (*str && !strchr(sep, *str)) // Copy the good stuff.
*buf++ = *str++;
*buf = 0;
}
else // just skip to the next separator or end-of-input
{
while (*str && !strchr(sep, *str))
str++;
}
return((char *)str); // Yep, give back this token
}
/*
* Return an allocated string which is a copy of str, with
* every occurrence of targPat replaced with repPat.
*/
char *
strRepStr(char *targPat, char *repPat, char *inStr)
{
char *targPos; // pointer into the input string
char *buf = NULL; // holds partial result
char *outStr; // output string after each replacement
int dot = 0; // offset of target in input string
int repLen; // length of replacement string
int targLen; // length of target string
repLen = strlen(repPat);
targLen = strlen(targPat);
if (!targPat || !repPat || !inStr)
return(NULL);
if (!(outStr = strSave(inStr)))
return(NULL);
while (targPos = strstr(outStr + dot, targPat))
{
dot = targPos - outStr;
if (!(buf = malloc(strlen(outStr) + (repLen - targLen) + 1)))
{
free(outStr);
return(NULL);
}
strncpy(buf, outStr, dot);
strncpy(buf + dot, repPat, repLen);
strcpy(buf + dot + repLen, targPos + targLen);
free(outStr);
outStr = buf;
dot += repLen;
}
return(outStr);
}
char *nonFusionItems[] =
{
"Browse",
"BrowseQFilename",
"BrowseSetFile",
"BufDiff",
"CompilerAdd",
"CompilerAddBuild",
"CompilerAssign",
"CompilerNewExt",
"CWHelpDefaultName",
"CWHelpSDKName",
"CWUseQuickHelp",
"ExecCompile",
"ExecDebug",
"ExecMake",
"ExecRebuild",
"ExecRun",
"MenuAddKeyString",
"MenuCommand",
"MenuDelete",
"MenuDeleteItem",
"MenuGetId",
"MenuGetItemId",
"MenuGetItemPos",
"MenuGetPos",
"MenuInsert",
"MenuInsertItem",
"MenuQCount",
"MenuQHandle",
"MenuQItemCount",
"MenuRegisterHandler",
"MenuRegisterInitializer",
"MouseCreateWin",
"RibbonAddBitmap",
"RibbonAddButton",
"RibbonAddControl",
"RibbonAddIcon",
"RibbonAddItem",
"RibbonControlAssign",
"RibbonControlPos",
"RibbonDelControl",
"RibbonQBinding",
"RibbonQHeight",
"RibbonQUnusedID",
"RibbonQWidth",
"RibbonRedraw",
"RibbonSetHeight",
"RibbonSetWidth",
"RibbonViewSideBar",
"SideBarControl",
"SysLoadDesktopBitmap",
"SysQuit",
"SysSetFileLocking",
"WinQHClient",
"WinQHInstance",
"WinQHRibbon",
"WinSetCreationPos",
NULL
};
char *changedFusionItems[] =
{
"BufCreate",
"BufQViews",
"ErrorNext",
"SysSetFlags",
"WinQHFrame",
NULL
};
char *cwvcSections[] =
{
"DefaultKeymap",
"KmapAssign",
"LibPreload",
"Editor",
"Printer",
"Helper",
"fmatch",
"SpellCheck",
NULL
};
char *cwrightSections[] =
{
"DefaultKeymap",
"KmapAssign",
"LibPreLoad",
"Editor",
"Colors",
"Printer",
"Definitions",
"Compiler",
"VersionControl",
NULL
};
/*
* Who knows? Maybe this is too slow?
*/
int
checkName(char *call)
{
char **vp;
if (call)
{
for (vp = nonFusionItems; *vp; ++vp)
{
if (!strnicmp(*vp, call, strlen(*vp)))
return(2);
}
for (vp = changedFusionItems; *vp; ++vp)
{
if (!strnicmp(*vp, call, strlen(*vp)))
return(1);
}
}
return(0);
}
/*
* If there's no valid keymap name, print fatal error.
* If there are no errors, say so.
* Otherwise, print exit-with-warning status.
*/
char *changedNameTab[] =
{
"cua", "cwvcua",
"brief", "cwvbrief",
"vi", "cwvvi",
"epsilon", "cwvepsln",
"cwctl3d", "cwvctl3d",
"cwldraw", "cwvldraw",
NULL, NULL
};
char *
convertName(char *call)
{
char **vp;
char *callBu;
char *p;
if (call)
{
callBu = strSave(call);
// could be 'LibAutoLoad=dogface: kid' or 'LibAutoLoad=dogface(kid)'
// or 'LibPreload=dogface.dll'
if (p = strchr(callBu, '.'))
*p = 0;
if (p = strchr(callBu, ':'))
*p = 0;
if (p = strchr(callBu, '('))
*p = 0;
for (vp = changedNameTab; vp[0] && vp[1]; vp += 2)
{
if (!stricmp(*vp, callBu))
{
free(callBu);
return(vp[1]);
}
}
free(callBu);
}
return(NULL);
}
/*
* Strips characters in a specified set from the beginning
* and end of str. Returns an allocated string consisting
* of the input string without leading or trailing decoration. If
* preBuf and sufBuf are non-NULL, prefix and suffix ornamentation
* is copied into them. The function assumes that preBuf and
* sufBuf, if not NULL, are large enough to hold the decoration.
*/
char *
stripDecorations(char *str, char *preBuf, char *sufBuf, const char *baubles)
{
char *stripStr;
char *stripP;
if (!str || !*str || !baubles)
return(NULL);
stripStr = stripP = malloc(strlen(str) + 1);
if (preBuf)
{
while (*str && strchr(baubles, *str))
*preBuf++ = *str++;
*preBuf = 0;
}
else
{
while (*str && strchr(baubles, *str))
str++;
}
while (*str && !strchr(baubles, *str))
*stripP++ = *str++;
*stripP = 0;
if (sufBuf)
{
while (*str && strchr(baubles, *str))
*sufBuf++ = *str++;
*sufBuf = 0;
}
else
{
while (*str && strchr(baubles, *str))
str++;
}
return(stripStr);
}
/*
* Restores decoration to the given string.
* Returns an allocated string consisting of the input string with
* preBuf prepended and sufBuf appended. Either may be NULL.
*/
char *
reDecorate(char *str, char *preBuf, char *sufBuf)
{
int preLen;
int sufLen;
int strLen;
char *newStr;
if (!str)
return(NULL);
if (preBuf)
preLen = strlen(preBuf);
else
preLen = 0;
if (sufBuf)
sufLen = strlen(sufBuf);
else
sufLen = 0;
strLen = strlen(str);
if (newStr = malloc(strLen + preLen + sufLen + 1))
{
if (preBuf)
strncpy(newStr, preBuf, preLen);
strncpy(newStr + preLen, str, strLen);
if (sufBuf)
strncpy(newStr + preLen + strLen, sufBuf, sufLen);
newStr[preLen + strLen + sufLen] = 0;
}
return(newStr);
}