/*++ Copyright (c) 2000 Microsoft Corporation Module Name: genlvl.c Abstract: This module implements a program which generates the debug print filter component id enumeration and the system filter table that are used by various components in the system to dynamically filter debug print output. Two files are generated by this program. A header file that declares an enumeration of debug print filter component id, and a source file that declares and initializes the individual component filter variables. Author: David N. Cutler (davec) 7-Jan-2000 Environment: User mode. Revision History: None. --*/ #include #include #include #include #include // // Increment this everytime a change to this file is made. // #define GENLVL_VERSION "1.0" // // Define component name table. // #define MAXIMUM_NAMES 4096 PCHAR ComponentNameTable[MAXIMUM_NAMES + 1] = {NULL}; // // Define forward referenced prototypes. // ULONG InsertName( IN PCHAR NewName ); ULONG GenerateCmHeaderFile( FILE *OutputFile ); ULONG GenerateCmSourceFile( FILE *OutputFile ); ULONG GenerateKdSourceFile( FILE *OutputFile ); ULONG GenerateNtHeaderFile( FILE *OutputFile ); // // Main program. // int __cdecl main( int argc, char *argv[] ) { CHAR Buffer[132]; CHAR CmHeaderFileName[128]; FILE *CmHeaderFile; CHAR CmSourceFileName[128]; FILE *CmSourceFile; ULONG Count; PCHAR ComponentDirectory; FILE *ComponentFile = NULL; CHAR ComponentFileName[128]; int ExitCode = 0; CHAR NtHeaderFileName[128]; FILE *NtHeaderFile = NULL; FILE *KdSourceFile = NULL; CHAR KdSourceFileName[128]; PCHAR TargetDirectory; // // Parse arguments. // if (argc == 2 && (!strcmp(argv[1],"-?") || !strcmp(argv[1],"/?"))) { goto PrintUsage; } // // Determine name of target directory for generated files. This requires // the -t switch be specified and that the argument after the switch is // the target directory name. If no -t switch is specfied, then default // to ".". // if (argc >= 3 && !_stricmp(argv[1],"-t")) { TargetDirectory = argv[2]; argc -= 2; argv += 2; } else { TargetDirectory = "."; } // // Determine name of the component id directory. This is the last input // command line argument. If a component id directory is not specified, // then default to ".". // if (argc >= 2) { ComponentDirectory = argv[1]; argc -= 1; argv += 1; } else { ComponentDirectory = "."; } // // There should be no more arguments. // if (argc != 1) { printf("\n Manformed command line\n"); ExitCode = 1; goto PrintUsage; } // // Open the component id input file. // sprintf(&ComponentFileName[0], "%s\\componentid.tab", ComponentDirectory); ComponentFile = fopen(&ComponentFileName[0], "r"); if (!ComponentFile) { printf("\n Unable to open component id file %s\n", &ComponentFileName[0]); ExitCode = 1; goto PrintUsage; } // // Open the kernel debugger source output file. // sprintf(&KdSourceFileName[0], "%s\\dpfilter.c", TargetDirectory); KdSourceFile = fopen(&KdSourceFileName[0], "w"); if (!KdSourceFile) { printf("\n Unable to open filter source file %s\n", &KdSourceFileName[0]); ExitCode = 1; goto PrintUsage; } // // Open the configuration manager header output file. // sprintf(&CmHeaderFileName[0], "%s\\dpfiltercm.h", TargetDirectory); CmHeaderFile = fopen(&CmHeaderFileName[0], "w"); if (!CmHeaderFile) { printf("\n Unable to open filter source file %s\n", &CmHeaderFileName[0]); ExitCode = 1; goto PrintUsage; } // // Open the configuration manager source output file. // sprintf(&CmSourceFileName[0], "%s\\dpfiltercm.c", TargetDirectory); CmSourceFile = fopen(&CmSourceFileName[0], "w"); if (!CmSourceFile) { printf("\n Unable to open filter source file %s\n", &CmSourceFileName[0]); ExitCode = 1; goto PrintUsage; } // // Open the ntrtl.w append header output file. // sprintf(&NtHeaderFileName[0], "%s\\dpfilter.h", TargetDirectory); NtHeaderFile = fopen(&NtHeaderFileName[0], "w"); if (!NtHeaderFile) { printf("\n Unable to open filter header file %s\n", &NtHeaderFileName[0]); ExitCode = 1; PrintUsage: printf("GENLVL: Debug Print Filter Generator. Version " GENLVL_VERSION "\n"); printf(" Usage: genlvl [-t target directory] [componentid.tab directory]\n"); goto Exit; } // // Read component id table. // Count = 0; while (fgets(&Buffer[0], 132, ComponentFile) != NULL) { // // If the the line is null, begins with a blank, or begins with // a semicolon, then skip it. // if ((Buffer[0] == 0) || (Buffer[0] == '\n') || (Buffer[0] == ' ') || (Buffer[0] == ';')) { continue; } // // Insert the component name in the component name table. // Count += InsertName(&Buffer[0]); if (Count >= MAXIMUM_NAMES) { printf(" Component name table overflow at name %s\n", &Buffer[0]); ExitCode = 1; goto Exit; } } // // Check to determine if an error of eof was encountered. // if (feof(ComponentFile) == 0) { printf(" Error encountered while reading component name file\n"); ExitCode = 1; goto Exit; } // // Generate configuration manager header file. // if (GenerateCmHeaderFile(CmHeaderFile) == 0) { ExitCode = 1; goto Exit; } // // Generate configuration manager source file. // if (GenerateCmSourceFile(CmSourceFile) == 0) { ExitCode = 1; goto Exit; } // // Generate kernel debugger source file. // if (GenerateKdSourceFile(KdSourceFile) == 0) { ExitCode = 1; goto Exit; } // // Generate ntrtl.w append header file. // if (GenerateNtHeaderFile(NtHeaderFile) == 0) { ExitCode = 1; goto Exit; } // // Common program exit. // // Close any files that are open and exit with appropriate exit code. // Exit: if (CmHeaderFile != NULL) { fclose(CmHeaderFile); } if (CmSourceFile != NULL) { fclose(CmSourceFile); } if (ComponentFile != NULL) { fclose(ComponentFile); } if (KdSourceFile != NULL) { fclose(KdSourceFile); } if (NtHeaderFile != NULL) { fclose(NtHeaderFile); } return ExitCode; } ULONG GenerateCmHeaderFile( FILE *OutputFile ) { ULONG Count; PCHAR Name; // // Generate opening comments. // fprintf(OutputFile, "//\n"); fprintf(OutputFile, "// External component filter level definitions.\n"); fprintf(OutputFile, "//\n"); fprintf(OutputFile, "\n"); // // Output all the component variable names. // Count = 0; while ((Name = ComponentNameTable[Count]) != NULL) { fprintf(OutputFile, "extern ULONG Kd_%s_Mask;\n", Name); Count += 1; } fprintf(OutputFile, "\n"); return TRUE; } ULONG GenerateCmSourceFile( FILE *OutputFile ) { ULONG Count; PCHAR Name; // // Generate opening comments. // fprintf(OutputFile, "//\n"); fprintf(OutputFile, "// Debug print filter level initialization.\n"); fprintf(OutputFile, "//\n"); fprintf(OutputFile, "\n"); // // Output all the component variable names. // Count = 0; while ((Name = ComponentNameTable[Count]) != NULL) { fprintf(OutputFile, " { L\"Session Manager\\\\Debug Print Filter\",\n"); fprintf(OutputFile, " L\"%s\",\n", Name); fprintf(OutputFile, " &Kd_%s_Mask,\n", Name); fprintf(OutputFile, " NULL,\n"); fprintf(OutputFile, " NULL\n"); fprintf(OutputFile, " },\n"); fprintf(OutputFile, "\n"); Count += 1; } return TRUE; } ULONG GenerateKdSourceFile( FILE *OutputFile ) { ULONG Count; PCHAR Name; // // Generate opening comments and typedef. // fprintf(OutputFile, "//\n"); fprintf(OutputFile, "// Component filter levels.\n"); fprintf(OutputFile, "//\n"); fprintf(OutputFile, "\n"); // // Output all the component variable names with initialization. // Count = 0; while ((Name = ComponentNameTable[Count]) != NULL) { fprintf(OutputFile, "ULONG Kd_%s_Mask = 0;\n", Name); Count += 1; } fprintf(OutputFile, "ULONG Kd_ENDOFTABLE_Mask = 0;\n"); // // Output the initialization of the component variable table. // fprintf(OutputFile, "\n"); fprintf(OutputFile, "//\n"); fprintf(OutputFile, "// Component debug print filter table.\n"); fprintf(OutputFile, "//\n"); fprintf(OutputFile, "\n"); fprintf(OutputFile, "PULONG KdComponentTable[] = {\n"); Count = 0; while ((Name = ComponentNameTable[Count]) != NULL) { fprintf(OutputFile, " &Kd_%s_Mask,\n", Name); Count += 1; } // // Output one final dummy entry and close the initialization. // fprintf(OutputFile, " &Kd_ENDOFTABLE_Mask\n"); fprintf(OutputFile, "};\n"); fprintf(OutputFile, "\n"); return TRUE; } ULONG GenerateNtHeaderFile( FILE *OutputFile ) { ULONG Count; PCHAR Name; // // Generate opening comments and typedef. // fprintf(OutputFile, "//\n"); fprintf(OutputFile, "// Component name filter id enumeration and levels.\n"); fprintf(OutputFile, "//\n"); fprintf(OutputFile, "\n"); fprintf(OutputFile, "#define DPFLTR_ERROR_LEVEL 0\n"); fprintf(OutputFile, "#define DPFLTR_WARNING_LEVEL 1\n"); fprintf(OutputFile, "#define DPFLTR_TRACE_LEVEL 2\n"); fprintf(OutputFile, "#define DPFLTR_INFO_LEVEL 3\n"); fprintf(OutputFile, "#define DPFLTR_MASK 0x80000000\n"); fprintf(OutputFile, "\n"); fprintf(OutputFile, "typedef enum _DPFLTR_TYPE {\n"); // // Output all the enumerations. // Count = 0; while ((Name = ComponentNameTable[Count]) != NULL) { fprintf(OutputFile, " DPFLTR_%s_ID = %d,\n", Name, Count); Count += 1; } // // Output one final dummy entry and close the enumeration. // fprintf(OutputFile, " DPFLTR_ENDOFTABLE_ID\n"); fprintf(OutputFile, "} DPFLTR_TYPE;\n"); fprintf(OutputFile, "\n"); return TRUE; } // // Insert component name in component name table. // ULONG InsertName( IN PCHAR NewName ) { ULONG Index; ULONG Length; PCHAR OldName; // // Convert the input string to upper case. // Length = 0; while (NewName[Length] != 0) { if (NewName[Length] == '\n') { NewName[Length] = 0; break; } NewName[Length] = (CHAR)toupper(NewName[Length]); Length += 1; } // // Search for a duplicate name in the component name table. // Index = 0; while ((OldName = ComponentNameTable[Index]) != NULL) { if (strcmp(OldName, NewName) == 0) { printf(" Duplicate component name %s ignored.\n", NewName); return 0; } Index += 1; } // // Allocate a new table entry, copy the new name to the entry, and // insert the new entry in the table. // OldName = malloc(Length + 1); if (!OldName) { printf("Out of memory\n"); return 0; } strcpy(OldName, NewName); ComponentNameTable[Index] = OldName; ComponentNameTable[Index + 1] = NULL; return 1; }