1371 lines
31 KiB
C
1371 lines
31 KiB
C
/*
|
|
ventura.c - Module to output the data.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <assert.h>
|
|
|
|
#include "types.h"
|
|
#include "docfmt.h"
|
|
#include "text.h"
|
|
#include "ventura.h"
|
|
#include "process.h"
|
|
#include "errstr.h"
|
|
|
|
|
|
int VenLineOut(FILE * fpoutfile, char * pch, int wState);
|
|
|
|
/* Formatting codes to output for ventura word formatting.
|
|
*/
|
|
char *pchVenparm="<MI>";
|
|
char *pchVenfunc="<B>";
|
|
char *pchVenelem="<B>";
|
|
char *pchVendefault="<D>";
|
|
|
|
|
|
#define NUMFLAGTYPES 8
|
|
#define REGISTERS 0
|
|
#define REGRETURN 1
|
|
#define REGCONDITION 2
|
|
#define PARAMETERS 3
|
|
#define PARAMRETURN 4
|
|
#define FIELD1 5
|
|
#define FIELD2 6
|
|
#define FIELD3 7
|
|
|
|
|
|
/* "output" modes for the line out routines. These
|
|
* signify what sort of formatting should be done.
|
|
*/
|
|
#define TEXT 0x0
|
|
#define PARM 0x1
|
|
#define FUNC 0x2
|
|
#define STRUCT 0x3
|
|
#define ELEMENT 0x4
|
|
|
|
#define OLDSTYLE 0x80
|
|
#define NEWSTYLE 0x40
|
|
|
|
/*
|
|
* @doc VENTURA
|
|
* @api void | VenturaBlockOut | Central entry point for outputing a
|
|
* Ventura format outerlevel block.
|
|
*
|
|
* @parm aBlock * | pBlock | Pointer to block structure.
|
|
* @parm FILE * | ofile | Output file pointer.
|
|
*
|
|
* @comm Call this to get something output in ventura.
|
|
*
|
|
*/
|
|
void VenturaBlockOut( aBlock *pBlock, FILE *ofile)
|
|
{
|
|
VenfuncOut(pBlock, ofile);
|
|
}
|
|
|
|
|
|
|
|
/*************************************************************
|
|
*
|
|
* LINE OUT STUFF
|
|
*
|
|
*************************************************************/
|
|
|
|
/* @doc INTERNAL
|
|
*
|
|
* @func void | VentextOut | This outputs the given text lines. Uses
|
|
* <f VenLineOut> to expand formatting codes.
|
|
*
|
|
* @parm FILE * | file | Specifies the output file.
|
|
* @parm aLine * | line | Specifies the text to output.
|
|
*
|
|
* @xref VenLineOut
|
|
*
|
|
*/
|
|
void VentextOut( FILE *file, aLine *line, BOOL fLineSeps )
|
|
{
|
|
int wMode = TEXT;
|
|
|
|
for (; line != NULL; line = line->next) {
|
|
wMode = VenLineOut( file, line->text, wMode );
|
|
if (fLineSeps)
|
|
fprintf(file, "\n");
|
|
}
|
|
|
|
if (wMode != TEXT) {
|
|
fprintf(errfp, "Warning: Runaway formatting code with no close.\n");
|
|
fprintf(file, "<D>"); // is this right?
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* @doc INTERNAL
|
|
*
|
|
* @func void | VentextOutLnCol | This outputs the given text lines,
|
|
* with each line separated by a newline. If a new paragraph occurs, it is
|
|
* prefixed by the column prefix code <p pColHead>.
|
|
*
|
|
* @parm FILE * | file | Specifies the output file.
|
|
* @parm aLine * | line | Specifies the text lines to output.
|
|
* @parm char * | pColHead | Column header string to prefix new
|
|
* paragraphs with.
|
|
*
|
|
* @comm Uses <f VenLineOut> to expand formatting codes.
|
|
*
|
|
* @xref VentextOut, VenLineOut
|
|
*
|
|
*/
|
|
void VentextOutLnCol( FILE *file, aLine *line, char *pColHead )
|
|
{
|
|
|
|
int wMode = TEXT;
|
|
|
|
for (; line != NULL; line = line->next) {
|
|
if (*(line->text) == '\0') {
|
|
/* Print warning if a formatting code is being
|
|
* continued across a para boundry.
|
|
*/
|
|
if (wMode != TEXT) {
|
|
fprintf(errfp, "Warning: formatting code"
|
|
"crosses paragraph boundry.\n");
|
|
}
|
|
|
|
/* blank line, need new paragraph header */
|
|
fprintf(file, "\n%s", pColHead);
|
|
}
|
|
else {
|
|
/* Otherwise, normal line, print the line as usual */
|
|
wMode = VenLineOut(file, line->text, wMode);
|
|
fprintf(file, "\n");
|
|
}
|
|
}
|
|
|
|
if (wMode != TEXT) {
|
|
fprintf(errfp, "Warning: Runaway formatting code with no"
|
|
"close before para end.\n");
|
|
fprintf(file, "<D>\n"); // is this right?
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func int | VenLineOut | Output the given text line, expanding any
|
|
* character/word formatting control codes to the appropriate ventura
|
|
* control codes.
|
|
*
|
|
* @parm FILE * | fpoutfile | Output file pointer.
|
|
* @parm char * | line | Specifies the text to output.
|
|
* @parm int | wState | Specifies the current line output
|
|
* state, either TEXT, FUNC, STRUCTURE, or PARM. This value should initially
|
|
* be TEXT.
|
|
*
|
|
* @rdesc Returns the line output state at the end of the text line.
|
|
* This value should be passed to <f VenLineOut> on the next iteration
|
|
* in order to continue the formatting code across a line break.
|
|
*
|
|
* @comm Reads and expands both old <p>foobar<d> style function
|
|
* parameters and <p foobar> new-style parameters.
|
|
*
|
|
* This functions sends out character strings. Use <f VentextOut> and
|
|
* <f VentextOut> for printing the aLine text storage data structures.
|
|
*
|
|
*/
|
|
int VenLineOut(FILE * fpoutfile, char * pch, int wState)
|
|
{
|
|
|
|
/*
|
|
* <p> is parm
|
|
* <f> is function
|
|
* <t> is struct/union reference
|
|
* <e> is structure element reference
|
|
* <m> is message
|
|
* <d> is return to default
|
|
* <p foobar> is param
|
|
* <f foobar> is function
|
|
* <t foobar> is structure/union
|
|
*/
|
|
|
|
BOOL iStyle;
|
|
char chFormat;
|
|
char *pchTemp;
|
|
|
|
/* Loop over all chars on line */
|
|
while(*pch) {
|
|
/* Convert tabs into spaces. */
|
|
if(*pch == '\t')
|
|
*pch=' ';
|
|
|
|
/* Skip non-printing chars */
|
|
if (((*pch) & 0x80) || (*pch < ' ')) {
|
|
pch++;
|
|
continue;
|
|
}
|
|
|
|
|
|
/* Check and see if this is a formatting prefix character.
|
|
*/
|
|
if (*pch == '<') {
|
|
pch++;
|
|
if (!*pch)
|
|
/* Warning! Unexpected EOS */
|
|
continue;
|
|
|
|
chFormat = *pch;
|
|
|
|
/* Move the character pointer to the characters following
|
|
* the formatting, and determine the type of formatting code
|
|
* in use, old or new style.
|
|
*/
|
|
pch++; // skip the formatting character
|
|
if (*pch == '>') {
|
|
pch++;
|
|
iStyle = OLDSTYLE;
|
|
}
|
|
else {
|
|
/* For a new style formatting code, there must be
|
|
* either a EOL or whitespace following the code
|
|
* character. Make sure this is the case. If not,
|
|
* then this isn't a formatting code, so
|
|
* just print the characters out.
|
|
*/
|
|
if (*pch && !isspace(*pch)) {
|
|
fprintf(errfp,"Warning: New-style formatting "
|
|
"code without whitespace.\nCode ignored but text printed.\n");
|
|
/* Write out the characters, but
|
|
* don't enter a formatting state.
|
|
*/
|
|
putc('<', fpoutfile);
|
|
putc(chFormat, fpoutfile);
|
|
continue; // the while (*pch)
|
|
}
|
|
|
|
/* Otherwise, this a new style def. Suck
|
|
* up any whitespace present.
|
|
*/
|
|
iStyle = NEWSTYLE;
|
|
/* Chew up whitespace */
|
|
while (*pch && isspace(*pch))
|
|
pch++;
|
|
}
|
|
|
|
/* Now I'm pointing to the start of the string
|
|
* that the formatting should be applied to.
|
|
* Check that a formatting code is not already
|
|
* in effect, cancel it if so.
|
|
*/
|
|
if (!(chFormat == 'd' || chFormat == 'D') && wState != TEXT) {
|
|
fprintf(errfp, "Error: Nested formatting codes.\n");
|
|
fprintf(fpoutfile, "<D>"); // HACK HACK!
|
|
wState = TEXT;
|
|
}
|
|
|
|
|
|
/* Now setup the output state as appropriate, setting
|
|
* the wState variable and outputting any leader chars
|
|
* required.
|
|
*/
|
|
switch (chFormat) {
|
|
case 'P':
|
|
case 'p':
|
|
|
|
/* Parameter formatting. Output the
|
|
* leader codes and setup wState.
|
|
*/
|
|
wState = iStyle | PARM;
|
|
fprintf(fpoutfile, pchVenparm);
|
|
break;
|
|
|
|
case 'E':
|
|
case 'e':
|
|
|
|
/* Data structure element formatting. Output the
|
|
* leader codes and setup wState.
|
|
*/
|
|
wState = iStyle | ELEMENT;
|
|
fprintf(fpoutfile, pchVenelem);
|
|
|
|
/* Skip over the structure notation (struct.element).
|
|
*/
|
|
pchTemp = pch;
|
|
while (*pchTemp++ != '>') {
|
|
if (*pchTemp == '.')
|
|
pch = ++pchTemp;
|
|
}
|
|
break;
|
|
|
|
case 'F':
|
|
case 'f':
|
|
/* Function formatting. Output & setup state */
|
|
wState = iStyle | FUNC;
|
|
fprintf(fpoutfile, pchVenfunc);
|
|
break;
|
|
|
|
case 'D':
|
|
case 'd':
|
|
if (iStyle == NEWSTYLE) {
|
|
fprintf(errfp,"Error: <d foobar> encountered."
|
|
" <d> is the only valid use for <d>.\n");
|
|
/* Here, just print the <d_ anyway. Then
|
|
* set no mode, continue.
|
|
*/
|
|
fprintf(fpoutfile, "<d ");
|
|
}
|
|
else {
|
|
/* Oldstyle end of formatting encountered.
|
|
* Cancel the current mode, output
|
|
* a return-to-normal code (ventura is nice
|
|
* for this one thing, being consistent in
|
|
* what constitues return-to-normal!)
|
|
*/
|
|
wState = TEXT; // reset mode
|
|
fprintf(fpoutfile, "<D>");
|
|
}
|
|
break;
|
|
|
|
case 'T':
|
|
case 't':
|
|
|
|
case 'M':
|
|
case 'm':
|
|
|
|
/* Structure definition */
|
|
wState = iStyle | STRUCT;
|
|
fprintf(fpoutfile, pchVenfunc);
|
|
break;
|
|
|
|
default:
|
|
/* Unrecognized code. Barf.
|
|
*/
|
|
fprintf(errfp, "Error: unrecognized"
|
|
" formatting code.\n");
|
|
|
|
/* Simulate the output and set no mode */
|
|
if (iStyle == NEWSTYLE)
|
|
fprintf(fpoutfile, "<%c ", chFormat);
|
|
else
|
|
fprintf(fpoutfile, "<%c>", chFormat);
|
|
break;
|
|
} // switch for '<' formating codes
|
|
} // if *pch == '<'
|
|
|
|
/* If the character is a new-style close end formatting
|
|
* indicator, clear the current mode to text and send out the
|
|
* the ventura return-to-default code.
|
|
*
|
|
* If there is no current mode, then just output the chracter?
|
|
*/
|
|
|
|
else if (*pch == '>') {
|
|
if (wState != TEXT) {
|
|
|
|
if (wState & OLDSTYLE) {
|
|
fprintf(errfp, "Warning: new style close in "
|
|
"oldstyle formatting.\nIgnoring close, writing char.\n");
|
|
putc(*pch, fpoutfile);
|
|
}
|
|
else {
|
|
/* Cancel the current mode */
|
|
fprintf(fpoutfile, "<D>");
|
|
wState = TEXT;
|
|
}
|
|
}
|
|
else {
|
|
fprintf(errfp, "Warning: Standalone '>' "
|
|
"encountered.\n");
|
|
putc(*pch, fpoutfile);
|
|
}
|
|
|
|
pch++; // skip the '>'
|
|
|
|
}
|
|
else {
|
|
/* Just print the character */
|
|
putc(*pch, fpoutfile);
|
|
pch++;
|
|
}
|
|
|
|
} // while (*pch);
|
|
|
|
/* We're done! Return the current output state */
|
|
return wState;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************
|
|
*
|
|
* XREFS
|
|
*
|
|
****************************************************/
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
* @func void | VenDoXrefs | Process and print the cross reference
|
|
* list for a function or message block.
|
|
*
|
|
* @parm FILE * | file | Specifies the output file.
|
|
* @parm aLine * | line | The line of cross references to print.
|
|
*
|
|
*/
|
|
void VenDoXrefs( FILE *file, aLine *line)
|
|
{
|
|
char ach[80];
|
|
int i;
|
|
char *p;
|
|
|
|
|
|
if (line == NULL) {
|
|
fprintf(errfp, "NULL line passed to VenDoXrefs\n");
|
|
return;
|
|
}
|
|
|
|
/* Header line */
|
|
fprintf( file, "@HO = See Also\n\n" );
|
|
|
|
while (line != NULL) {
|
|
/* skip whitespace */
|
|
for (p = line->text; isspace(*p); p++);
|
|
|
|
while (*p) {
|
|
i = 0;
|
|
while (*p && !(*p == ',' || isspace(*p)))
|
|
ach[i++] = *p++;
|
|
|
|
if (i > 0) {
|
|
ach[i] = '\0';
|
|
fprintf(file, "%s", ach);
|
|
}
|
|
|
|
while (*p && (*p == ',' || isspace(*p)))
|
|
p++;
|
|
if (*p)
|
|
fprintf(file, ", ");
|
|
} /* while *p */
|
|
|
|
fprintf(file, "\n");
|
|
line = line->next;
|
|
if (line)
|
|
fprintf(file, " ");
|
|
|
|
} /* while line != NULL */
|
|
|
|
fprintf(file, "\n");
|
|
|
|
}
|
|
|
|
|
|
/****************************************************
|
|
*
|
|
* FLAGS
|
|
*
|
|
****************************************************/
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void | VenDoFlagList | Print the flag list of a parameter,
|
|
* register, or return description.
|
|
*
|
|
* @parm aFlag * | flag | Pointer to flag list to be printed.
|
|
*
|
|
* @parm FILE * | file | Specifies the file to print to.
|
|
*
|
|
* @parm WORD | wType | This parameter may be one of the following,
|
|
* depending on the type of flag list being produced:
|
|
*
|
|
* @flag REGISTERS | This is a normal input register declaration, below
|
|
* a ASM or ASM callback function declaration.
|
|
* @flag REGRETURN | This is a register return declaration beneath
|
|
* a return description. This is not part of a conditional
|
|
* block.
|
|
* @flag REGCONDITION | This is a register return declaration beneath
|
|
* a return conditional block.
|
|
* @flag PARAMETERS | This is a normal parameter declaration beneath
|
|
* an API, or API Callback function or Message declaration.
|
|
* @flag PARAMRETURN | This is a return flag list declaration beneath
|
|
* a return block in an API or API callback, or a Message return.
|
|
*/
|
|
void VenDoFlagList( aFlag *flag, FILE *file, int wType )
|
|
{
|
|
static char *aszFlagNameOut[NUMFLAGTYPES] = {
|
|
"@RFLAG = ", // registers
|
|
"@RFLAG = ", // reg return
|
|
"@RFLAG = ", // reg condition return
|
|
"@FLAG = ", // param flag
|
|
"@PARM = ", // param return
|
|
"@FLAG = ", // level 1 field
|
|
"@L2FLAG = ", // level 2 field
|
|
"@L3FLAG = ", // level 3 field
|
|
};
|
|
|
|
static char *aszFlagDescOut[NUMFLAGTYPES] = {
|
|
"@RFLDESC = ", // registers
|
|
"@RFLDESC = ", // reg return
|
|
"@RFLDESC = ", // reg condition return
|
|
"@FLDESC = ", // param flag
|
|
"@PDESC = ", // param return
|
|
"@FLDESC = ", // level 1 field
|
|
"@L2FLDESC = ", // level 2 field
|
|
"@L3FLDESC = ", // level 3 field
|
|
};
|
|
|
|
if (!flag) {
|
|
fprintf(errfp, "Warning: NULL Flag sent to VenDoFlaglist\n");
|
|
return;
|
|
}
|
|
|
|
assert(wType < NUMFLAGTYPES);
|
|
|
|
/* loop over the flag list */
|
|
for ( ; flag != NULL; flag = flag->next) {
|
|
/* Do flag name */
|
|
fprintf(file, aszFlagNameOut[wType]);
|
|
VentextOut( file, flag->name, FALSE );
|
|
fprintf( file, "\n\n" );
|
|
|
|
/* Do the description */
|
|
fprintf(file, aszFlagDescOut[wType]);
|
|
VentextOutLnCol(file, flag->desc, aszFlagNameOut[wType]);
|
|
|
|
fprintf( file, "\n" );
|
|
} // for flag list
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************
|
|
*
|
|
* PARMS
|
|
*
|
|
****************************************************/
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
* @func void | VenDoParmList | Print the parameter list of a function
|
|
* block.
|
|
*
|
|
* @parm aBlock * | pBlock | Specifies the enclosing block of the
|
|
* parameter list.
|
|
* @parm aParm * | parm | The parameter list to print.
|
|
* @parm FILE * | file | Specifies the file to use for output.
|
|
*
|
|
* @comm Prints the given parameter list. If parameters within the
|
|
* list contain a flag list, the flag list is printed using
|
|
* <f VenDoFlagList>.
|
|
*
|
|
* @xref VenDoFlagList
|
|
*
|
|
*/
|
|
void VenDoParmList( aBlock *pBlock, aParm *parm, FILE *file )
|
|
{
|
|
|
|
if (!parm) {
|
|
fprintf(file, "None\n\n");
|
|
}
|
|
else {
|
|
/* Loop over the parameter list of the message */
|
|
for (; parm != NULL; parm = parm->next) {
|
|
/* Print first col, param type and name */
|
|
fprintf( file, "@PARM = " );
|
|
|
|
VentextOut( file, parm->type, FALSE );
|
|
|
|
fprintf( file, "<_><MI>");
|
|
VentextOut( file, parm->name, FALSE );
|
|
fprintf( file, "<D>\n\n" );
|
|
|
|
/* Do second column, the description */
|
|
fprintf( file, "@PDESC = " );
|
|
VentextOutLnCol( file, parm->desc, "@PDESC = ");
|
|
// VentextOutLnCol( file, parm->desc, "@PDESC");
|
|
fprintf( file, "\n" );
|
|
|
|
/* Print the parameter's flags, if any */
|
|
if (parm->flag != NULL) {
|
|
VenDoFlagList(parm->flag, file, PARAMETERS);
|
|
}
|
|
} // for parm list
|
|
}
|
|
|
|
/* Close off the parameter list */
|
|
fprintf(file, "@LE = \n\n");
|
|
|
|
}
|
|
|
|
|
|
/****************************************************
|
|
*
|
|
* REGS AND CONDITIONALS
|
|
*
|
|
****************************************************/
|
|
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
* @func void | VenDoRegList | Print a register list.
|
|
*
|
|
* @parm aBlock * | pBlock | Specifies the enclosing block of the
|
|
* parameter list.
|
|
* @parm aReg * | reg | The register list to print.
|
|
* @parm FILE * | file | Specifies the file to use for output.
|
|
*
|
|
* @parm WORD | wType | This parameter may be one of the following,
|
|
* depending on the type of register list being produced:
|
|
*
|
|
* @flag REGISTERS | This is a normal input register declaration, below
|
|
* a ASM or ASM callback function declaration.
|
|
* @flag REGRETURN | This is a register return declaration beneath
|
|
* a return description. This is not part of a conditional
|
|
* block.
|
|
* @flag REGCONDITION | This is a register return declaration beneath
|
|
* a return conditional block.
|
|
*
|
|
* @comm Prints the given register list. If registers within the
|
|
* list contain a flag list, the flag list is printed using
|
|
* <f VenDoFlagList>.
|
|
*
|
|
* @xref VenDoFlagList
|
|
*
|
|
*/
|
|
void VenDoRegList( aBlock *pBlock, aReg *reg, FILE *file, int wType)
|
|
{
|
|
static char *aszRegNameOut[] = {
|
|
"@RNAME = ", // registers
|
|
"@RNAME = ", // reg return
|
|
"@RNAME = ", // reg condition return
|
|
};
|
|
|
|
static char *aszRegDescOut[] = {
|
|
"@RDESC = ", // registers
|
|
"@RDESC = ", // reg return
|
|
"@RDESC = ", // reg condition return
|
|
};
|
|
|
|
assert(wType == REGISTERS || wType == REGRETURN || wType == REGCONDITION);
|
|
|
|
if (reg == NULL) {
|
|
fprintf(file, "None\n\n");
|
|
}
|
|
else {
|
|
/* Loop over the register list of the message */
|
|
for (; reg != NULL; reg = reg->next) {
|
|
/* Print first col, reg name */
|
|
fprintf( file, aszRegNameOut[wType]);
|
|
|
|
/* Print the register name */
|
|
fprintf( file, "<B>" );
|
|
VentextOut( file, reg->name, FALSE );
|
|
fprintf( file, "<D>\n\n" );
|
|
|
|
/* Do second column, the description */
|
|
fprintf( file, aszRegDescOut[wType] );
|
|
VentextOutLnCol( file, reg->desc, aszRegDescOut[wType] );
|
|
fprintf( file, "\n" );
|
|
|
|
/* Print the parameter's flags, if any */
|
|
if (reg->flag != NULL) {
|
|
VenDoFlagList(reg->flag, file, wType);
|
|
}
|
|
} // for reg list
|
|
}
|
|
|
|
fprintf(file, "@LE = \n\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void | VenDoCondList | Print a conditional register list.
|
|
*
|
|
* @parm aBlock * | pBlock | Specifies the enclosing block of the
|
|
* register list.
|
|
*
|
|
* @parm aCond * | cond | The conditional list to print.
|
|
*
|
|
* @parm FILE * | file | Specifies the file to use for output.
|
|
*
|
|
* @comm Prints the given conditional list. For each conditional
|
|
* block, the text is printed, followed by the the list of registers
|
|
* (and their associated tags) for the conditional block.
|
|
*
|
|
* @xref VenDoRegList, VenDoFlagList
|
|
*
|
|
*/
|
|
void VenDoCondList( aBlock *pBlock, aCond *cond, FILE *file)
|
|
{
|
|
|
|
assert(cond != NULL);
|
|
|
|
/* Loop over the register list of the message */
|
|
for (; cond != NULL; cond = cond->next) {
|
|
|
|
/* Print out the conditional tag text.. */
|
|
fprintf( file, "@COND = ");
|
|
VentextOutLnCol(file, cond->desc, "@COND = ");
|
|
|
|
fprintf( file, "\n");
|
|
|
|
/* Now print the conditional's registers (and subseqent flags) */
|
|
VenDoRegList(pBlock, cond->regs, file, REGCONDITION);
|
|
|
|
} // for conditional list
|
|
|
|
fprintf(file, "@LE = \n\n");
|
|
|
|
}
|
|
|
|
|
|
/*******************************************************
|
|
*
|
|
* STRUCTS
|
|
*
|
|
*******************************************************/
|
|
|
|
|
|
/*
|
|
* VenPrintFieldText(aType *type, FILE *file)
|
|
*
|
|
* Prints the text of a field for a structure courier dump. This proc
|
|
* only prints the name and type of structure fields at the appropriate
|
|
* indent levels.
|
|
*
|
|
*/
|
|
void VenPrintFieldText(aType *type, FILE *file)
|
|
{
|
|
int i;
|
|
|
|
for (i = type->level + 1; i > 0; i--)
|
|
fprintf(file, " ");
|
|
|
|
VentextOut(file, type->type, FALSE);
|
|
fprintf(file, " ");
|
|
|
|
VentextOut(file, type->name, FALSE);
|
|
|
|
fprintf(file, ";<R>\n");
|
|
|
|
/* Flags? */
|
|
}
|
|
|
|
|
|
/*
|
|
* VenPrintSubstructText(aSU *su, file, wType)
|
|
*
|
|
* Prints a courier dump of a sub-structure or sub-union at the
|
|
* appropriate indent level. Does not print any description text.
|
|
*
|
|
* wType must indicate whether this is a union or structure, being
|
|
* either FIELD_STRUCT or FIELD_UNION.
|
|
*
|
|
*/
|
|
void VenPrintSubstructText(aSU *su, FILE *file, int wType)
|
|
{
|
|
int i;
|
|
aField *field;
|
|
|
|
|
|
/* Do struct/union and brace of sub-structure */
|
|
for (i = su->level; i > 0; i--)
|
|
fprintf(file, " ");
|
|
|
|
fprintf(file, "%s {<R>\n", wType == FIELD_STRUCT ? "struct" : "union");
|
|
|
|
field = su->field;
|
|
if (field) {
|
|
while (field) {
|
|
switch (field->wType) {
|
|
case FIELD_TYPE:
|
|
VenPrintFieldText((aType *) field->ptr, file);
|
|
break;
|
|
|
|
case FIELD_STRUCT:
|
|
case FIELD_UNION:
|
|
VenPrintSubstructText((aSU *) field->ptr,
|
|
file, field->wType);
|
|
break;
|
|
}
|
|
field = field->next;
|
|
}
|
|
}
|
|
|
|
/* Do closing brace and title of sub-structure */
|
|
for (i = su->level; i > 0; i--)
|
|
fprintf(file, " ");
|
|
|
|
fprintf(file, "} %s;<R>\n", su->name->text);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* VenPrintStructText(pBlock, file, wType)
|
|
*
|
|
* Prints a courier dump of the text of a structure/union outerlevel
|
|
* block. Does not print any description fields or flags.
|
|
*
|
|
* wType indicates whether the block is a structure or union, either
|
|
* FIELD_STRUCT or FIELD_UNION.
|
|
*
|
|
*/
|
|
void VenPrintStructText(aBlock *pBlock, FILE *file)
|
|
{
|
|
aField *curf;
|
|
aLine *tag;
|
|
|
|
curf = pBlock->field;
|
|
tag = pBlock->tagname;
|
|
|
|
fprintf(file, "@EX = typedef %s ",
|
|
pBlock->blockType == STRUCTBLOCK ? "struct" : "union");
|
|
if (tag)
|
|
fprintf(file, "%s ", tag->text);
|
|
|
|
fprintf(file, "{<R>\n");
|
|
|
|
while (curf) {
|
|
switch (curf->wType) {
|
|
case FIELD_TYPE:
|
|
VenPrintFieldText((aType *) curf->ptr, file);
|
|
break;
|
|
|
|
case FIELD_STRUCT:
|
|
case FIELD_UNION:
|
|
VenPrintSubstructText((aSU *) curf->ptr, file, curf->wType);
|
|
break;
|
|
|
|
default:
|
|
assert(FALSE);
|
|
break;
|
|
}
|
|
curf = curf->next;
|
|
}
|
|
fprintf(file, "} %s;\n\n", pBlock->name->text);
|
|
|
|
/* Now print out the othernames? */
|
|
}
|
|
|
|
|
|
/********* DESCRIPTION DUMPS ************/
|
|
|
|
#define NUMFIELDLEVELS 3
|
|
|
|
char *aachFieldNameTags[NUMFIELDLEVELS] = {
|
|
"@PARM = ", "@L2PARM = ", "@L3PARM = "
|
|
};
|
|
char *aachFieldDescTags[NUMFIELDLEVELS] = {
|
|
"@PDESC = ", "@L2PDESC = ", "@L3PDESC = "
|
|
};
|
|
|
|
int aiFlagTypes[NUMFIELDLEVELS] = { FIELD1, FIELD2, FIELD3 };
|
|
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @api void | VenPrintFieldDesc | This function prints the
|
|
* descriptions of a field entry in a structure. The printout is done
|
|
* using the standard @parm tags (and associated flag tags).
|
|
*
|
|
* @parm aType * | type | Points to a type structure which contains
|
|
* the field information.
|
|
*
|
|
* @parm FILE * | file | Specifies the output file.
|
|
*
|
|
* @comm Use this function to output the names/descriptions of fields.
|
|
* Use <f VenPrintFieldText> to output a similated text dump of the
|
|
* structure definition.
|
|
*
|
|
* Note that the use of this function requires an @LE tag be output when
|
|
* the list of parameters has been ended.
|
|
*
|
|
*/
|
|
void VenPrintFieldDesc(aType *type, FILE *file)
|
|
{
|
|
int level;
|
|
|
|
level = type->level;
|
|
if (level >= NUMFIELDLEVELS)
|
|
level = NUMFIELDLEVELS - 1;
|
|
|
|
/* Print the field type and name in the first column, formatted */
|
|
fprintf(file, "%s<B>", aachFieldNameTags[level]);
|
|
VentextOut(file, type->name, FALSE);
|
|
fprintf(file, "<D>\n\n");
|
|
#if 0
|
|
/* Print parameter type above? */
|
|
fprintf(file, "<_><MI>");
|
|
VentextOut(file, type->name, FALSE);
|
|
fprintf(file, "\n\n");
|
|
#endif
|
|
|
|
/* Do the second column, description text */
|
|
fprintf(file, aachFieldDescTags[level]);
|
|
VentextOutLnCol(file, type->desc, aachFieldDescTags[level]);
|
|
putc('\n', file);
|
|
|
|
/* Do the flag list, if any */
|
|
if (type->flag != NULL) {
|
|
VenDoFlagList(type->flag, file, aiFlagTypes[level]);
|
|
}
|
|
|
|
/* Now, somewhere, a @LE = needs to be output! */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VenPrintSubstructDesc(aSU *su, FILE *file, int wType)
|
|
{
|
|
aField *field;
|
|
int level;
|
|
int levelStruct;
|
|
|
|
/* Limit level to the number of nesting levels supported by Ventura */
|
|
level = min(NUMFIELDLEVELS - 1, su->level);
|
|
|
|
levelStruct = level - 1;
|
|
|
|
/* For the sub-structure, print out a little blurb for
|
|
* the sub-structure/union itself, as well as the optional
|
|
* description text that may come with a sub-structure.
|
|
*/
|
|
|
|
fprintf(file, aachFieldNameTags[levelStruct]);
|
|
fprintf(file, "<B>%s<D>\n\n", su->name->text);
|
|
|
|
if (su->desc) {
|
|
fprintf(file, aachFieldDescTags[levelStruct]);
|
|
VentextOutLnCol(file, su->desc, aachFieldDescTags[levelStruct]);
|
|
putc('\n', file);
|
|
}
|
|
|
|
/* Now print the sub-fields */
|
|
fprintf(file, aachFieldDescTags[levelStruct]);
|
|
fprintf(file, "The following sub-fields are contained in %s <B>%s<D>:\n\n",
|
|
wType == FIELD_STRUCT ? "structure" : "union",
|
|
su->name->text);
|
|
|
|
/* Now do each field of the sub-structure */
|
|
field = su->field;
|
|
if (field) {
|
|
while (field) {
|
|
switch (field->wType) {
|
|
case FIELD_TYPE:
|
|
VenPrintFieldDesc((aType *) field->ptr, file);
|
|
break;
|
|
|
|
case FIELD_STRUCT:
|
|
case FIELD_UNION:
|
|
VenPrintSubstructDesc((aSU *) field->ptr,
|
|
file, field->wType);
|
|
break;
|
|
}
|
|
field = field->next;
|
|
}
|
|
}
|
|
|
|
/* Print a closing blurb */
|
|
fprintf(file, aachFieldNameTags[levelStruct]);
|
|
fprintf(file, "End of sub-fields for %s %s.\n\n",
|
|
wType == FIELD_STRUCT ? "structure" : "union", su->name->text);
|
|
|
|
}
|
|
|
|
|
|
|
|
void VenDoStructDescriptions(aBlock *pBlock, FILE *file)
|
|
{
|
|
aField *cur;
|
|
|
|
/* Look through the field list, printing each field as it is
|
|
* encountered using @parm tags...
|
|
*/
|
|
|
|
fprintf(file, "@HO = Fields\n\n");
|
|
|
|
fprintf(file, "The <b>%s<d> %s has the following fields:\n\n",
|
|
pBlock->name->text,
|
|
pBlock->blockType == STRUCTBLOCK ? "structure" : "union");
|
|
|
|
/* Dump the structure */
|
|
cur = pBlock->field;
|
|
if (cur == NULL) {
|
|
fprintf(file, "None\n\n");
|
|
return;
|
|
}
|
|
|
|
while (cur) {
|
|
switch (cur->wType) {
|
|
case FIELD_TYPE:
|
|
VenPrintFieldDesc((aType *) cur->ptr, file);
|
|
break;
|
|
|
|
case FIELD_STRUCT:
|
|
case FIELD_UNION:
|
|
VenPrintSubstructDesc((aSU *) cur->ptr, file, cur->wType);
|
|
break;
|
|
|
|
default:
|
|
assert(FALSE);
|
|
break;
|
|
}
|
|
cur = cur->next;
|
|
}
|
|
|
|
/* Close off the param list */
|
|
fprintf(file, "@LE = \n\n");
|
|
|
|
/* Print out othertypes? */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************
|
|
*
|
|
* DOC BLOCK
|
|
*
|
|
*********************************************************/
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
* @func void | VenfuncOut | This outputs the function information.
|
|
*
|
|
* @parm aBlock * | func | Specifies a pointer to the function
|
|
* information. The type of the block is determined by looking at the
|
|
* blocktype field.
|
|
*
|
|
* @parm FILE * | file | Specifies the output file.
|
|
*
|
|
* @comm This function may be called recursively to deal with callback
|
|
* procedures. It handles most anything.
|
|
*
|
|
*/
|
|
void VenfuncOut( aBlock *func, FILE *file )
|
|
{
|
|
aParm *parm;
|
|
aBlock *pCb;
|
|
int type;
|
|
|
|
/* Pointer to tag header type - depends on block type */
|
|
char *pIntHeader;
|
|
static char achCbHeader[] = "@HU =";
|
|
static char achFuncHeader[] = "@HO =";
|
|
|
|
if( func == NULL || file == NULL) {
|
|
fprintf(errfp, "Bogus params to VenFuncOut!\n");
|
|
return;
|
|
}
|
|
|
|
/* Get the blocktype for this block, do different things according to
|
|
* type.
|
|
*/
|
|
type = func->blockType;
|
|
|
|
/*
|
|
* DO THE BLOCK HEADER
|
|
*/
|
|
switch (type) {
|
|
case FUNCTION:
|
|
/* use interior headers of normal level */
|
|
pIntHeader = achFuncHeader;
|
|
|
|
/* Block header */
|
|
fprintf(file, "@HR = ");
|
|
VentextOut(file, func->name, FALSE);
|
|
fprintf(file, "\n\n");
|
|
|
|
/* Setup API description */
|
|
fprintf( file, "@HO = Syntax\n\n" );
|
|
|
|
VentextOut( file, func->type, FALSE );
|
|
fprintf( file, "<_><B>" );
|
|
VentextOut( file, func->name, FALSE );
|
|
fprintf( file, "<D>" );
|
|
|
|
DoFunctionBlockHeader:
|
|
/* Print the function header line, with parameters */
|
|
fprintf(file, "(");
|
|
for (parm = func->parm; parm != NULL; ) {
|
|
fprintf(file, "<MI>");
|
|
VentextOut(file, parm->name, FALSE);
|
|
fprintf(file, "<D>");
|
|
/* Advance */
|
|
parm = parm->next;
|
|
if (parm != NULL)
|
|
fprintf(file, ", ");
|
|
}
|
|
fprintf(file, ")\n\n");
|
|
// fprintf(file, "\n\n");
|
|
|
|
break;
|
|
|
|
case CALLBACK:
|
|
/* Use callback interior header styles */
|
|
pIntHeader = achCbHeader;
|
|
|
|
/* Print function header setup */
|
|
fprintf(file, "@HO = Callback\n\n");
|
|
VentextOut(file, func->type, FALSE);
|
|
fprintf(file, "<_><B>");
|
|
VentextOut(file, func->name, FALSE);
|
|
fprintf(file, "<D>");
|
|
|
|
/* Get the parameter list done the same way as with a normal
|
|
* function. Cheat by using a goto to the above code.
|
|
*/
|
|
goto DoFunctionBlockHeader;
|
|
break;
|
|
|
|
case MESSAGE:
|
|
pIntHeader = achFuncHeader;
|
|
|
|
/* Print message header setup */
|
|
fprintf(file, "@HR = ");
|
|
VentextOut(file, func->name, FALSE);
|
|
fprintf(file, "\n\n");
|
|
|
|
// fprintf(file, "@HO = Description\n\n");
|
|
|
|
break;
|
|
|
|
case MASMBLOCK:
|
|
pIntHeader = achFuncHeader;
|
|
|
|
/* Print MASM block header setup */
|
|
fprintf(file, "@HR = ");
|
|
VentextOut(file, func->name, FALSE);
|
|
fprintf(file, "\n\n");
|
|
|
|
break;
|
|
|
|
case MASMCBBLOCK:
|
|
pIntHeader = achCbHeader;
|
|
|
|
/* Print MASM block header setup */
|
|
fprintf(file, "@HO = Callback\n\n");
|
|
|
|
/* BOLD THE CALLBACK NAME? */
|
|
fprintf(file, "<B>");
|
|
VentextOut(file, func->name, FALSE);
|
|
fprintf(file, "<D>\n\n");
|
|
|
|
break;
|
|
|
|
|
|
case STRUCTBLOCK:
|
|
case UNIONBLOCK:
|
|
pIntHeader = achFuncHeader;
|
|
|
|
/* Print message header setup */
|
|
fprintf(file, "@HR = ");
|
|
VentextOut(file, func->name, FALSE);
|
|
fprintf(file, "\n\n");
|
|
|
|
// fprintf(file, "@HO = Description\n\n");
|
|
|
|
break;
|
|
|
|
|
|
// case UNIONBLOCK:
|
|
// break;
|
|
|
|
default:
|
|
fprintf(errfp, "Ventura: Unknown block type\n");
|
|
return;
|
|
|
|
} // switch type
|
|
|
|
|
|
|
|
/*
|
|
* DO DESCRIPTION
|
|
*/
|
|
if (func->desc != NULL) {
|
|
VentextOut( file, func->desc, TRUE );
|
|
fprintf( file, "\n" );
|
|
}
|
|
|
|
|
|
/*
|
|
* DO STRUCTURE/UNION FIELDS
|
|
*/
|
|
if (func->field != NULL) {
|
|
/* Print structure dump in courier */
|
|
VenPrintStructText(func, file);
|
|
|
|
/* Print out the fields with descriptions & flags in table
|
|
* format.
|
|
*/
|
|
VenDoStructDescriptions(func, file);
|
|
}
|
|
|
|
if (func->other) {
|
|
/* RTFOtherOut(file, func->other);
|
|
*/
|
|
|
|
}
|
|
|
|
/*
|
|
* DO PARAMETER OR REGISTER LISTS
|
|
*/
|
|
switch (type) {
|
|
case FUNCTION:
|
|
case CALLBACK:
|
|
case MESSAGE:
|
|
fprintf(file, "%s Parameters\n\n", pIntHeader);
|
|
VenDoParmList(func, func->parm, file);
|
|
assert(func->reg == NULL);
|
|
break;
|
|
|
|
case MASMBLOCK:
|
|
case MASMCBBLOCK:
|
|
fprintf(file, "%s Registers\n\n", pIntHeader);
|
|
/* Print the register list in input register declaration format */
|
|
VenDoRegList(func, func->reg, file, REGISTERS);
|
|
assert(func->parm == NULL);
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* DO RETURN DESCRIPTION
|
|
*/
|
|
if( func->rtndesc != NULL ) {
|
|
fprintf( file, "%s Return Value\n\n", pIntHeader );
|
|
|
|
/* Print the return description text */
|
|
VentextOut(file, func->rtndesc, TRUE);
|
|
fprintf(file, "\n");
|
|
|
|
switch (type) {
|
|
case MESSAGE:
|
|
case FUNCTION:
|
|
case CALLBACK:
|
|
if (func->rtnflag != NULL) {
|
|
VenDoFlagList(func->rtnflag, file, PARAMRETURN);
|
|
fprintf(file, "@LE = \n\n");
|
|
}
|
|
break;
|
|
case MASMBLOCK:
|
|
case MASMCBBLOCK:
|
|
/* Process any available register tags */
|
|
if (func->rtnreg != NULL) {
|
|
VenDoRegList(func, func->rtnreg, file, REGRETURN);
|
|
}
|
|
|
|
/* Now do the conditional list */
|
|
if (func->cond != NULL) {
|
|
VenDoCondList(func, func->cond, file);
|
|
}
|
|
|
|
break;
|
|
default:
|
|
assert(0);
|
|
break;
|
|
|
|
} // switch
|
|
}
|
|
|
|
/*
|
|
* DO USES TAG
|
|
*/
|
|
if (func->uses != NULL) {
|
|
fprintf(file, "%s Uses\n\n", pIntHeader);
|
|
VentextOut(file, func->uses, TRUE);
|
|
fprintf(file, "\n@LE = \n\n");
|
|
}
|
|
|
|
/*
|
|
* DO COMMENT BLOCK
|
|
*/
|
|
if( func->comment != NULL ) {
|
|
fprintf( file, "%s Comments\n\n", pIntHeader );
|
|
VentextOut( file, func->comment, TRUE );
|
|
fprintf( file, "\n" );
|
|
}
|
|
|
|
|
|
/*
|
|
* DO ANY CALLBACKS
|
|
*/
|
|
for (pCb = func->cb; pCb != NULL; pCb = pCb->next) {
|
|
VenfuncOut( pCb, file );
|
|
}
|
|
|
|
/*
|
|
* DO CROSS REFERENCES
|
|
*/
|
|
if (func->xref != NULL) {
|
|
VenDoXrefs(file, func->xref);
|
|
}
|
|
|
|
/* Done. Whew! */
|
|
}
|
|
|
|
|
|
|
|
/****************************************************
|
|
*
|
|
* RANDOM STUFF TO SUPPORT RTF FILES
|
|
*
|
|
****************************************************/
|
|
|
|
|
|
void
|
|
VenFileInit(FILE * phoutfile, logentry *curlog)
|
|
{
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
VenFileProcess(FILE * phoutfile, files curfile)
|
|
{
|
|
copyfile(phoutfile,curfile->filename);
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
void
|
|
VenFileDone(FILE * phoutfile, files headfile)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
void
|
|
VenLogInit(FILE * phoutfile, logentry * * pheadlog)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void
|
|
VenLogProcess(FILE * phoutfile, logentry * curlog)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void
|
|
VenLogDone(FILE * phoutfile, logentry * headlog)
|
|
{
|
|
return;
|
|
}
|