home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Windows Gam…ming Gurus (2nd Edition)
/
Disc2.iso
/
msdn_vcb
/
samples
/
vc98
/
addins
/
api2help
/
apisplit.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1998-04-02
|
13KB
|
386 lines
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//This code is the basis for which the add-in to MSDevStudio
// for generating help files will stem. As of now it splits apart
// the prototype for a function
//This will work on almost every function declaration
// 1) DO NOT use on function pointer declarations. For example:
// "DWORD (CALLBACK* Get)(LPOLESTREAM, void FAR*, DWORD);"
// will fail. The parser gets confused on the (CALLBACK* Get).
// 2) The question arises as to which which do you run this macro on,
// in the header declaration, or in the actual source code.
// If you are generating help for a function not in a class, it
// is probably best to run it on the header file declaration.
// If the function is in a class, try to run it on the source
// declaration because the parser can detect the class scoping
// (although, as of right now parses this class scoping, but does
// nothing with it, except storing it into an array).
// 3) Many OLE 2 declarations are declared with macros,
// WINOLEAPI_(BOOL) OleIsRunning(LPOLEOBJECT pObject);
// the parser is fine with this as long as there are no spaces in
// between the WINOLEAPI_ and (BOOL).
// 4) The parser gets confused if the prototype is something like:
// void foo(CArray<CObject, CObject> bar); This happens when there is
// a template in the parameter list and a comma appears within this
// template declaration. The parser gets confused and tries to set
// each as a parameter, ie CArray<CObject is one parameter, and
// CObject> bar is another.
#include <stdafx.h>
#include <afxtempl.h>
#include <fstream.h>
#include "resource.h"
#include "apisplit.h"
//The following value is described in the comment for GetReturnType
#define DEFAULT_RETURN 1
inline void WriteString(CString strStr, CFile& file)
{ file.Write(strStr, strStr.GetLength()); }
inline void WriteString(int nIDS, CFile& file)
{
CString strStringToWrite;
strStringToWrite.LoadString(nIDS);
WriteString(strStringToWrite, file);
}
void GenerateHTML(CString strHTMLPath, CString strClassFunctionName,
CString strFunctionName,
CArray<CString,CString>& Parameters,
CArray<CString,CString>& ParameterNames, CString strReturn)
{
CFile Stream(strHTMLPath,
CFile::modeCreate|CFile::modeWrite|CFile::shareExclusive);
WriteString(IDS_HTML1, Stream);
WriteString(strFunctionName, Stream);
WriteString(IDS_HTML2, Stream);
WriteString(strClassFunctionName, Stream);
WriteString(IDS_HTML3, Stream);
WriteString(strReturn+" "+strFunctionName,Stream);
WriteString(IDS_HTML4, Stream);
if (Parameters.GetSize() != 0)
{
for (int i = 0 ; i < Parameters.GetSize()-1 ; i++)
{
WriteString(IDS_HTML5, Stream);
WriteString(Parameters.GetAt(i), Stream);
WriteString(IDS_HTML6, Stream);
}
WriteString(IDS_HTML5, Stream);
WriteString(Parameters.GetAt(Parameters.GetSize()-1), Stream);
WriteString(IDS_HTML7, Stream);
}
else
WriteString(IDS_HTML8, Stream);
WriteString(IDS_HTML9, Stream);
for (int i = 0 ; i < ParameterNames.GetSize() ;i++)
{
WriteString(IDS_HTML10, Stream);
WriteString(ParameterNames.GetAt(i), Stream);
WriteString(IDS_HTML11, Stream);
}
//For some reason, the following <dt></dt> sequence is needed to keep
// things straight.in the resulting HTML
WriteString(IDS_HTML12, Stream);
}
void GenerateHelpFile(CString strRTFPath, CString strClassFunctionName,
CString strFunctionName,
CArray<CString,CString>& Parameters,
CArray<CString,CString>& ParameterNames,
CString strReturn, CString ContextID, CString TopicName)
{
CString sStringToWrite;
CFile Stream(strRTFPath,
CFile::modeCreate|CFile::modeWrite|CFile::shareExclusive);
WriteString(IDS_RTF1, Stream);
WriteString(IDS_RTF2, Stream);
WriteString(IDS_RTF3, Stream);
//Send the context ID for the page being generated
WriteString(ContextID, Stream);
//Dump secondary help header
WriteString(IDS_RTF4, Stream);
WriteString("SIMPLE Help Topic 1", Stream);
//More header info
WriteString(IDS_RTF5, Stream);
//Dump the name this is known as in help topics.index dialog
WriteString(TopicName, Stream);
//Output prototype dependant information
WriteString(IDS_RTF6, Stream);
WriteString(strClassFunctionName, Stream);
WriteString(IDS_RTF7, Stream);
WriteString(strReturn+" "+strFunctionName+"(\n", Stream);
WriteString("\\par ", Stream);
if (Parameters.GetSize() != 0)
{
for (int i = 0 ; i < Parameters.GetSize()-1 ; i++)
{
WriteString(" "+Parameters.GetAt(i)+",\n", Stream);
WriteString("\\par\n", Stream);
}
WriteString(" "+Parameters.GetAt(Parameters.GetSize()-1), Stream);
}
WriteString(IDS_RTF8, Stream);
for (int i = 0 ; i < ParameterNames.GetSize() ;i++)
{
WriteString(ParameterNames.GetAt(i)+"\n", Stream);
WriteString(IDS_RTF9, Stream);
}
WriteString(IDS_RTF10, Stream);
Stream.Close();
}
//Because double spaces only get in the way, this routine removes them.
//It also removes spaces around '::' so that we can find scope resolution
void RemoveUnnecessary(CString& str)
{
//First, strip out all those pesky, unwanted double spaces
str.TrimLeft();
str.TrimRight();
int nLoc = str.Find(" ");
while (nLoc > 0)
{
str = str.Left(nLoc) + str.Right(str.GetLength()-nLoc-1);
nLoc = str.Find(" ");
}
//Now get rid of and ' ::' or ':: '
nLoc = str.Find(" ::");
while(nLoc > 0)
{
str = str.Left(nLoc) + str.Right(str.GetLength()-nLoc-1);
nLoc = str.Find(" ::");
}
nLoc = str.Find(":: ");
while(nLoc > 0)
{
str = str.Left(nLoc+2) + str.Right(str.GetLength()-nLoc-3);
nLoc = str.Find(":: ");
}
}
void GetFunctAndScope(CString& strFuncName, CArray<CString,CString>& Scoping,
CString& strNewFunc)
{
strNewFunc = strFuncName;
int nLoc = strNewFunc.Find("::");
while (nLoc > 0)
{
Scoping.Add(strNewFunc.Left(nLoc));
strNewFunc = strNewFunc.Right(strNewFunc.GetLength()-nLoc-2);
nLoc = strNewFunc.Find("::");
}
}
void ConvertWSToSpace (CString& str)
{
//To fix the problem of when there is a comment describing parameters,
// the first step is to scan the string, and see if there are any '//'
int nLoc = str.Find("//");
while (nLoc != -1)
{
//There is a '//', so we then take the string from there to the
// end of the string, and find a '\n'
CString strComment = str.Right(str.GetLength()-nLoc);
str = str.Left(nLoc);
//within comment, search for the '\n'
int nCRLoc = strComment.Find('\n');
if (nCRLoc != -1)
{
CString strDecommented = strComment.Right(
strComment.GetLength()-nCRLoc);
str += strDecommented;
//An enhancement would be to save this comment, and use it
// to describe the parameter in the help file
nLoc = str.Find("//");
}
else
{
nLoc = -1;
}
}
//Next, a search for the old style comments (/**/) is performed
nLoc = str.Find("/*");
while(nLoc != -1)
{
CString strComment = str.Right(str.GetLength()-nLoc);
str = str.Left(nLoc);
//within the comment, search for the closing '*/'
int nEndComm = strComment.Find("*/");
if (nEndComm != -1)
{
CString strDecommented = strComment.Right(
strComment.GetLength()-nEndComm-2);
str += strDecommented;
//An enhancement would be to save this comment,
// and use it to describe the parameter in the help file
nLoc = str.Find("/*");
}
else
{
nLoc = -1;
}
}
nLoc = str.Find("\t");
while(nLoc != -1)
{
char foo = str.GetAt(nLoc);
str.SetAt(nLoc, ' ');
nLoc = str.Find("\t");
}
nLoc = str.Find("\n");
while(nLoc != -1)
{
char foo = str.GetAt(nLoc);
str.SetAt(nLoc, ' ');
nLoc = str.Find("\n");
}
/*for (int i = 0 ; i < str.GetLength()-1 ; i++)
if ((str[i] == '\t') || (str[i] == '\n'))
str.SetAt(i, ' ');*/
}
void GetReturnType(CString& str, CArray<CString,CString>& ReturnsArray,
CString& strSuggested, int nAppendStar)
{
//There are many conflicts that could arise from
// finding the return type, for example look at the prototype
// from the windows header files for FreeLibrary:
// WINBASEAPI BOOL WINAPI FreeLibrary(HMODULE hLibModule);
// If we start at FreeLibrary and scan backwards for the first
// word, we have WINAPI as the return type. If we start at
// the beginning of the line and scan foreward for the first
// word, we have WINBASEAPI as the return type. Things could
// also get more complicated, we could start throwing FAR's,
// _declspec's, and much more (static _declspec BOOL FAR foo(char*))
// The way this is remedied is as follows:
// 1) Count the number of items that appears before the function name
// 2) if Count == 0, no return type is assumed
// if Count == 1, use the found return type
// if Count >= 2, use the DEFAULT_RETURN word as the return type
// If the wrong word is grabbed, it is trivial to change it in the
// help file, but under most circumstances this should work.*/
//we know the string is of the form: words words ... funcname
str = str.Left(str.ReverseFind(' '));
str.TrimRight();
if (str.GetLength() != 0)
{
int nEndOfItem = str.Find(' ');
while ((str.GetLength() != 0) && (nEndOfItem != -1))
{
ReturnsArray.Add(str.Left(nEndOfItem));
str = str.Right(str.GetLength()-nEndOfItem);
str.TrimLeft();
str.TrimRight();
nEndOfItem = str.Find(' ');
}
ReturnsArray.Add(str);
//Right now there could possibly be a problem with pointers, if the
// prototype is of the form HWND *foo(...) the pointer is attached to
// the function name, when in actuality the '*' belongs with HWND.
// Also there is the case when the prototype is HWND * foo(...), it
// ends up that * is viewed as a return type, that is fixed up here.
for (int i = 0 ; i < ReturnsArray.GetSize() ; i++)
{
//Check to see if the element is a '*'
if (ReturnsArray.GetAt(i) == "*")
{
//Delete it...
ReturnsArray.RemoveAt(i);
//Change old value before it
ReturnsArray.SetAt(i-1, ReturnsArray.GetAt(i-1) + "*");
}
}
//Check for the HWND *foo(...) case
for (i = nAppendStar ; i > 0 ; i--)
ReturnsArray.SetAt(ReturnsArray.GetSize()-1,
ReturnsArray.GetAt(ReturnsArray.GetSize()-1) + " *");
//Here we decide which value we use as the return type,
// there probably is a better way of calculating this, but that
// will be
// left until later.
if (ReturnsArray.GetSize() == 1)
strSuggested = ReturnsArray.GetAt(0);
else
{
//If DEFAULT_RETURN is greater than the actual number of possible
// return types, then give back the last possible one
if (DEFAULT_RETURN > ReturnsArray.GetSize())
strSuggested = ReturnsArray.GetAt(ReturnsArray.GetSize()-1);
else
strSuggested = ReturnsArray.GetAt(DEFAULT_RETURN);
}
}
}
void GetListOfParamNames(CArray<CString,CString>& ParamList,
CArray<CString,CString>& ParamNames)
{
for (int i = 0 ; i < ParamList.GetSize() ; i++)
{
CString strTemp = ParamList.GetAt(i);
strTemp = strTemp.Right(strTemp.GetLength()-strTemp.ReverseFind(' ')-1);
while (strTemp[0] == '*')
strTemp = strTemp.Right(strTemp.GetLength()-1);
ParamNames.Add(strTemp);
}
}
int GetParameters(CString& strParameters, CString& strPrototype,
CArray<CString,CString>& ParamList)
{
//Start off by getting to the end of the argument list
strParameters = strPrototype.Left(strPrototype.ReverseFind(')'));
strParameters.TrimRight();
int nBeginningOfParameters = strParameters.ReverseFind('(');
strParameters = strParameters.Right(strParameters.GetLength()-
nBeginningOfParameters-1);
strParameters.TrimLeft();
//now pull off each parameter
if (strParameters.GetLength() != 0)
{
int nComma = strParameters.Find(',');
while (nComma != -1)
{
ParamList.Add(strParameters.Left(nComma));
strParameters = strParameters.Right(strParameters.GetLength()-
nComma-1);
strParameters.TrimLeft();
strParameters.TrimRight();
nComma = strParameters.Find(',');
}
ParamList.Add(strParameters);
}
return nBeginningOfParameters;
}