windows-nt/Source/XPSP1/NT/base/ntsetup/legacy/dll/infdebug.c
2020-09-26 16:20:57 +08:00

553 lines
12 KiB
C

#include "precomp.h"
#pragma hdrstop
#if DEVL
typedef enum {
CmdNone,
CmdHelp,
CmdGo,
CmdList,
CmdTrace,
CmdSymbol,
CmdTraceback,
CmdCurrent,
CmdNearestLabel,
CmdBreak
} InfCmd;
BOOL StopAtLine = FALSE;
CHAR CmdBuffer[256];
#endif
BOOL
SdpReconstructLine(
IN PINFLINE MasterLineArray,
IN UINT MasterLineCount,
IN UINT Line,
OUT PUCHAR Buffer,
IN UINT BufferSize
)
/*++
Routine Description:
Reconstruct a pseudo-line in an inf file, placing it into the
global temporary buffer.
Arguments:
MasterLineArray - supplies master line array for inf in question
MasterLineCount - supplies # of pseudo-lines in the inf
Line - supplies pseudo-line # of line to dump
Buffer - supplies output buffer
BufferSize - supplies max # characters that fit into Buffer
Return Value:
None.
--*/
{
PCHAR pIn;
PCHAR pOut = Buffer;
PINFLINE InfLine;
UCHAR c;
InfLine = &MasterLineArray[Line];
pIn = InfLine->text.addr;
memset(Buffer,0,BufferSize);
if(InfLine->flags & INFLINE_SECTION) {
*pOut++ = '[';
lstrcpy(pOut,pIn);
lstrcat(pOut,"]");
} else {
if(InfLine->flags & INFLINE_KEY) {
lstrcpy(pOut,pIn);
lstrcat(pOut," = ");
pOut += lstrlen(pOut);
pIn += lstrlen(pIn);
}
while(pIn < MasterLineArray[Line+1].text.addr) {
switch(c = *pIn++) {
case TOKEN_VARIABLE:
*pOut++ = '$';
*pOut++ = '(';
break;
case TOKEN_LIST_FROM_SECTION_NTH_ITEM:
*pOut++ = '^';
*pOut++ = '(';
break;
case TOKEN_LOCATE_ITEM_IN_LIST:
*pOut++ = '~';
*pOut++ = '(';
break;
case TOKEN_NTH_ITEM_FROM_LIST:
*pOut++ = '*';
*pOut++ = '(';
break;
case TOKEN_FIELD_ADDRESSOR:
*pOut++ = '#';
*pOut++ = '(';
break;
case TOKEN_APPEND_ITEM_TO_LIST:
*pOut++ = '>';
*pOut++ = '(';
break;
case TOKEN_LIST_START:
*pOut++ = '{';
break;
case TOKEN_LIST_END:
*pOut++ = '}';
break;
case TOKEN_SPACE:
*pOut++ = ' ';
break;
case TOKEN_COMMA:
*pOut++ = ',';
break;
case TOKEN_RIGHT_PAREN:
*pOut++ = ')';
break;
default:
if(IS_STRING_TOKEN(c)) {
ULONG len;
switch(c) {
case TOKEN_STRING:
len = (ULONG)(*pIn++) + 100;
break;
case TOKEN_LONG_STRING:
len = (ULONG)((*pIn++) << 8) + (ULONG)(*pIn++);
break;
default:
// short string
len = c - TOKEN_SHORT_STRING;
break;
}
strncpy(pOut,pIn,len);
pOut += len;
pIn += len;
}
break;
}
}
}
return(TRUE);
}
#if DEVL
VOID
SdTracingOn(
VOID
)
/*++
Routine Description:
Turn inf tracing on.
Arguments:
None.
Return Value:
None.
--*/
{
StopAtLine = !StopAtLine;
DbgPrint("SETUP: INF Tracing %s.\n",StopAtLine ? "on; will break at next line" : "off");
}
InfCmd
SdGetCmd(
PCHAR *CharAfterCmd
)
/*++
Routine Description:
Fetch a command from the user.
Arguments:
CharAfterCmd - receives a pointer to the character that terminated
the command string.
Return Value:
member of InfCmd enum indicating which command the user entered
--*/
{
PCHAR p;
while(1) {
DbgPrompt("setup>",CmdBuffer,sizeof(CmdBuffer));
if(CmdBuffer[0]) {
p = strpbrk(CmdBuffer," \t");
*CharAfterCmd = p ? p : strchr(CmdBuffer,'\0');
switch(tolower(CmdBuffer[0])) {
case 'd':
return(CmdSymbol);
case 'g':
return(CmdGo);
case 'h':
case '?':
return(CmdHelp);
case 'k':
return(CmdTraceback);
case 'l':
if(tolower(CmdBuffer[1]) == 'n') {
return(CmdNearestLabel);
}
break;
case 'r':
return(CmdCurrent);
case 't':
return(CmdTrace);
case 'u':
return(CmdList);
case 'x':
return(CmdBreak);
}
DbgPrint("%s: unknown command\n",CmdBuffer);
}
}
}
PCHAR
SdpFindSection(
IN PPARSED_INF ParsedInf,
IN UINT Line
)
/*++
Routine Description:
Determine the section name of given pseudo-line.
Arguments:
ParsedInf - supplies a pointer to the inf parse structure for the
inf file in which the line is located.
Line - supplies the pseudo-line.
Return Value:
Name of the section, or NULL if it can't be determined
--*/
{
INT L;
PCHAR Section = NULL;
for(L=(INT)Line; L>=0; --L) {
if(ParsedInf->MasterLineArray[L].flags & INFLINE_SECTION) {
Section = ParsedInf->MasterLineArray[L].text.addr;
break;
}
}
return(Section);
}
VOID
SdpCurrentLineOut(
IN UINT Line
)
/*++
Routine Description:
Dump out a line in the current context.
Arguments:
Line - supplies pseudo-line number of line to dump
Return Value:
None.
--*/
{
PCHAR Section;
CHAR buf[1024];
//
// Determine the current section name by searching backwards for
// a line with its section flag set.
//
Section = SdpFindSection(pLocalInfTempInfo()->pParsedInf,Line);
DbgPrint("%s.INF:[%s]\n",pLocalInfPermInfo()->szName,Section ? Section : "???");
SdpReconstructLine( pLocalInfTempInfo()->pParsedInf->MasterLineArray,
pLocalInfTempInfo()->pParsedInf->MasterLineCount,
Line,
buf,
1024
);
DbgPrint("%s\n",buf);
}
VOID
SdpInfDebugPrompt(
IN UINT Line
)
/*++
Routine Description:
Debug prompt. Accept a command from the user and act on it.
If we got here via SdBreakNow, then not all commands will function
as one might expect -- for example, tracing won't return until the
next line is actually interpreted.
Arguments:
None.
Return Value:
None.
--*/
{
CHAR buf[1024];
PCHAR Section;
INT L;
UINT UL;
PCHAR NextChar;
BOOL looping = TRUE;
InfCmd cmd;
PINFCONTEXT Context;
BOOL Found;
PPARSED_INF ParsedInf;
if(!StopAtLine) {
return;
}
DbgPrint("\n");
SdpCurrentLineOut(Line);
while(looping) {
switch(cmd = SdGetCmd(&NextChar)) {
case CmdHelp:
DbgPrint("d <symbol> - print current value of <symbol>\n");
DbgPrint("g - go\n");
DbgPrint("h,? - print this message\n");
DbgPrint("k - crude traceback\n");
DbgPrint("ln - list nearest preceding line in section with a key\n");
DbgPrint("r - list current line again\n");
DbgPrint("t - trace one line\n");
DbgPrint("u - list a few lines starting at current line\n");
DbgPrint("x - break into debugger\n");
DbgPrint("\n");
break;
case CmdGo:
StopAtLine = FALSE;
looping = FALSE;
break;
case CmdTrace:
StopAtLine = TRUE;
looping = FALSE;
break;
case CmdList:
//
// List out a few lines.
//
for(UL=Line+1; (UL<pLocalInfTempInfo()->pParsedInf->MasterLineCount) && (UL<Line+6); UL++) {
SdpReconstructLine( pLocalInfTempInfo()->pParsedInf->MasterLineArray,
pLocalInfTempInfo()->pParsedInf->MasterLineCount,
UL,
buf,
1024
);
DbgPrint("%s\n",buf);
}
DbgPrint("\n");
break;
case CmdBreak:
DbgUserBreakPoint();
break;
case CmdSymbol:
//
// Look up a symbol.
//
if(*NextChar) {
PCHAR Value = SzFindSymbolValueInSymTab(NextChar+1);
if(Value) {
DbgPrint("Value = %s\n",Value);
} else {
DbgPrint("Symbol not found.\n");
}
} else {
DbgPrint("No symbol given.\n");
}
DbgPrint("\n");
break;
case CmdTraceback:
//
// Perform a sort of crude traceback.
//
Context = pLocalContext()->pNext;
while(Context) {
Section = SdpFindSection(Context->pInfTempInfo->pParsedInf,Context->CurrentLine-1);
DbgPrint("%s.INF:[%s]\n",Context->pInfTempInfo->pInfPermInfo->szName,Section ? Section : "???");
SdpReconstructLine( Context->pInfTempInfo->pParsedInf->MasterLineArray,
Context->pInfTempInfo->pParsedInf->MasterLineCount,
Context->CurrentLine-1,
buf,
1024
);
DbgPrint(" %s\n",buf);
Context = Context->pNext;
}
DbgPrint("\n");
break;
case CmdNearestLabel:
//
// Search backwards for the nearest line w/ a key.
//
ParsedInf = pLocalInfTempInfo()->pParsedInf;
for(Found=FALSE,L=(INT)Line; L>=0; --L) {
if(ParsedInf->MasterLineArray[L].flags & INFLINE_KEY) {
Found = TRUE;
break;
}
if(ParsedInf->MasterLineArray[L].flags & INFLINE_SECTION) {
break;
}
}
if(Found) {
SdpReconstructLine( ParsedInf->MasterLineArray,
ParsedInf->MasterLineCount,
(UINT)L,
buf,
1024
);
DbgPrint("%s\n",buf);
} else {
DbgPrint("Key not found in this section.\n");
}
DbgPrint("\n");
break;
case CmdCurrent:
//
// Print the current line again
//
SdpCurrentLineOut(Line);
DbgPrint("\n");
break;
}
}
}
VOID
SdAtNewLine(
IN UINT Line
)
/*++
Routine Description:
This routine should be called just before execution of a new line.
Arguments:
None.
Return Value:
None.
--*/
{
SdpInfDebugPrompt(Line);
}
VOID
SdBreakNow(
VOID
)
/*++
Routine Description:
Break into the inf debug prompt now.
Arguments:
None.
Return Value:
None.
--*/
{
StopAtLine = TRUE;
SdpInfDebugPrompt(pLocalContext()->CurrentLine-1);
}
#endif // DEVL