diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/sdktools/doctor | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/sdktools/doctor')
-rw-r--r-- | private/sdktools/doctor/c2rtf.c | 691 | ||||
-rw-r--r-- | private/sdktools/doctor/doctor.c | 184 | ||||
-rw-r--r-- | private/sdktools/doctor/doctor.h | 202 | ||||
-rw-r--r-- | private/sdktools/doctor/makefile | 6 | ||||
-rw-r--r-- | private/sdktools/doctor/readtxt.c | 1425 | ||||
-rw-r--r-- | private/sdktools/doctor/sources | 17 | ||||
-rw-r--r-- | private/sdktools/doctor/strings.c | 113 | ||||
-rw-r--r-- | private/sdktools/doctor/strings.h | 24 | ||||
-rw-r--r-- | private/sdktools/doctor/symbol.c | 489 | ||||
-rw-r--r-- | private/sdktools/doctor/symbol.h | 53 | ||||
-rw-r--r-- | private/sdktools/doctor/writertf.c | 251 |
11 files changed, 3455 insertions, 0 deletions
diff --git a/private/sdktools/doctor/c2rtf.c b/private/sdktools/doctor/c2rtf.c new file mode 100644 index 000000000..5e80fbf75 --- /dev/null +++ b/private/sdktools/doctor/c2rtf.c @@ -0,0 +1,691 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <memory.h> +#define IN +#define OUT +#define MAX_COMMENT_SIZE 10000 +#define isalpha(c) ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) +#define isnum(c) (c >= '0' && c <= '9') +#define ISWHITESPACE(c) (c == ' ' || c == '\t') + +char *Header[] = { +"{\\rtf1\\pc {\\info{\\revtim\\mo07\\dy31\\yr1989}{\\creatim\\mo07\\dy31\\yr1989}", +"{\\nofchars9564}}\\deff0{\\fonttbl{\\f0\\fmodern pica;}", +"{\\f1\\fmodern Courier;}{\\f2\\fmodern elite;}{\\f3\\fmodern prestige;}", +"{\\f4\\fmodern lettergothic;}{\\f5\\fmodern gothicPS;}", +"{\\f6\\fmodern cubicPS;}{\\f7\\fmodern lineprinter;}", +"{\\f8\\fswiss Helvetica;}{\\f9\\fmodern avantegarde;}", +"{\\f10\\fmodern spartan;}{\\f11\\fmodern metro;}", +"{\\f12\\fmodern presentation;}{\\f13\\fmodern APL;}{\\f14\\fmodern OCRA;}", +"{\\f15\\fmodern OCRB;}{\\f16\\froman boldPS;}{\\f17\\froman emperorPS;}", +"{\\f18\\froman madaleine;}{\\f19\\froman zapf humanist;}", +"{\\f20\\froman classic;}{\\f21\\froman roman f;}{\\f22\\froman roman g;}", +"{\\f23\\froman roman h;}{\\f24\\froman timesroman;}{\\f25\\froman century;}", +"{\\f26\\froman palantino;}{\\f27\\froman souvenir;}{\\f28\\froman garamond;}", +"{\\f29\\froman caledonia;}{\\f30\\froman bodini;}{\\f31\\froman university;}", +"{\\f32\\fscript script;}{\\f33\\fscript scriptPS;}{\\f34\\fscript script c;}", +"{\\f35\\fscript script d;}{\\f36\\fscript commercial script;}", +"{\\f37\\fscript park avenue;}{\\f38\\fscript coronet;}", +"{\\f39\\fscript script h;}{\\f40\\fscript greek;}{\\f41\\froman kana;}", +"{\\f42\\froman hebrew;}{\\f43\\froman roman s;}{\\f44\\froman russian;}", +"{\\f45\\froman roman u;}{\\f46\\froman roman v;}{\\f47\\froman roman w;}", +"{\\f48\\fdecor narrator;}{\\f49\\fdecor emphasis;}", +"{\\f50\\fdecor zapf chancery;}{\\f51\\fdecor decor d;}", +"{\\f52\\fdecor old english;}{\\f53\\fdecor decor f;}{\\f54\\fdecor decor g;}", +"{\\f55\\fdecor cooper black;}{\\f56\\ftech Symbol;}{\\f57\\ftech linedraw;}", +"{\\f58\\ftech math7;}{\\f59\\ftech math8;}{\\f60\\ftech bar3of9;}", +"{\\f61\\ftech EAN;}{\\f62\\ftech pcline;}{\\f63\\ftech tech h;}}", +"{\\stylesheet {\\*\\cs1\\b\\f16 CT;}{\\*\\cs2\\b\\f16 CP;}{\\*\\cs3\\b\\f16 CD;}", +"{\\*\\cs4\\i\\f16 CI;}{\\*\\cs5\\f16\\ul CR;}{\\*\\s30\\sl-240\\sa240 \\f16", +"Normal;}{\\*\\s31\\li720\\fi-720\\sl-240\\sa240\\tqr\\tx432\\tx720 \\f16 L1;}", +"{\\*\\s32\\li1440\\fi-1440\\sl-240\\sa240\\tqr\\tx1152\\tx1440 \\f16 L2;}{\\*\\s33", +"\\li1152\\sl-240\\sa240 \\b\\f16\\ul P3;}{\\*\\s34\\li1728\\fi-576\\sl-240\\sa240", +"\\f16 P4;}{\\*\\s35\\li720\\sl-240\\sa240 \\f16 S1;}{\\*\\s36", +"\\li1440\\sl-240\\sa240 \\f16 S2;}{\\*\\s42\\ri576\\li576\\sl-240\\sa240 \\i\\f16", +"N1;}{\\*\\s43\\ri576\\li1296\\sl-240\\sa240 \\i\\f16 N2;}{\\*\\s44", +"\\li1152\\fi-576\\sl-240 \\f16 NL;}{\\*\\s52\\sl-240\\tx576\\tx1152\\tx1728", +"\\f16 PP;}{\\*\\s53\\li1152\\fi-576\\sl-240\\sa240 \\f16 PL;}{\\*\\s54", +"\\li1152\\sl-240\\sa240 \\f16 P2;}{\\*\\s62\\sl-240\\tqr\\tx9936 \\b\\f16 RH;}", +"{\\*\\s63\\qc\\sl-240 \\b\\f16 RF;}{\\*\\s64\\sl-240\\sa240 \\b\\f16 TN;}{\\*\\s65", +"\\sl-240\\sa240 \\i\\f16 TA;}{\\*\\s66\\sl-240 \\i\\f16 TR;}{\\*\\s72", +"\\li576\\fi-576\\sl-240\\sa240 \\f16 PT;}{\\*\\s73", +"\\li576\\sl-240\\tx1152\\tx1728\\tx2304\\tx2880\\tx3456\\tx4032\\tx4608\\tx5184\\tx5760\\tx6336\\tx6912", +"\\f7\\fs17 PC;}{\\*\\s74\\keep\\sl-240 \\f1 PD;}{\\*\\s88\\keepn\\sl-240\\sa240", +"\\b\\f16 heading 1;}{\\*\\s89\\keepn\\sl-240\\sa240 \\b\\f16 heading 2;}{\\*\\s90", +"\\keepn\\sl-240\\sa240 \\b\\f16 heading 3;}{\\*\\s91\\keepn\\sl-240\\sa240", +"\\b\\f16 heading 4;}{\\*\\s99", +"\\li288\\fi-288\\sl-240\\sb240\\tldot\\tx8064\\tqr\\tx8640 \\f16 toc 1;}", +"{\\*\\s100\\li576\\fi-288\\sl-240\\tldot\\tx8064\\tqr\\tx8640 \\f16 toc 2;}", +"{\\*\\s101\\li864\\fi-288\\sl-240\\tldot\\tx8064\\tqr\\tx8640 \\f16 toc 3;}", +"{\\*\\s102\\li1152\\fi-288\\sl-240\\tldot\\tx8064\\tqr\\tx8640 \\f16 toc 4;}", +"{\\*\\ds105\\linex576\\endnhere\\pgnrestart standard division;}{\\*\\ds106", +"\\pgnlcrm\\linex576\\endnhere\\pgnrestart DT;}}", +"\0" +}; + +FILE *InputFile; +char FileName[50],Function[50]; +char GetWord(); +void DoFormat(),GlobalFormat(); +int GetComment(),strpos(); +char Comment[MAX_COMMENT_SIZE]; +char *cp; /* pointer to current value in Comment */ + +int +_CRTAPI1 +main(argc,argv) +int argc; +char *argv[]; +{ + int i,nummods; + char *modules[255]; + + + nummods = 0; + if(argc != 3 && argc != 1) { + fprintf(stderr,"Usage: c2rtf [program function]\n"); + exit(1); + } + + i = 0; + while(*Header[i] != '\0') { + printf("%s\n",Header[i++]); + } + printf("\\ftnbj\\ftnrestart\\widowctrl \\sectd \\linex576\\endnhere"); + printf(" \\pard \\sl-240\n"); + + if(argc == 3) { + InputFile = fopen(argv[1],"r"); + if(InputFile == NULL) { + fprintf(stderr,"c2rtf: Error opening file %s.\n",argv[1]); + exit(2); + } + + strcpy(Function,argv[2]); + strcpy(FileName,argv[1]); + DoFormat(); + + fclose(InputFile); + } else { + if(scanf("%s",FileName) == EOF) { + exit(1); + } + InputFile = fopen(FileName,"r"); + if(InputFile == NULL) { + fprintf(stderr,"c2rtf: Error opening file %s.\n",FileName); + } else { + modules[nummods] = (char *)malloc((strlen(FileName) + 1) * sizeof(char)); + strcpy(modules[nummods++],FileName); + GlobalFormat(); + } + fclose(InputFile); + while(scanf("%s",Function) != EOF) { + if(!strncmp(strchr(Function,'\0')-2,".c",2) || + !strncmp(strchr(Function,'\0')-2,".s",2) || + !strncmp(strchr(Function,'\0')-2,".h",2)) { + strcpy(FileName,Function); + InputFile = fopen(FileName,"r"); + if(InputFile == NULL) { + fprintf(stderr,"c2rtf: Error opening file %s.\n",FileName); + continue; + } + for(i = 0; i < nummods; i++) { + if(!strcmp(modules[i],FileName)) { + break; + } + } + if(i == nummods) { + modules[nummods] = (char *)malloc((strlen(FileName) + 1) * sizeof(char)); + strcpy(modules[nummods++],FileName); + GlobalFormat(); + } + fclose(InputFile); + if(scanf("%s",Function) == EOF) { + exit(0); + } + } + InputFile = fopen(FileName,"r"); + if(InputFile == NULL) { + fprintf(stderr,"c2rtf: Error opening file %s for %s.\n",FileName,Function); + continue; + } + + DoFormat(); + + fclose(InputFile); + } + } + + printf("}\n"); + return 0; +} + +int +KillWhiteSpace( + char *killchars + ) +/*++ + +Routine Description: + + Removes white space from InputFile until non-whitespace character + is reached. + +Arguments: + + killchars - characters to be removed; generally some of ' ', '\t', '\n'. + +Return Value: + + Number of characters removed. + +--*/ + +{ + int i = 0; + char c; + + c = getc(InputFile); + while(strpos(killchars,c) != -1) { + i++; + c = getc(InputFile); + } + ungetc(c,InputFile); + return(i); +} + +char +GetWord( + OUT char *word, + IN char todo + ) +/*++ + +Routine Description: + + Finds the next string of alphabetic characters in InputFile. + Only letters are used. + +Arguments: + + word - pointer to space where the string is placed + + todo - a character that determines whether to get the next word + from the input or the previous word (stored in the static last). + +Return value: + + EOF if the end of file is reached before a word is found, 0 otherwise. + +--*/ + +{ + char c; + char *w; + static char last[50]; + + /* if todo is 'l' then return the previous word instead of next */ + if(todo == 'l') { + strcpy(word,last); + return(1); + } + + strcpy(last,word); + w = word; + c = getc(InputFile); + while(c != EOF && !(isalpha(c) || c == '_')) { + c = getc(InputFile); + } + if(c != EOF) { + *w++ = c; + } + while((c = getc(InputFile)) != EOF && (isalpha(c) || c == '_' || isnum(c))) { + *w++ = c; + } + ungetc(c,InputFile); + *w = '\0'; + if(strlen(word) == 0) + return(EOF); + else + return(0); +} + +void +DoFormat( + ) +/*++ + +Routine Description: + + Performs actual parsing and output formating. + +Arguments: + + none + +Return Value: + + none + +--*/ + +{ + char word[50],c; + int isfuncdef; + + isfuncdef = 0; + do { + do { + if(GetWord(word,'c') == EOF) { + fprintf(stderr,"c2rtf: Function %s not found in %s.\n",Function,FileName); + return; + } + } + while(strcmp(word,Function)); + KillWhiteSpace("\n\t "); + if(getc(InputFile) == '(') { + KillWhiteSpace("\t /"); + c = getc(InputFile); + if(c == '\n') { + isfuncdef = 1; + } + if(c == ')') { + KillWhiteSpace(" \t\n"); + c = getc(InputFile); + if(c != ';') { + ungetc(c,InputFile); + isfuncdef = 2; + } + } + } + } + while(!isfuncdef); + + printf("\\s89\\keepn\\sl-240\\sa240 \\plain \\b\\f16 %s\\par\n",Function); + + GetWord(word,'l'); + printf("\\pard \\s30\\sl-240\\sa0 \\plain \\b\\f16 %s\\par\n",word); + if(isfuncdef == 1) { + printf("%s(\\par\n",Function); + do { + printf("\\tab "); + do { + GetWord(word,'c'); + printf("%s ",word); + } + while(!strcmp(word,"IN") || !strcmp(word,"OUT")); + GetWord(word,'c'); + printf("\\plain \\i\\f16 %s\\plain \\b\\f16 ",word); + KillWhiteSpace("\t "); + while((c = getc(InputFile)) != ',' && c != '\n') { + ungetc(c,InputFile); + GetWord(word,'c'); + printf(" %s",word); + KillWhiteSpace("\t "); + } + if(c == '\n') { + printf("\\par\n\\tab )\\par"); + } else { + printf(",\\par\n"); + } + } + while(c != '\n'); + } else { + printf("%s()\\par\n",Function); + } + + if(GetComment()) { + printf("\\par \\pard\n"); + return; + } + + while(strncmp("Routine Description:",cp,20)) { + cp++; + if(*cp == '\0') { + fprintf(stderr,"c2rtf: Function %s in %s has no routine description.\n",Function,FileName); + printf("\\pard\n"); + return; + } + } + + printf("\\par\n"); + printf("\\plain \\f16\\ul Routine Description:\\plain \\f16 \\par \\par\n"); + printf("\\pard \\s53\\li576\\fi0\\sl-240\\sa240 "); + for(cp += 22; strchr(" \t\n/",*cp) != NULL; cp++); + + while(strncmp("Arguments:",cp,10)) { + if(*cp == '\n') { + if(*(cp + 1) == '\n' || !strncmp(cp + 1, "//\n",3)) { + printf("\\par\n"); + for(cp++; strchr(" \t\n/",*cp) != NULL; cp++); + continue; + } else { + putchar(' '); + for(cp++; strchr(" \t/",*cp) != NULL; cp++); + continue; + } + } + putchar(*cp); + cp++; + + if(*cp == '\0') { + fprintf(stderr,"c2rtf: Function %s in %s lacks 'Arguments:'.\n",Function,FileName); + printf("\\pard\n"); + return; + } + } + + printf("\\pard \\plain \\f16\\ul Parameters:\\plain \\f16 \\par \\par\n"); + printf("\\pard \\s53\\li1152\\fi-576\\sl-240\\sa240 "); + for(cp += 11; strchr(" \t\n/",*cp) != NULL; cp++); + printf("\\plain \\i\\f16 "); + do { + putchar(*cp++); + } + while(isalpha(*cp)); + printf("\\plain \\f16 "); + + while(strncmp("Return Value",cp,12)) { + if(*cp == '\n') { + for(cp++; strchr(" \t/",*cp) != NULL; cp++); + if(*cp == '\n') { + while(strchr(" \t\n/",*cp) != NULL) { + cp++; + } + if(!strncmp("Return Value",cp,12)) { + continue; + } + printf("\\par\n"); + printf("\\plain \\i\\f16 "); + do { + putchar(*cp++); + } + while(isalpha(*cp)); + printf("\\plain \\f16 "); + continue; + } else { + while(strchr(" \t\n/",*cp) != NULL) { + cp++; + } + putchar(' '); + putchar(*cp); + } + } else { + putchar(*cp); + } + cp++; + if(*cp == '\0') { + fprintf(stderr,"c2rtf: Function %s in %s lacks 'Return Value'.\n",Function,FileName); + printf("\\pard\n"); + return; + } + + } + + printf("\\par \\pard\n"); + printf("\\plain \\f16\\ul Return Value:\\plain \\f16 \\par \\par\n"); + printf("\\pard \\s53\\li576\\fi0\\sl-240\\sa240 "); + for(cp += 14; strchr(" \t\n/",*cp) != NULL; cp++); + + while(*cp != '\0' && strncmp(cp,"Environment",11)) { + if(*cp == '\n') { + for(cp++; strchr(" \t/",*cp) != NULL; cp++); + if(*cp == '\n') { + printf("\\par\n"); + for(cp++; strchr(" \n\t/",*cp) != NULL && *cp != EOF; cp++) { + if(*cp == '\0') { + break; + } + } + continue; + } else { + putchar(' '); + continue; + } + } + putchar(*cp); + cp++; + } + + if(*cp == '\0') { + printf("\\pard \\plain\n"); + return; + } + + printf("\\pard\n"); + printf("\\plain \\f16\\ul Environment:\\plain \\f16 \\par \\par\n"); + printf("\\pard \\s53\\li576\\fi0\\sl-240\\sa240 "); + for(cp += 14; strchr(" \t\n/",*cp) != NULL; cp++); + + while(*cp != '\0') { + if(*cp == '\n') { + for(cp++; strchr(" \t/",*cp) != NULL; cp++); + if(*cp == '\n') { + printf("\\par\n"); + for(cp++; strchr(" \n\t/",*cp) != NULL && *cp != EOF; cp++) { + if(*cp == '\0') { + break; + } + } + continue; + } else { + putchar(' '); + continue; + } + } + putchar(*cp); + cp++; + } + printf("\\pard \\plain\n"); +} + +int +GetComment( + ) +/*++ + +Routine Description: + + This routine loads the next comment in the input, defined in the normal C + manner with / *++ and --* / (no spaces in there) into the Comment[] + array. + +Arguments: + + none + +Return Value: + + 0 if successful + 1 if { precedes the next comment + 2 if the comment is not ended + 3 if comment size is larger than MAX_COMMENT_SIZE + +--*/ +{ + int index,i; + char temp[5]; + + + for(i = 0; i<4; i++) { + if((temp[i] = getc(InputFile)) == EOF) { + fprintf(stderr,"No comment found.\n"); + return(1); + } + } + temp[4] = '\0'; + + while(strcmp(temp,"/*++") && strcmp(temp + 2,"//")) { + temp[0] = temp[1]; + temp[1] = temp[2]; + temp[2] = temp[3]; + temp[3] = getc(InputFile); + if(temp[3] == EOF || temp[3] == '{') { + fprintf(stderr,"c2rtf: No comment found in %s of %s.\n",Function,FileName); + return(1); + } + } + + for(i = 0; i<4; i++) { + if((temp[i] = getc(InputFile)) == EOF) { + fprintf(stderr,"c2rtf: Comment not ended in %s of %s.\n",Function,FileName); + return(1); + } + } + temp[4] = '\0'; + + index = 0; + while(strcmp(temp,"--*/") && strcmp(temp,"//--")) { + if(temp[0] == '\t') { + for(i=0; i<8; i++) { + Comment[index++] = ' '; + } + } else { + Comment[index++] = temp[0]; + } + temp[0] = temp[1]; + temp[1] = temp[2]; + temp[2] = temp[3]; + temp[3] = getc(InputFile); + if(temp[3] == EOF) { + fprintf(stderr,"c2rtf: Comment not ended in %s of %s.\n",Function,FileName); + return(2); + } + if(index >= MAX_COMMENT_SIZE) { + fprintf(stderr,"c2rtf: Comment too large in %s of %s.\n",Function,FileName); + return(3); + } + } + + Comment[index] = '\0'; + cp = Comment; + return(0); +} + +int +strpos( + char *s, + char c + ) + +/*++ + +Routine Description: + + Finds the location of the character c in the string s. See section + 15.5 of _C: A Reference Manual_, page 300, for complete description. + +Parameters: + + s - "haystack" of characters to search for. + + c - character to search for. + +Return Value: + + The position of c in s or -1 if c is not in s. + +--*/ + +{ + int i; + + for(i = 0; *s != '\0'; s++,i++) { + if(c == *s) { + return(i); + } + } + return(-1); +} + +void GlobalFormat( + ) + +/*++ + +Routine Description: + + Formats the abstract of a module into RTF format. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + char c,word[50],basename[75],*s; + int i; + + do { + if(GetWord(word,'c') == EOF) { + fprintf(stderr,"Module %s lacks an abstract.\n"); + return; + } + } + while(strcmp("Abstract",word)); + + while((c = getchar()) == ' ' || c == '\t' || c == '\n') { + i++; + } + + i = 0; + if(c == '\"') { + while((c = getchar()) != '\"') { + basename[i++] = c; + } + basename[i] = '\0'; + } else { + ungetc(c,stdin); + for(s = FileName; *s != '\0'; s++) { + if(*s == '\\') { + i = 0; + } else { + basename[i++] = *s; + } + } + basename[i] = '\0'; + } + + if(!strcmp("continue",basename)) { + return; + } + + printf("\\page\n"); + printf("\\pard \\s88\\keepn\\sl-240\\sa240 \\plain \\b\\f16 %s\\par",basename); + printf("\\pard \\li576\\sl-240\\sa240 \\plain \\f16\n"); + + strcpy(word,"\0"); + KillWhiteSpace(" \t\n/:"); + do { + c = getc(InputFile); + if(c == '\n') { + putchar(' '); + KillWhiteSpace(" \t/"); + c = getc(InputFile); + if(c == '\n') { + printf("\\par\n"); + KillWhiteSpace(" \t\n/"); + GetWord(word,'c'); + if(strcmp(word,"Author")) { + printf("%s",word); + } + } else { + putchar(c); + } + } else { + putchar(c); + } + } + while(strcmp(word,"Author")); + + printf("\\pard\n"); + + return; + +} diff --git a/private/sdktools/doctor/doctor.c b/private/sdktools/doctor/doctor.c new file mode 100644 index 000000000..6edafc473 --- /dev/null +++ b/private/sdktools/doctor/doctor.c @@ -0,0 +1,184 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + doctor.c + +Abstract: + + Main source file for the doctor program. This program reads plain + text source files, with limited markups to describe formatting. It + output .RTF files, which can then be read into WORD to convert to + .DOC files. Hopefully, we can run the RTF_OS2.EXE conversion program + directly. + +Author: + + Steve Wood (stevewo) 02-Mar-1989 + + +Revision History: + +--*/ + +#include "doctor.h" + +// +// Variables maintained by doctor.c +// + +int DoctorReturnCode = 0; + +BOOLEAN VerboseOutput = FALSE; +BOOLEAN KeepIntermediateFile = FALSE; +BOOLEAN OutputQuickHelp = FALSE; // -h switch specified +BOOLEAN OutputRichTextFormat = TRUE; // -r switch NOT specified + +BOOLEAN +ConstructFileNames( PSZ FileNameArgument ); + +char TxtFileName[ MAXPATHLEN ]; // Full path spec of text input file +char RtfFileName[ MAXPATHLEN ]; // Full path spec of RTF output file +char DocFileName[ MAXPATHLEN ]; // Full path spec of RTF output file +char HlpFileName[ MAXPATHLEN ]; // Full path spec of QH output file + +#define RTF2DOC_PROGRAM "RTF_OS2.EXE" +char ProgramName[ MAXPATHLEN ]; // Full path name for RTF_OS2.EXE +char Arguments[ 4+2*MAXPATHLEN ]; // Command line arguments for RTF_OS2.EXE + +void +PrintUsage( void ) +{ + fprintf( stderr, "usage: DOCTOR [-?] [-v] [-k] {.TXT filename}\n" ); +} + + +int +_CRTAPI1 +main( + int argc, + char *argv[] + ) +{ + register char *s, c; + BOOLEAN result; + PROCESS_INFORMATION ProcessInformation; + STARTUPINFO StartupInfo; + + if (argc < 2) { + PrintUsage(); + exit( 1 ); + } + + while (--argc) { + s = *++argv; + if (*s == '-' || *s == '/') { + while (c = *++s) { + switch( tolower( c ) ) { + case '?': PrintUsage(); + exit( 1 ); + break; + + case 'h': OutputQuickHelp = TRUE; + break; + + case 'k': KeepIntermediateFile = TRUE; + break; + + case 'v': VerboseOutput = TRUE; + break; + + default: + fprintf( stderr, "Invalid switch: %c\n", (USHORT)c ); + break; + } + } + } + else + if (ConstructFileNames( s )) { + fprintf( stderr, "Reading %s", TxtFileName ); + if (InitTxtFileReader( TxtFileName )) { + fprintf( stderr, "\n" ); + if (OutputRichTextFormat) { + if (!OpenRtfFile( RtfFileName )) { + fprintf( stderr, + "Unable to open intermediate file - %s\n", + RtfFileName ); + exit(1); + } + } + + if (OutputRichTextFormat || OutputQuickHelp) { + result = ProcessTxtFile(); + + if (OutputRichTextFormat) + CloseRtfFile(); + if (OutputQuickHelp) + ; + } + + TermTxtFileReader(); + } + else { + fprintf( stderr, " - unable to open\n" ); + DoctorReturnCode = 1; + } + } + } + + return( DoctorReturnCode ); +} + +BOOLEAN +ConstructFileNames( PSZ FileNameArgument ) +{ + register char *s; + + RtfFileName[ 0 ] = '\0'; + DocFileName[ 0 ] = '\0'; + HlpFileName[ 0 ] = '\0'; + + rootpath( FileNameArgument, TxtFileName ); + while (!(s = strchr( TxtFileName, '.' ))) { + strcat( TxtFileName, ".txt" ); + } + + *s = '\0'; + strcpy( RtfFileName, TxtFileName ); + strcpy( DocFileName, TxtFileName ); + *s = '.'; + strcat( RtfFileName, ".rtf" ); + strcat( DocFileName, ".doc" ); + + return( TRUE ); +} + + +PVOID +AllocateMemory( + IN ULONG NumberBytes + ) +{ + register PVOID Memory = (PVOID)calloc( NumberBytes, 1 ); + + if (!Memory) + fprintf( stderr, "*** Out of memory, need %d bytes\n", NumberBytes ); + + return( Memory ); +} + + +PVOID +FreeMemory( + IN PVOID Memory + ) +{ + if (Memory) { + free( (char *)Memory ); + Memory = (PVOID)NULL; + } + + return( NULL ); +} diff --git a/private/sdktools/doctor/doctor.h b/private/sdktools/doctor/doctor.h new file mode 100644 index 000000000..edcee231c --- /dev/null +++ b/private/sdktools/doctor/doctor.h @@ -0,0 +1,202 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + doctor.h + +Abstract: + + Top level include file for doctor program + +Author: + + Steve Wood (stevewo) 02-Mar-1989 + +--*/ + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> +#include <windows.h> + +#include <stdio.h> +#include <stddef.h> +#include <stdlib.h> +#include <stdarg.h> +#include <limits.h> +#include <errno.h> +#include <ctype.h> +#include <signal.h> +#include <string.h> +#include <time.h> +#include <tools.h> + +#include "strings.h" +#include "symbol.h" + +typedef struct _RESULTCODES { /* resc */ + USHORT codeTerminate; + USHORT codeResult; +} RESULTCODES; +typedef RESULTCODES far *PRESULTCODES; + +typedef USHORT SEL, far *PSEL; + +#define MAKEP(sel, off) ((PVOID)MAKEULONG(off, sel)) +#define MAKEULONG(l, h) ((ULONG)(((USHORT)(l)) | ((ULONG)((USHORT)(h))) << 16)) + +USHORT pascal far DosAllocSeg( USHORT, PSEL, USHORT ); +USHORT pascal far DosReallocSeg(USHORT, SEL); +USHORT pascal far DosFreeSeg( SEL ); + +USHORT pascal far DosExecPgm(char far *, SHORT, USHORT, char far *, char far *, PRESULTCODES, char far *); +USHORT pascal far DosSearchPath(USHORT, char far *, char far *, char far *, USHORT); + +/* DosExecPgm functions */ + +#define EXEC_SYNC 0 +#define EXEC_ASYNC 1 +#define EXEC_ASYNCRESULT 2 +#define EXEC_TRACE 3 +#define EXEC_BACKGROUND 4 +#define EXEC_LOAD 5 + +#define SEARCH_CUR_DIRECTORY 0x01 +#define SEARCH_ENVIRONMENT 0x02 +#define SEARCH_PATH 0x00 + +// +// Entry points in doctor.c +// +PVOID +AllocateMemory( + IN ULONG NumberBytes + ); + +PVOID +FreeMemory( + IN PVOID Memory + ); + +// +// Entry points in readtxt.c +// +VOID +ErrorMessage( + IN PSZ FormatString, + IN PSZ InsertString + ); + +BOOLEAN +InitTxtFileReader( + IN PSZ TxtFileName + ); + +BOOLEAN +TermTxtFileReader( VOID ); + +#define MAXLINELENGTH 1024 +#define DOCTORCOMMANDCHAR '.' +#define DOCTORLINECONTCHAR '\\' + +BOOLEAN +ProcessTxtFile( VOID ); + + +// +// Entry points in writertf.c +// +BOOLEAN +OpenRtfFile( + IN PSZ RtfFileName + ); + + +BOOLEAN +CloseRtfFile( VOID ); + +BOOLEAN +RtfTitlePage( + IN PSZ Title, + IN PSZ Author, + IN PSZ Revision, + IN PSZ Creation + ); + +BOOLEAN +RtfHeading( + ULONG HeadingLevel, + PSZ HeadingNumber, + PSZ HeadingTitle + ); + +BOOLEAN +RtfParagraph( + PSZ ParagraphStyle, + PSZ CharStyle, + PSZ ParagraphBullet, + PSZ ParagraphText + ); + +BOOLEAN +RtfOpenPara( + PSZ ParagraphStyle, + PSZ LeadingText + ); + +BOOLEAN +RtfClosePara( + PSZ TrailingText + ); + +BOOLEAN +RtfWord( + PSZ CharStyle, + PSZ LeadingText, + PSZ WordText + ); + +#define EMDASH "\\f1 \\plain " + +#define CS_NORMAL "\\plain " +#define CS_CP "\\cs2\\b\\f16 " +#define CS_CD "\\cs3\\b\\f16 " +#define CS_CT "\\cs1\\b\\f16 " +#define CS_CI "\\cs4\\i\\f16 " +#define CS_CR "\\cs5\\f16\\ul " + +#define PS_PSKEEP "\\pard \\s48\\keepn\\sl-240\\sa240 \\plain \\f16 " +#define PS_PS "\\pard \\s30\\sl-240\\sa240 \\plain \\f16 " +#define PS_L1 "\\pard \\s31\\li720\\fi-720\\sl-240\\sa240\\tqr\\tx432\\tx720 \\plain \\f16 " +#define PS_L2 "\\pard \\s32\\li1152\\fi-1152\\sl-240\\sa240\\tqr\\tx864\\tx1152 \\plain \\f16 " +#define PS_L3 "\\pard \\s45\\li1584\\fi-1584\\sl-240\\sa240\\tqr\\tx1296\\tx1584 \\plain \\f16 " +#define PS_L4 "\\pard \\s46\\li2016\\fi-2016\\sl-240\\sa240\\tqr\\tx1728\\tx2016 \\plain \\f16 " +#define PS_T5 "\\pard \\s47\\li1440\\fi-288\\sl-240\\tldot\\tx8064\\tqr\\tx8640 \\plain \\f16 " +#define PS_S1 "\\pard \\s35\\li432\\sl-240\\sa240 \\plain \\f16 " +#define PS_S2 "\\pard \\s36\\li1152\\sl-240\\sa240 \\plain \\f16 " +#define PS_PT "\\pard \\s72\\li576\\fi-576\\sl-240\\sa240 \\plain \\f16 " +#define PS_PP "\\pard \\s52\\keep\\keepn\\sl-240\\tx576\\tx1152\\tx1728 \\plain \\f16 " +#define PS_PL "\\pard \\s53\\li1152\\fi-576\\sl-240\\sa240 \\plain \\f16 " +#define PS_P2 "\\pard \\s54\\li1152\\sl-240\\sa240 \\plain \\f16 " +#define PS_PV "\\pard \\s55\\li576\\sl-240\\sa240 \\plain \\f16 " +#define PS_P3 "\\pard \\s33\\li1152\\sl-240\\sa240 \\plain \\b\\f16\\ul " +#define PS_P4 "\\pard \\s34\\li1728\\fi-576\\sl-240\\sa240 \\plain \\f16 " +#define PS_P5 "\\pard \\s37\\li1728\\sl-240\\sa240 \\plain \\b\\f16\\ul " +#define PS_P6 "\\pard \\s38\\li2304\\fi-576\\sl-240\\sa240 \\plain \\f16 " +#define PS_P7 "\\pard \\s40\\li2304\\sl-240\\sa240 \\plain \\b\\f16\\ul " +#define PS_P8 "\\pard \\s41\\li2880\\fi-576\\sl-240\\sa240 \\plain \\f16 " +#define PS_N1 "\\pard \\s42\\ri576\\li576\\sl-240\\sa240 \\plain \\i\\f16 " +#define PS_N2 "\\pard \\s43\\ri576\\li1296\\sl-240\\sa240 \\plain \\i\\f16 " +#define PS_NL "\\pard \\s44\\li1152\\fi-576\\sl-240 \\plain \\f16 " +#define PS_RH "\\pard \\s62\\sl-240\\tqr\\tx9936 \\plain \\b\\f16 " +#define PS_RF "\\pard \\s63\\qc\\sl-240 \\plain \\b\\f16 " +#define PS_PC "\\pard \\s73\\li576\\sl-240\\tx1152\\tx1728\\tx2304\\tx2880\\tx3456\\tx4032\\tx4608\\tx5184\\tx5760\\tx6336\\tx6912 \\f7\\fs17 " +#define PS_PD "\\pard \\s74\\keep\\keepn\\sl-240 \\f1 " +#define PS_H1 "\\pard \\s88\\keepn\\sl-240\\sa240 \\plain \\b\\f16 " +#define PS_H2 "\\pard \\s89\\keepn\\sl-240\\sa240 \\plain \\b\\f16 " +#define PS_H3 "\\pard \\s90\\keepn\\sl-240\\sa240 \\plain \\b\\f16 " +#define PS_H4 "\\pard \\s91\\keepn\\sl-240\\sa240 \\plain \\b\\f16 " +#define PS_H5 "\\pard \\s92\\keepn\\sl-240\\sa240 \\plain \\b\\f16 " +#define PS_HN "\\pard \\keepn\\sl-240\\sa240 \\plain \\b\\f16 " diff --git a/private/sdktools/doctor/makefile b/private/sdktools/doctor/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/sdktools/doctor/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/sdktools/doctor/readtxt.c b/private/sdktools/doctor/readtxt.c new file mode 100644 index 000000000..f7617c69c --- /dev/null +++ b/private/sdktools/doctor/readtxt.c @@ -0,0 +1,1425 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + readtext.c + +Abstract: + + This module contains the code to read the text input format supported + by the doctor program. + +Author: + + Steve Wood (stevewo) 02-Mar-1989 + +Revision History: + +--*/ + +#include "doctor.h" + +extern BOOLEAN VerboseOutput; + +BOOLEAN PreviousParagraphHeading; + +BOOLEAN +PushTxtFile( + IN PSZ TxtFileName, + IN ULONG TxtFileEof + ); + +BOOLEAN +PopTxtFile( + VOID + ); + +BOOLEAN +ReadTxtPara( + BOOLEAN LineBreaksPara + ); + +typedef struct _PARAINFO { + ULONG Type; + ULONG Level; + ULONG Lines; + BOOLEAN Bullet; + BOOLEAN FunctionPrototype; + BOOLEAN TrailingColon; + ULONG CountOfTokensBeforeEmDash; + PSZ EmDash; + PSZ Text; + PSZ NextWord; +} PARAINFO, *PPARAINFO; + +PARAINFO TxtFilePara; + +#define TXT_PARA_BUFFER_LENGTH 4096 +char TxtParaBuffer[ TXT_PARA_BUFFER_LENGTH ]; +char TxtWordBuffer[ TXT_PARA_BUFFER_LENGTH/8 ]; + +#define PARA_EOF 0 +#define PARA_CMD 1 +#define PARA_TXT 2 + +PSZ +GetParaWord( + BOOLEAN BlankDelimitted + ); + +BOOLEAN +ProcessTxtCommand( + VOID + ); + +#define MAX_TXTFILESTACK_DEPTH 16 +#define MAX_PARAMTABLESTACK_DEPTH 8 +#define MAX_HEADING_LEVEL 8 + +#define TFS_PARAGRAPH 0 +#define TFS_RETURN_TYPE 1 +#define TFS_FUNCTION_NAME 2 +#define TFS_PARAMETER_DECL 3 +#define TFS_END_FUNCTION 4 +#define TFS_FUNCTION_LIST 5 + +#define TXT_FILE 0 +#define SRC_FILE_MODULE_HEADER 1 +#define SRC_FILE_FUNCTION_HEADER 2 + +typedef struct _TXTFILE { + ULONG TxtFileState; + ULONG TxtFileEof; + PSTRING TxtFileName; + ULONG TxtLineNumber; + FILE *TxtFileHandle; +} TXTFILE, *PTXTFILE; + +TXTFILE TxtFileStack[ MAX_TXTFILESTACK_DEPTH ]; +ULONG TxtFileStackDepth = MAX_TXTFILESTACK_DEPTH; +PTXTFILE CurrentTxtFile; +BOOLEAN TitlePageWritten = FALSE; +ULONG LinesPerInch; +BOOLEAN InLiteralText = FALSE; +BOOLEAN LiteralFixedPitchFont = FALSE; +BOOLEAN GlobalHighlight = FALSE; + +PSTRING TitleString; +PSTRING AuthorName; +PSTRING CreationDate; +PSTRING RevisionNumber; + +SYMBOLTABLEHANDLE HighLightTable; + +SYMBOLTABLEHANDLE ParamTableStack[ MAX_PARAMTABLESTACK_DEPTH ]; +ULONG ParamTableStackDepth = MAX_PARAMTABLESTACK_DEPTH; +ULONG HeadingLevels[ MAX_HEADING_LEVEL ]; + +BOOLEAN ProcessHeadingCmd( PSZ CmdLine ); +BOOLEAN ProcessBeginCmd( PSZ CmdLine ); +BOOLEAN CheckForEndCmd( PSZ CmdLine ); +BOOLEAN ProcessBulletedList( VOID ); +BOOLEAN ProcessSimpleList( VOID ); +BOOLEAN ProcessFunctionList( VOID ); +BOOLEAN ProcessFunction( VOID ); +BOOLEAN ProcessFunctionPrototype( PULONG FuncType ); + +#define FUNC_TYPE_VOID_RETURN 0x1 +#define FUNC_TYPE_VOID_PARMS 0x2 + +BOOLEAN ProcessFunctionParameters( VOID ); +BOOLEAN ProcessStructure( VOID ); +BOOLEAN ProcessFunctionNames( VOID ); +BOOLEAN ProcessFieldNames( VOID ); +BOOLEAN ProcessLiteralText( VOID ); +BOOLEAN ProcessTextParagraph( VOID ); + +BOOLEAN OutputParagraph( + PSZ ParaStyle, + PSZ Bullet, + ULONG ParaType + ); + +#define OUTPUT_PARA_TEXT 0 +#define OUTPUT_PARA_FUNCLIST 1 +#define OUTPUT_PARA_FUNCPROTO 2 + +VOID +SetTxtFileState( + ULONG NewState + ); + +PSZ +GetNextWord( + PSZ *String, + ULONG *HighLight + ); + +BOOLEAN +GetIdentifier( + register PSZ DstString, + PSZ *SrcString + ); + +PSZ +AddFuncName( + PSZ FuncString + ); + +PSZ +AddParmName( + PSZ ParmString + ); + +PSZ +AddTypeName( + PSZ FuncString + ); + +PSZ +SkipSpaces( + IN PSZ String + ); + +PSZ +MarkToken( + IN PSZ String + ); + +BOOLEAN +InitTxtFileReader( + IN PSZ TxtFileName + ) +{ + ULONG i; + + if (!(HighLightTable = CreateSymbolTable( 37, TRUE ))) { + return( FALSE ); + } + + ParamTableStackDepth = MAX_PARAMTABLESTACK_DEPTH; + + TitleString = MakeString( "*** .title ***" ); + AuthorName = MakeString( "*** .author ***" ); + CreationDate = MakeString( "*** .created ***" ); + RevisionNumber = MakeString( "*** .revision ***" ); + + for (i=0; i<MAX_HEADING_LEVEL; i++) { + HeadingLevels[ i ] = 0; + } + + TxtFileStackDepth = MAX_TXTFILESTACK_DEPTH; + CurrentTxtFile = NULL; + return( PushTxtFile( TxtFileName, TXT_FILE ) ); +} + + +BOOLEAN +TermTxtFileReader( VOID ) +{ + HighLightTable = DestroySymbolTable( HighLightTable ); + + while (PopTxtFile()) + ; + + return( TRUE ); +} + + +VOID +ErrorMessage( + IN PSZ FormatString, + IN PSZ InsertString + ) +{ + if (CurrentTxtFile) { + fprintf( stderr, "%s(%d) : ", CurrentTxtFile->TxtFileName->Buffer, + CurrentTxtFile->TxtLineNumber ); + } + + fprintf( stderr, FormatString, InsertString ); + fprintf( stderr, "\n" ); +} + + +BOOLEAN +PushTxtFile( + IN PSZ TxtFileName, + IN ULONG TxtFileEof + ) +{ + FILE *TxtFileHandle; + PSZ s; + + if (TxtFileStackDepth && + (TxtFileHandle = fopen( TxtFileName, "r" ))) { + + s = TxtFileName; + while (*s) { + switch (*s++) { + case ':': + case '/': + case '\\': + TxtFileName = s; + } + } + + CurrentTxtFile = &TxtFileStack[ --TxtFileStackDepth ]; + CurrentTxtFile->TxtFileName = MakeString( TxtFileName ); + CurrentTxtFile->TxtFileHandle = TxtFileHandle; + CurrentTxtFile->TxtLineNumber = 0; + CurrentTxtFile->TxtFileEof = TxtFileEof; + CurrentTxtFile->TxtFileState = TFS_PARAGRAPH; + return( TRUE ); + } + else + return( FALSE ); +} + + +BOOLEAN +PopTxtFile( + VOID + ) +{ + if (CurrentTxtFile && (CurrentTxtFile->TxtFileHandle != NULL)) { + fclose( CurrentTxtFile->TxtFileHandle ); + CurrentTxtFile->TxtFileHandle = NULL; + } + + if (TxtFileStackDepth < MAX_TXTFILESTACK_DEPTH) + CurrentTxtFile = &TxtFileStack[ ++TxtFileStackDepth ]; + else + CurrentTxtFile = NULL; + + return( (BOOLEAN)(CurrentTxtFile != NULL) ); +} + + +BOOLEAN +ReadTxtPara( + BOOLEAN LineBreaksPara + ) +{ + PSZ s, s1; + ULONG n, cb; + int c; + + s = TxtParaBuffer; + n = TXT_PARA_BUFFER_LENGTH; + *s = '\0'; + + TxtFilePara.Type = PARA_EOF; + TxtFilePara.Text = "*** END OF FILE ***"; + TxtFilePara.NextWord = NULL; + TxtFilePara.FunctionPrototype = FALSE; + TxtFilePara.TrailingColon = FALSE; + TxtFilePara.Lines = 0; + while (TRUE) { + s1 = s; + while ((c = fgetc( CurrentTxtFile->TxtFileHandle )) != EOF) { + if (c == '\n') { + *s1 = '\0'; + break; + } + + if (c == '\\') { + *s1++ = (char)c; + } + + *s1++ = (char)c; + } + + if (c == EOF) { + break; + } + + CurrentTxtFile->TxtLineNumber++; + cb = s1 - s; + + if (!cb) { + if (!TxtFilePara.Lines) { + continue; + } + + break; + } + + TxtFilePara.Lines++; + s1 = s; + while (*s1 == ' ') { + s1++; + } + + if (*s1 == DOCTORCOMMANDCHAR) { + if (s != s1) { + ErrorMessage( "Illegal command indentation - %s", s ); + break; + } + + if (TxtFilePara.Lines > 1) { + fseek( CurrentTxtFile->TxtFileHandle, -(long)cb, SEEK_CUR ); + } + else { + TxtFilePara.Type = PARA_CMD; + } + break; + } + + TxtFilePara.Type = PARA_TXT; + if (LineBreaksPara) { + break; + } + + if (TxtFilePara.Lines > 1) { + cb -= (s1 - s); + strcpy( s, s1 ); + } + + s += cb; + *s++ = ' '; + *s = '\0'; + n -= cb+1; + } + + while (*--s == ' ') { + *s = '\0'; + } + + if (TxtFilePara.Lines == 1) { + if (*s == ':') { + TxtFilePara.TrailingColon = TRUE; + } + } + else { + if (!strcmp( s-1, " )" ) || + !strcmp( s-2, " );" ) || + !strcmp( s-6, " VOID )" ) || + !strcmp( s-7, " VOID );" ) + ) { + TxtFilePara.FunctionPrototype = TRUE; + } + } + + s = TxtParaBuffer; + cb = 0; + while (*s == ' ') { + cb++; + s++; + } + + TxtFilePara.Bullet = FALSE; + if (!LineBreaksPara && cb && !TxtFilePara.FunctionPrototype && + (TxtFilePara.Type == PARA_TXT) + ) { + if (cb % 4) { + if (s[1] == ' ' && (s[0] == 'o' || s[0] == '-')) { + cb += 2; + *s++ = ' '; + if (*++s != ' ') { + TxtFilePara.Bullet = TRUE; + } + else { + ErrorMessage( "Illegal bulleted text - %s", TxtParaBuffer ); + return( FALSE ); + } + } + else { + ErrorMessage( "Illegal indentation - %s", TxtParaBuffer ); + return( FALSE ); + } + } + + TxtFilePara.Level = cb/4; + } + else { + TxtFilePara.Level = 0; + } + + TxtFilePara.CountOfTokensBeforeEmDash = 0; + TxtFilePara.EmDash = NULL; + TxtFilePara.Text = s; + TxtFilePara.NextWord = s; + + if (!TxtFilePara.FunctionPrototype) { + while (*s) { + if (*s == ' ') { + s++; + if (*s == ' ') { + break; + } + + if (TxtFilePara.CountOfTokensBeforeEmDash++ >= 2) { + break; + } + + if (*s == '-' && *++s == ' ' && *++s != ' ') { + TxtFilePara.EmDash = s - 2; + break; + } + } + else { + s++; + } + } + } + + if (!TxtFilePara.EmDash) { + TxtFilePara.CountOfTokensBeforeEmDash = 0; + } + +#if 0 + fprintf( stderr, + "\n\nReadTxtPara: Type: %d \"%s\"\n", + TxtFilePara.Type, + TxtFilePara.Text + ); + + fprintf( stderr, + "Level: %d Bullet: %d Func: %d Lines: %d Colon: %d EmDash: (%d)%.8s\n\n", + TxtFilePara.Level, + TxtFilePara.Bullet, + TxtFilePara.FunctionPrototype, + TxtFilePara.Lines, + TxtFilePara.TrailingColon, + TxtFilePara.CountOfTokensBeforeEmDash, + TxtFilePara.EmDash ? TxtFilePara.EmDash : "" + ); +#endif + + return( (BOOLEAN)(TxtFilePara.Type != PARA_EOF) ); +} + +PSZ +GetParaWord( + BOOLEAN BlankDelimitted + ) +{ + PSZ s, dst; + + s = TxtFilePara.NextWord; + if (!s) { + return( NULL ); + } + + while (*s == ' ') { + s++; + } + + dst = TxtWordBuffer; + *dst = '\0'; + if (BlankDelimitted) { + while (*s && *s > ' ') { + *dst++ = *s++; + } + + } + else { + if (iscsymf( *s )) { + while (iscsym( *s )) { + *dst++ = *s++; + } + } + else { + while (*s && !iscsymf( *s )) { + *dst++ = *s++; + } + + if (dst != TxtWordBuffer) { + while (dst[-1] == ' ') { + dst--; + } + } + } + } + + if (TxtWordBuffer[ 0 ]) { + TxtFilePara.NextWord = s; + + *dst = '\0'; + if (dst != TxtWordBuffer) { + return( TxtWordBuffer ); + } + } + + TxtFilePara.NextWord = NULL; + return( NULL ); +} + + +BOOLEAN +ProcessTxtFile( VOID ) +{ + while (ReadTxtPara( FALSE )) { + if (TxtFilePara.Type == PARA_CMD) { + if (!ProcessTxtCommand()) { + return( FALSE ); + } + } + else + if (TxtFilePara.Type == PARA_TXT) { + ProcessTextParagraph(); + PreviousParagraphHeading = FALSE; + } + } + + return( TRUE ); +} + + +BOOLEAN +ProcessTxtCommand( VOID ) +{ + PSZ Cmd = TxtFilePara.Text; + register PSZ s; + + s = Cmd; + while (*s > ' ') + s++; + + *s++ = '\0'; + + if (!_stricmp( Cmd, ".title" )) { + TitleString = MakeString( s ); + return( (BOOLEAN)(TitleString != NULL) ); + } + else + if (!_stricmp( Cmd, ".author" )) { + AuthorName = MakeString( s ); + return( (BOOLEAN)(AuthorName != NULL) ); + } + else + if (!_stricmp( Cmd, ".revision" )) { + RevisionNumber = MakeString( s ); + return( (BOOLEAN)(RevisionNumber != NULL) ); + } + else + if (!_stricmp( Cmd, ".created" )) { + CreationDate = MakeString( s ); + return( (BOOLEAN)(CreationDate != NULL) ); + } + else + if (!_stricmp( Cmd, ".heading" )) { + if (!TitlePageWritten) { + RtfTitlePage( TitleString->Buffer, + AuthorName->Buffer, + RevisionNumber->Buffer, + CreationDate->Buffer ); + TitlePageWritten = TRUE; + } + + return( ProcessHeadingCmd( s ) ); + } + else + if (!_stricmp( Cmd, ".begin" )) { + return( ProcessBeginCmd( s ) ); + } + else + if (!_stricmp( Cmd, ".end" )) { + ErrorMessage( ".end command without .begin command", NULL ); + return( FALSE ); + } + else { + ErrorMessage( "Unknown command - %s", Cmd ); + return( FALSE ); + } +} + +BOOLEAN +ProcessHeadingCmd( + PSZ CmdLine + ) +{ + ULONG HeadingLevel, i; + PSZ HeadingString, s; + char HeadingBuffer[ 32 ]; + + CmdLine = SkipSpaces( CmdLine ); + HeadingLevel = (ULONG)atoi( CmdLine ); + if (HeadingLevel >= MAX_HEADING_LEVEL ) { + ErrorMessage( "Invalid heading level - %s", CmdLine ); + return( FALSE ); + } + else { + HeadingString = MarkToken( CmdLine ); + HeadingLevels[ HeadingLevel ] += 1; + s = HeadingBuffer; + for (i=0; i<=HeadingLevel; i++) { + sprintf( s, "%d", HeadingLevels[ i ] ); + s += strlen( s ); + if (!HeadingLevel || i<HeadingLevel) { + *s++ = '.'; + } + *s = '\0'; + } + for (i=HeadingLevel+1; i<MAX_HEADING_LEVEL; i++) { + HeadingLevels[ i ] = 0; + } + + RtfHeading( HeadingLevel, HeadingBuffer, HeadingString ); + PreviousParagraphHeading = TRUE; + return( TRUE ); + } +} + +BOOLEAN +ProcessBeginCmd( + PSZ CmdLine + ) +{ + CmdLine = SkipSpaces( CmdLine ); + + if (!_stricmp( CmdLine, "simple" )) { + return( ProcessSimpleList() ); + } + else + if (!_stricmp( CmdLine, "funclist" )) { + return( ProcessFunctionList() ); + } + else + if (!_stricmp( CmdLine, "literal" )) { + return( ProcessLiteralText() ); + } + else + if (!_stricmp( CmdLine, "funcnames" )) { + return( ProcessFunctionNames() ); + } + else + if (!_stricmp( CmdLine, "fieldnames" )) { + return( ProcessFieldNames() ); + } + else { + ErrorMessage( "Unknown .begin argument - %s", CmdLine ); + return( FALSE ); + } +} + +BOOLEAN +CheckForEndCmd( + PSZ CmdLine + ) +{ + if (!_stricmp( CmdLine, ".end" )) { + return( TRUE ); + } + else { + return( FALSE ); + } +} + + +BOOLEAN ProcessBulletedList( VOID ) +{ + PSZ Bullet; + PSZ ParaStyle; + ULONG StartingLevel = TxtFilePara.Level; + + do { + if (TxtFilePara.Type == PARA_CMD) { + return( ProcessTxtCommand() ); + } + + if (TxtFilePara.Level < StartingLevel) { + break; + } + + if (TxtFilePara.Level == 1) { + ParaStyle = PS_L1; + } + else + if (TxtFilePara.Level == 2) { + ParaStyle = PS_L2; + } + else { + ErrorMessage( "Illegal nesting of bulleted list - %s", + TxtFilePara.Text + ); + + return( FALSE ); + } + + if (TxtFilePara.Bullet) { + Bullet = "\to\t"; + } + else { + Bullet = "\t\t"; + } + + OutputParagraph( ParaStyle, Bullet, OUTPUT_PARA_TEXT ); + } + while (ReadTxtPara( FALSE )); + + return( TRUE ); +} + + +BOOLEAN ProcessSimpleList( VOID ) +{ + PSZ ParaStyle; + + while (ReadTxtPara( FALSE )) { + if (TxtFilePara.Type == PARA_CMD) { + break; + } + + if (TxtFilePara.Level == 1) { + ParaStyle = PS_S1; + } + else + if (TxtFilePara.Level == 2) { + ParaStyle = PS_S2; + } + else { + ErrorMessage( "Illegal nesting of simple list - %s", + TxtFilePara.Text + ); + + return( FALSE ); + } + + OutputParagraph( ParaStyle, "", OUTPUT_PARA_TEXT ); + } + + return( CheckForEndCmd( TxtFilePara.Text ) ); +} + + +BOOLEAN ProcessFunctionList( VOID ) +{ + while (ReadTxtPara( FALSE )) { + if (TxtFilePara.Type == PARA_CMD) { + break; + } + + OutputParagraph( PS_NL, "", OUTPUT_PARA_FUNCLIST ); + } + + RtfParagraph( PS_NL, "", "", "" ); + return( CheckForEndCmd( TxtFilePara.Text ) ); +} + +BOOLEAN ProcessFunction( VOID ) +{ + ULONG VoidFunction; + + if (!ProcessFunctionPrototype( &VoidFunction )) { + return( FALSE ); + } + + ReadTxtPara( FALSE ); + if (TxtFilePara.Type != PARA_TXT || + TxtFilePara.Lines != 1 || + _stricmp( TxtFilePara.Text, "Parameters:" ) + ) { + if (!(VoidFunction & FUNC_TYPE_VOID_PARMS)) { + ErrorMessage( "Missing Parameters: line - %s", TxtFilePara.Text ); + return( FALSE ); + } + else { + RtfParagraph( PS_PP, "", "", "" ); + } + } + else { + if (VoidFunction & FUNC_TYPE_VOID_PARMS) { + ErrorMessage( "VOID Function cant have parameters - %s", TxtFilePara.Text ); + return( FALSE ); + } + + RtfParagraph( PS_PP, "", "", "" ); + RtfParagraph( PS_PP, CS_CR, "", TxtFilePara.Text ); + RtfParagraph( PS_PP, "", "", "" ); + + } + + if (!(VoidFunction & FUNC_TYPE_VOID_PARMS)) { + if (!ProcessFunctionParameters()) { + return( FALSE ); + } + } + + if (TxtFilePara.Type != PARA_TXT || + _stricmp( TxtFilePara.Text, "Return Value:" ) + ) { + if (!(VoidFunction & FUNC_TYPE_VOID_RETURN)) { + ErrorMessage( "Return Value: line missing - %s", TxtFilePara.Text ); + return( FALSE ); + } + } + else { + if (VoidFunction & FUNC_TYPE_VOID_RETURN) { + ErrorMessage( "Return Value: line on VOID - %s", TxtFilePara.Text ); + return( FALSE ); + } + else { + RtfParagraph( PS_PP, CS_CR, "", TxtFilePara.Text ); + RtfParagraph( PS_PP, "", "", "" ); + while (ReadTxtPara( FALSE )) { + if (TxtFilePara.Type == PARA_CMD) { + return( ProcessTxtCommand() ); + } + else + if (TxtFilePara.Type == PARA_TXT) { + if (TxtFilePara.Level > 0) { + OutputParagraph( PS_PV, "", OUTPUT_PARA_TEXT ); + } + else + return( ProcessTextParagraph() ); + } + } + } + } + + return( TRUE ); +} + +#define FUNCPROTO_STATE_RETURN_TYPE 1 +#define FUNCPROTO_STATE_NAME1 2 +#define FUNCPROTO_STATE_NAME2 3 +#define FUNCPROTO_STATE_PARM1 4 +#define FUNCPROTO_STATE_PARM2 5 +#define FUNCPROTO_STATE_PARM3 6 +#define FUNCPROTO_STATE_DONE 7 + +BOOLEAN ProcessFunctionPrototype( + PULONG VoidFunction + ) +{ + BOOLEAN FirstParmToken, PrevAsterisk; + ULONG State; + PSZ s; + + *VoidFunction = 0; + PrevAsterisk = FALSE; + State = FUNCPROTO_STATE_RETURN_TYPE; + while (s = GetParaWord( FALSE )) { +donextword: + switch (State) { + case FUNCPROTO_STATE_RETURN_TYPE: + RtfParagraph( PS_PP, CS_CT, "", s ); + if (!strcmp( s, "VOID" )) { + *VoidFunction |= FUNC_TYPE_VOID_RETURN; + } + + RtfOpenPara( PS_PP, "" ); + State = FUNCPROTO_STATE_NAME1; + break; + + case FUNCPROTO_STATE_NAME1: + if (!strcmp( s, "typedef" )) { + RtfClosePara( s ); + RtfOpenPara( PS_PP, "" ); + } + else + if (!strcmp( s, "(*" )) { + RtfWord( NULL, "", "(" ); + RtfWord( CS_CT, "", "*" ); + } + else { + if (VerboseOutput) { + printf( "%s\n", s ); + } + RtfWord( AddFuncName( s ), "", s ); + State = FUNCPROTO_STATE_NAME2; + } + break; + + case FUNCPROTO_STATE_NAME2: + if (!strcmp( s, ")(" ) || !strcmp( s, "(" )) { + RtfWord( NULL, "", s ); + s = GetParaWord( FALSE ); + if (!strcmp( s, "VOID" )) { + RtfWord( CS_CT, " ", s ); + State = FUNCPROTO_STATE_PARM3; + *VoidFunction |= FUNC_TYPE_VOID_PARMS; + } + else { + RtfClosePara( "" ); + RtfOpenPara( PS_PP, "\t" ); + State = FUNCPROTO_STATE_PARM1; + FirstParmToken = TRUE; + goto donextword; + } + } + else { + return( FALSE ); + } + + break; + + case FUNCPROTO_STATE_PARM1: + if (strcmp( s, "IN" ) && strcmp( s, "OUT" )) { + State = FUNCPROTO_STATE_PARM2; + } + RtfWord( CS_CT, FirstParmToken ? "" : " ", s ); + FirstParmToken = FALSE; + break; + + case FUNCPROTO_STATE_PARM2: + if (!strcmp( s, "*" ) || !strcmp( s, "OPTIONAL" )) { + PrevAsterisk = (BOOLEAN)(*s == '*'); + RtfWord( CS_CT, " ", s ); + } + else + if (!strcmp( s, "," ) || !strcmp( s, "[]," )) { + RtfClosePara( s ); + RtfOpenPara( PS_PP, "\t" ); + State = FUNCPROTO_STATE_PARM1; + FirstParmToken = TRUE; + } + else + if (!strcmp( s, ")" ) || !strcmp( s, ");" ) || !strcmp( s, "[]" )) { + RtfClosePara( "" ); + RtfOpenPara( PS_PP, "\t" ); + RtfClosePara( s ); + State = FUNCPROTO_STATE_DONE; + } + else { + RtfWord( AddParmName( s ), PrevAsterisk ? "" : " ", s ); + PrevAsterisk = FALSE; + } + + break; + + case FUNCPROTO_STATE_PARM3: + if (!strcmp( s, ")" ) || !strcmp( s, ");" )) { + RtfClosePara( " )" ); + State = FUNCPROTO_STATE_DONE; + } + else { + return( FALSE ); + } + break; + + case FUNCPROTO_STATE_DONE: + if (strlen( s )) { + return( FALSE ); + } + + break; + + default: + return( FALSE ); + } + } + + return( TRUE ); +} + +BOOLEAN ProcessFunctionParameters( VOID ) +{ + PSZ PrevStyle; + + while (ReadTxtPara( FALSE )) { + if (TxtFilePara.Level == 0) { + return( TRUE ); + } + + if (TxtFilePara.Level == 1) { + OutputParagraph( PrevStyle = PS_PL, "", OUTPUT_PARA_FUNCPROTO ); + } + else + if (TxtFilePara.TrailingColon) { + if (TxtFilePara.Level == 2) { + RtfParagraph( PrevStyle = PS_P3, "", "", TxtFilePara.Text ); + } + else + if (TxtFilePara.Level == 3) { + RtfParagraph( PrevStyle = PS_P5, "", "", TxtFilePara.Text ); + } + else + if (TxtFilePara.Level == 4) { + RtfParagraph( PrevStyle = PS_P7, "", "", TxtFilePara.Text ); + } + else { + ErrorMessage( "Value/Flags/Class/Structure: at wrong level - %s", + TxtFilePara.Text + ); + } + } + else + if (TxtFilePara.Level == 2) { + if (PrevStyle == PS_PL || PrevStyle == PS_P2) { + OutputParagraph( PrevStyle = PS_P2, "", OUTPUT_PARA_FUNCPROTO ); + } + else { + OutputParagraph( PrevStyle = PS_P4, "", OUTPUT_PARA_FUNCPROTO ); + } + } + else + if (TxtFilePara.Level == 3) { + OutputParagraph( PrevStyle = PS_P6, "", OUTPUT_PARA_FUNCPROTO ); + } + else + if (TxtFilePara.Level == 4) { + OutputParagraph( PrevStyle = PS_P8, "", OUTPUT_PARA_FUNCPROTO ); + } + else { + ErrorMessage( "Text at wrong level - %s", TxtFilePara.Text ); + } + } + + return( TRUE ); +} + + +BOOLEAN ProcessStructure( VOID ) +{ + BOOLEAN PrevAsterisk; + BOOLEAN PrevStruct; + PSZ s, sEnd; + ULONG i; + + s = GetParaWord( FALSE ); + RtfOpenPara( PS_PP, s ); // typedef + s = GetParaWord( FALSE ); + RtfWord( NULL, " ", s ); // struct + s = GetParaWord( FALSE ); + RtfWord( CS_CT, " ", s ); // TypeName + s = GetParaWord( FALSE ); + RtfClosePara( " \\{" ); // { + RtfOpenPara( PS_PP, "" ); + + i = 0; + PrevAsterisk = FALSE; + PrevStruct = FALSE; + while (TRUE) { + s = GetParaWord( FALSE ); + if (!s) { + return( FALSE ); + } + + if (i == 0) { + if (!strcmp( s, "struct" )) { + RtfWord( CS_CT, "\t", s ); // TypeName + PrevStruct = TRUE; + } + else { + RtfWord( CS_CT, PrevStruct ? "" : "\t", s ); // TypeName + PrevStruct = FALSE; + i++; + } + } + else + if (i == 1) { + if (!strcmp( s, "*" )) { + RtfWord( CS_CT, " ", s ); // TypeName + PrevAsterisk = TRUE; + } + else { // FieldName + + RtfWord( AddParmName( s ), PrevAsterisk ? "" : " ", s ); + PrevAsterisk = FALSE; + i++; + } + } + else { + sEnd = s + strlen( s ) - 1; + if (*sEnd == '}') { + *sEnd = '\0'; + RtfClosePara( s ); + RtfOpenPara( PS_PP, "\\}" ); + break; + } + + RtfWord( NULL, "", s ); // [: 2] ; + if (*sEnd == ';' ) { + RtfClosePara( "" ); + RtfOpenPara( PS_PP, "" ); + i = 0; + } + } + } + + s = GetParaWord( FALSE ); + RtfWord( CS_CT, " ", s ); // TypeName + if (VerboseOutput) { + printf( "%s\n", s ); + } + s = GetParaWord( FALSE ); + RtfWord( NULL, "", "," ); // , + RtfWord( CS_CT, " ", "*" ); // * + s = GetParaWord( FALSE ); + RtfWord( CS_CT, "", s ); // PTypeName + s = GetParaWord( FALSE ); + RtfClosePara( s ); // ; + + ReadTxtPara( FALSE ); + if (TxtFilePara.Type != PARA_TXT || + !TxtFilePara.TrailingColon + ) { + ErrorMessage( "Missing Structure: line - %s", TxtFilePara.Text ); + } + + RtfParagraph( PS_PP, "", "", "" ); + RtfParagraph( PS_PP, CS_CR, "", TxtFilePara.Text ); + RtfParagraph( PS_PP, "", "", "" ); + + if (!ProcessFunctionParameters()) { + return( FALSE ); + } + + return( TRUE ); +} + + +BOOLEAN ProcessFunctionNames( VOID ) +{ + PSZ s; + + while (ReadTxtPara( TRUE )) { + if (TxtFilePara.Type == PARA_CMD) { + break; + } + + while (s = GetParaWord( TRUE )) { + AddFuncName( s ); + } + } + + return( CheckForEndCmd( TxtFilePara.Text ) ); +} + + +BOOLEAN ProcessFieldNames( VOID ) +{ + PSZ s; + + while (ReadTxtPara( TRUE )) { + if (TxtFilePara.Type == PARA_CMD) { + break; + } + + while (s = GetParaWord( TRUE )) { + AddParmName( s ); + } + } + + return( CheckForEndCmd( TxtFilePara.Text ) ); +} + + +BOOLEAN ProcessLiteralText( VOID ) +{ + while (ReadTxtPara( TRUE )) { + if (TxtFilePara.Type == PARA_CMD) { + break; + } + + RtfParagraph( PS_PC, "", "", TxtFilePara.Text ); + } + + RtfParagraph( PS_PC, "", "", "" ); + return( CheckForEndCmd( TxtFilePara.Text ) ); +} + + +BOOLEAN ProcessTextParagraph( VOID ) +{ + if (TxtFilePara.Bullet) { + ProcessBulletedList(); + } + else + if (TxtFilePara.FunctionPrototype) { + if (!ProcessFunction()) { + ErrorMessage( "Invalid function prototype", NULL ); + return( FALSE ); + } + } + else + if (!strncmp( TxtFilePara.Text, "typedef struct _", 16 )) { + if (!ProcessStructure()) { + ErrorMessage( "Invalid structure prototype", NULL ); + return( FALSE ); + } + } + else { + if (PreviousParagraphHeading && TxtFilePara.Lines < 4) { + OutputParagraph( PS_PSKEEP, "", OUTPUT_PARA_TEXT ); + } + else { + OutputParagraph( PS_PS, "", OUTPUT_PARA_TEXT ); + } + } + + PreviousParagraphHeading = FALSE; + return( TRUE ); +} + + +BOOLEAN OutputParagraph( + PSZ ParaStyle, + PSZ Bullet, + ULONG ParaType + ) +{ + ULONG WordCount; + CHAR c; + PSZ CharStyle; + PSZ s, s1, Separator; + SYMBOLTABLEVALUE Value; + BOOLEAN EmDash; + + RtfOpenPara( ParaStyle, Bullet ); + EmDash = FALSE; + WordCount = 0; + Separator = ""; + while (s = GetParaWord( TRUE )) { + WordCount++; + CharStyle = NULL; + if (TxtFilePara.EmDash && WordCount <= 3) { + if (TxtFilePara.CountOfTokensBeforeEmDash == (WordCount-1) && + !strcmp( s, "-" ) + ) { + s = EMDASH; + EmDash = TRUE; + } + else + if (ParaType != OUTPUT_PARA_TEXT) { + if (TxtFilePara.CountOfTokensBeforeEmDash == WordCount) { + if (ParaType == OUTPUT_PARA_FUNCPROTO) { + CharStyle = AddParmName( s ); + } + else { + CharStyle = AddFuncName( s ); + } + } + else + if (TxtFilePara.CountOfTokensBeforeEmDash == (WordCount+1)) { + if (ParaType == OUTPUT_PARA_FUNCPROTO) { + CharStyle = AddTypeName( s ); + } + else { + ErrorMessage( "Illegal function list syntax - %s", + TxtFilePara.Text + ); + } + } + } + } + else { + if (iscsymf( *s )) { + s1 = s; + while (iscsym( *s1 )) { + s1++; + } + + c = *s1; + *s1 = '\0'; + if (AccessSymbolTable( HighLightTable, + s, + &Value, + LookupAccess ) + ) { + CharStyle = (PSZ)Value; + if (c) { + RtfWord( CharStyle, Separator, s ); + CharStyle = NULL; + Separator = ""; + *s1 = c; + s = s1; + } + } + else { + *s1 = c; + } + } + } + + RtfWord( CharStyle, Separator, s ); + if (EmDash) { + EmDash = FALSE; + Separator = ""; + } + else + if (s[strlen( s )-1] == '.') { + Separator = " "; + } + else { + Separator = " "; + } + } + + RtfClosePara( "" ); + return( TRUE ); +} + + +PSZ +AddFuncName( + PSZ FuncString + ) +{ + PSZ HighLighting = CS_CP; + + AccessSymbolTable( HighLightTable, + FuncString, + (SYMBOLTABLEVALUE *)&HighLighting, + InsertAccess ); + + return( HighLighting ); +} + + +PSZ +AddParmName( + PSZ ParmString + ) +{ + PSZ HighLighting = CS_CI; + + AccessSymbolTable( HighLightTable, + ParmString, + (SYMBOLTABLEVALUE *)&HighLighting, + InsertAccess ); + + return( HighLighting ); +} + +PSZ +AddTypeName( + PSZ FuncString + ) +{ + PSZ HighLighting = CS_CT; + + AccessSymbolTable( HighLightTable, + FuncString, + (SYMBOLTABLEVALUE *)&HighLighting, + InsertAccess ); + + return( HighLighting ); +} + + +PSZ +SkipSpaces( + IN PSZ String + ) +{ + while (*String == ' ') { + String++; + } + + if (*String) + return( String ); + else + return( NULL ); +} + + +PSZ +MarkToken( + IN PSZ String + ) +{ + while (*String && *String != ' ') { + String++; + } + + if (*String) + *String++ ='\0'; + + return( SkipSpaces( String ) ); +} diff --git a/private/sdktools/doctor/sources b/private/sdktools/doctor/sources new file mode 100644 index 000000000..9b177eae3 --- /dev/null +++ b/private/sdktools/doctor/sources @@ -0,0 +1,17 @@ +MAJORCOMP=tools +MINORCOMP=doctor + +TARGETNAME=doctor +TARGETPATH=obj +TARGETTYPE=LIBRARY + +INCLUDES=..\ztools\inc + +SOURCES=readtxt.c \ + writertf.c \ + strings.c \ + symbol.c + +UMAPPL=doctor*c2rtf +UMTYPE=console +UMLIBS=obj\*\doctor.lib ..\ztools\src\obj\*\ztools.lib diff --git a/private/sdktools/doctor/strings.c b/private/sdktools/doctor/strings.c new file mode 100644 index 000000000..4d8b0d909 --- /dev/null +++ b/private/sdktools/doctor/strings.c @@ -0,0 +1,113 @@ + +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + strings.c + +Abstract: + + This module defines functions for manipulating counted strings. + +Author: + + Steve Wood (stevewo) 14-Mar-1989 + +Revision History: + +--*/ + +#include "doctor.h" + +PSTRING +MakeString( + IN PSZ AscizString OPTIONAL + ) +{ + register PSTRING ResultString; + ULONG cb; + + cb = AscizString ? strlen( AscizString ) : 0; + if (ResultString = AllocateMemory( sizeof(STRING) )) { + ResultString->Length = (USHORT)cb; + if (cb) { + ResultString->MaximumLength = (USHORT)(cb+1); + ResultString->Buffer = (PSZ)AllocateMemory( cb+1 ); + strcpy( ResultString->Buffer, AscizString ); + } + else { + ResultString->Buffer = NULL; + ResultString->MaximumLength = 0; + } + } + + return( ResultString ); +} + + +PSTRING +FreeString( + IN PSTRING String + ) +{ + if (String) { + if (String->Buffer) { + FreeMemory( String->Buffer ); + } + FreeMemory( String ); + String = NULL; + } + + return( String ); +} + + +PSTRING +EraseString( + IN OUT PSTRING String + ) +{ + if (String) { + if (String->Buffer) + FreeMemory( String->Buffer ); + String->Length = 0; + String->MaximumLength = 0; + String->Buffer = NULL; + } + + return( String ); +} + + +PSTRING +CopyString( + OUT PSTRING DestString OPTIONAL, + IN PSTRING SourceString + ) +{ + PSZ StringCopy; + + if (!(StringCopy = (PSZ)AllocateMemory( (ULONG) + (SourceString->MaximumLength) ))) + return( NULL ); + + if (!DestString) + DestString = MakeString( NULL ); + else + EraseString( DestString ); + + if (DestString) { + strncpy( DestString->Buffer = StringCopy, + SourceString->Buffer, + (DestString->Length = SourceString->Length) + ); + DestString->MaximumLength = SourceString->MaximumLength; + } + else { + FreeMemory( StringCopy ); + } + + return( DestString ); +} diff --git a/private/sdktools/doctor/strings.h b/private/sdktools/doctor/strings.h new file mode 100644 index 000000000..2a13123e0 --- /dev/null +++ b/private/sdktools/doctor/strings.h @@ -0,0 +1,24 @@ +// +// Entry points in strings.c +// + +PSTRING +MakeString( + IN PSZ AscizString OPTIONAL + ); + +PSTRING +FreeString( + IN PSTRING String + ); + +PSTRING +EraseString( + IN OUT PSTRING String + ); + +PSTRING +CopyString( + OUT PSTRING DestString OPTIONAL, + IN PSTRING SourceString + ); diff --git a/private/sdktools/doctor/symbol.c b/private/sdktools/doctor/symbol.c new file mode 100644 index 000000000..ace4033f9 --- /dev/null +++ b/private/sdktools/doctor/symbol.c @@ -0,0 +1,489 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + symbol.c + +Abstract: + + This module implements a general symbol table package. A symbol + table uses a fixed size hash table, with chaining used to resolve + collisions. The hash function is the sum of the characters, except + that the char. bits are rotated in order to distribute the bits + across the hash function. Characters are converted to upper case + in the hash function so that case insensitive lookup can be supported, + while preserving the original case that the symbol has when inserted. + + This module supports multiple symbol tables, so that clients, can + implement a primitive scoping mechanism. + +Author: + + Steve Wood (stevewo) 02-Mar-1989 + + +Revision History: + +--*/ + +#include "doctor.h" + +// +// Data definitions private to this module. +// + +typedef struct _SYMBOLTABLEENTRY { + struct _SYMBOLTABLEENTRY *ChainLink; + SYMBOLTABLEVALUE Value; + ULONG NameLength; + CHAR Name[1]; +} SYMBOLTABLEENTRY, *PSYMBOLTABLEENTRY; + +typedef LONG (_cdecl *SYMBOLTABLESTRCMP)( + IN PSZ String1, + IN PSZ String2, + IN ULONG String1Length + ); + +typedef struct _SYMBOLTABLE { + ULONG Size; + ULONG Id; + SYMBOLTABLESTRCMP StrCmp; + ULONG CountSymbols; + ULONG CountHashBuckets; + PSYMBOLTABLEENTRY HashBuckets[1]; +} SYMBOLTABLE, *PSYMBOLTABLE; + +#define SYMBOLTABLEID 1234 + + +// +// Function prototypes for procedures private to this module +// + +PSYMBOLTABLE +MapHandleToTable( + IN SYMBOLTABLEHANDLE SymbolTableHandle + ); + +// +// This function allocates memory for a symbol table. The first parameter +// specifies the number of hash buckets to use. The second parameter +// specifies whether symbol lookup for this table is case sensitive or not. +// +SYMBOLTABLEHANDLE +CreateSymbolTable( + IN ULONG CountHashBuckets, + IN BOOLEAN IsCaseSensitive + ) +{ + PSYMBOLTABLE SymbolTable; + ULONG i; + + i = sizeof(SYMBOLTABLE) + (CountHashBuckets * sizeof(PSYMBOLTABLEENTRY)); + SymbolTable = AllocateMemory( i ); + if (SymbolTable) { + SymbolTable->Size = i; + SymbolTable->Id = SYMBOLTABLEID; + SymbolTable->StrCmp = (SYMBOLTABLESTRCMP)(IsCaseSensitive ? + strncmp : _strnicmp); + SymbolTable->CountSymbols = 0; + SymbolTable->CountHashBuckets = CountHashBuckets; + for (i=0; i<CountHashBuckets; i++) { + SymbolTable->HashBuckets[ i ] = (PSYMBOLTABLEENTRY)NULL; + } + } + + return( (SYMBOLTABLEHANDLE)SymbolTable ); +} + + +// +// This function frees the memory associated with the passed symbol table. +// Returns NULL if successful. Otherwise returns its parameter. +// +SYMBOLTABLEHANDLE +DestroySymbolTable( + SYMBOLTABLEHANDLE SymbolTableHandle + ) +{ + PSYMBOLTABLE SymbolTable = MapHandleToTable( SymbolTableHandle ); + PSYMBOLTABLEENTRY TableEntry; + PSYMBOLTABLEENTRY NextTableEntry; + ULONG i; + + if (!SymbolTable) + return( SymbolTableHandle ); + + // + // Make the symbol table invalid + // + SymbolTable->Id = 0; + + // + // Enumerate each non-null entry, free the memory associated with it. + // Zero the hash buckets as we go. + // + for (i=0; i<SymbolTable->CountHashBuckets; i++) { + TableEntry = SymbolTable->HashBuckets[ i ]; + SymbolTable->HashBuckets[ i ] = NULL; + while (TableEntry) { + NextTableEntry = TableEntry->ChainLink; + FreeMemory( TableEntry ); + TableEntry = NextTableEntry; + } + } + SymbolTable->CountSymbols = 0; + SymbolTable->CountHashBuckets = 0; + + // + // Free the memory associated with the symbol table header. + + FreeMemory( SymbolTable ); + return( NULL ); +} + + +// +// Function to enumerate the entries in a symbol table. No order is implied +// other than random order. The passed enumeration function is called once +// for each entry and is passed the two values that were passed to the +// InsertSymbol call that created the entry. It is also allow to pass in +// one ULONG argument that will be passed uninterpreted to the enumeration +// function. +// +// The enumeration function should return TRUE if it wants to stop the +// enumeration. Otherwise it should return FALSE to continue the enumeration. +// +// This function return TRUE if the enumeration was stopped by the +// enumeration function returning TRUE. Otherwise this function returns +// FALSE if an invalid symbol table was passed in, or if all the entries +// in the table were enumerated without the enumeration function returning +// TRUE. +// + + +BOOLEAN +EnumerateSymbolTable( + IN SYMBOLTABLEHANDLE SymbolTableHandle, + IN SYMBOLTABLEENUMERATIONFUNCTION EnumerationFunction, + IN ULONG EnumerationArgument + ) +{ + PSYMBOLTABLE SymbolTable = MapHandleToTable( SymbolTableHandle ); + PSYMBOLTABLEENTRY TableEntry; + PSYMBOLTABLEENTRY NextTableEntry; + BOOLEAN StopEnumeration = FALSE; + ULONG i; + + // + // Do nothing and return FALSE if invalid string table or null enumeration + // function passed. + // + if (!SymbolTable || !EnumerationFunction) { + return( FALSE ); + } + + // + // Enumerate each non-null entry until either the enumeration function + // stops the enumeration by returning TRUE or the end of the table is + // reached. + // + for (i=0; !StopEnumeration && i<SymbolTable->CountHashBuckets; i++) { + TableEntry = SymbolTable->HashBuckets[ i ]; + while (!StopEnumeration && TableEntry) { + NextTableEntry = TableEntry->ChainLink; + StopEnumeration = (*EnumerationFunction)( EnumerationArgument, + TableEntry->Name, + TableEntry->Value ); + TableEntry = NextTableEntry; + } + } + + // + // Return TRUE if enumeration function terminated the enumeration, and + // FALSE otherwise. + // + return( StopEnumeration ); +} + + +// +// This functions allows a client to maniputate the contents of a symbol +// table. It supports four operations: +// +// Lookup, Modify, Insert and Delete +// +// The Lookup, Modify and Delete operations succeed only if the passed +// name matches an entry in the symbol table. If a match is found and +// and the Value parameter is specified, then it will receive the value +// associated with the symbol found. In the case of Modify, the old and +// new values are exchanged. +// +// If the passed name is NOT found in the symbol table then all but the +// Insert operation will return FALSE. The Insert operation returns +// failure only if it is unable to allocate memory for the new entry. +// + +BOOLEAN +AccessSymbolTable( + SYMBOLTABLEHANDLE SymbolTableHandle, + IN PSZ Name, + IN OUT SYMBOLTABLEVALUE *Value OPTIONAL, + IN SYMBOLTABLEACCESS Access + ) +{ + PSYMBOLTABLE SymbolTable = MapHandleToTable( SymbolTableHandle ); + PSYMBOLTABLEENTRY *HeadTableEntry; + PSYMBOLTABLEENTRY TableEntry; + PSYMBOLTABLEENTRY NewTableEntry; + ULONG NameLength; + LONG ComparisonResult = -1; + SYMBOLTABLEVALUE NewValue = 0; + register PSZ s; + register ULONG h; + char c; + + // + // Validate symbol table and name pointers. Zero length names + // invalid also. + // + ; + if (!SymbolTable || !(s = Name) && !*s) + return( FALSE ); + + // + // Dummy up a valid Value pointer if none supplied. + // + if (!ARGUMENT_PRESENT( Value )) + Value = &NewValue; + + + // + // Compute the address of the head of the bucket chain for this name. + // + h = 0; + while (c = *s++) { + h += (h << 1) + (h >> 1) + c; + if (islower( c )) + h += (ULONG)('A'-'a'); + } + + HeadTableEntry = &SymbolTable->HashBuckets[ h % SymbolTable->CountHashBuckets ]; + + // + // Walt the chain of symbol table entries for this hash bucket, looking + // for either a match, or the insertion point if no match in the chain. + // + NameLength = strlen( Name ); + while (TableEntry = *HeadTableEntry) { + if (NameLength == TableEntry->NameLength) { + // + // Compare strings using appropriate function. + // + ComparisonResult = + (*SymbolTable->StrCmp)( Name, TableEntry->Name, NameLength ); + // + // If name matches, then exit loop with TableEntry pointing to + // matching entry. + // + if (!ComparisonResult) { + break; + } + + // + // If name less than name of current, then exit loop with + // TableEntry set to NULL and HeadTableEntry pointing to + // the insertion point if that is requested. + // + if (ComparisonResult < 0) { + TableEntry = NULL; + break; + } + + // + // Otherwise, name greater than this name, so continue to next + // entry on chain. + // + } + + HeadTableEntry = &TableEntry->ChainLink; + } + + // + // At this point, there are two possiblilities: + // + // - we found an entry that matched and TableEntry points to that + // entry. HeadTableEntry points to the pointer value that points + // to the entry found. (i.e. *HeadTableEntry == TableEntry). This + // is so the delete function can unlink the entry from the chain. + // + // - we did not find an entry that matched and TableEntry is NULL. + // HeadTableEntry points to the pointer value that points to entry + // to insert a new entry before. This is so the insertion function + // can link the new entry into the chain. + // + if (TableEntry) { + if (Access == LookupAccess) { + // + // Lookup function - just return the value. + // + *Value = TableEntry->Value; + return( TRUE ); + } + + else + if (Access == DeleteAccess) { + // + // Delete function - unlink the entry from the chain and free + // the memory for the entry. Decrement the count of entries + // in the table. + // + *HeadTableEntry = TableEntry->ChainLink; + *Value = TableEntry->Value; + TableEntry->ChainLink = NULL; + FreeMemory( TableEntry ); + SymbolTable->CountSymbols--; + return( TRUE ); + } + else + if (Access == ModifyAccess) { + // + // Modify function - return old value and update entry with + // new value. + // + *Value = TableEntry->Value; + TableEntry->Value = NewValue; + return( TRUE ); + } + else + // + // Insert function - return failure since it is already there + // + return( FALSE ); + } + else + // + // No match found - return failure if not insert function + // + if (Access != InsertAccess) + return( FALSE ); + + + // + // Insert function - allocate memory for a new entry. Fail if + // not enough memory. + // + NewTableEntry = (PSYMBOLTABLEENTRY) + AllocateMemory( sizeof( SYMBOLTABLEENTRY ) + + NameLength ); + + if (NewTableEntry) { + // + // Link the new entry into the chain at the insertion point. + // + NewTableEntry->ChainLink = *HeadTableEntry; + *HeadTableEntry = NewTableEntry; + + // + // Store the value, name length and name string in the entry. + // The name string will have a terminating null byte just for + // convenience. + // + NewTableEntry->Value = *Value; + NewTableEntry->NameLength = NameLength; + strncpy( NewTableEntry->Name, Name, NameLength+1 ); + + // + // Increment the count of entries in the symbol table and return + // success. + // + SymbolTable->CountSymbols++; + return( TRUE ); + } + else { + return( FALSE ); + } +} + + +// +// Function to map a string table handle to a pointer to string table. +// Assumes the handle is just the pointer, and validates that it really +// points to a string table. +// +PSYMBOLTABLE +MapHandleToTable( + IN SYMBOLTABLEHANDLE SymbolTableHandle + ) +{ + PSYMBOLTABLE SymbolTable = (PSYMBOLTABLE)SymbolTableHandle; + + // + // If non-null handle, and it points to valid string table Id then + // return the pointer. Otherwise return NULL. + // + if (SymbolTable && SymbolTable->Id == SYMBOLTABLEID) { + return( SymbolTable ); + } + else { + return( (PSYMBOLTABLE)NULL ); + } +} + + +#if DBG + +VOID +PrintSymbolTable( + IN SYMBOLTABLEHANDLE SymbolTableHandle, + IN FILE *PrintFileHandle OPTIONAL + ) +{ + PSYMBOLTABLE SymbolTable = MapHandleToTable( SymbolTableHandle ); + PSYMBOLTABLEENTRY TableEntry; + ULONG i; + + if (!ARGUMENT_PRESENT( PrintFileHandle )) + PrintFileHandle = stdout; + + fprintf( PrintFileHandle, + "Symbol Table Handle = %p\n", SymbolTableHandle ); + fprintf( PrintFileHandle, + "Size = %d\n", SymbolTable->Size ); + fprintf( PrintFileHandle, + "Id = %d\n", SymbolTable->Id ); + fprintf( PrintFileHandle, + "Case Sensitive: %s\n", + SymbolTable->StrCmp == (SYMBOLTABLESTRCMP)strncmp ? "Yes" : "No" ); + fprintf( PrintFileHandle, + "Count of Symbols = %d\n", SymbolTable->CountSymbols ); + fprintf( PrintFileHandle, + "Count of Hash Buckets: %d\n", SymbolTable->CountHashBuckets ); + + // + // Enumerate each non-null entry until either the enumeration function + // stops the enumeration by returning TRUE or the end of the table is + // reached. + // + for (i=0; i<SymbolTable->CountHashBuckets; i++) { + if (TableEntry = SymbolTable->HashBuckets[ i ]) + fprintf( PrintFileHandle, "chain[%2d]: ", i ); + while (TableEntry) { + fprintf( PrintFileHandle, "%4x (%2d) %-32s = %p\n", + TableEntry, + TableEntry->NameLength, + TableEntry->Name, + TableEntry->Value ); + + if (TableEntry = TableEntry->ChainLink) + fprintf( PrintFileHandle, " " ); + } + } + + fprintf( PrintFileHandle, "\n" ); +} + +#endif //DBG diff --git a/private/sdktools/doctor/symbol.h b/private/sdktools/doctor/symbol.h new file mode 100644 index 000000000..7f803a5f0 --- /dev/null +++ b/private/sdktools/doctor/symbol.h @@ -0,0 +1,53 @@ +// +// Entry points in symbol.c +// +typedef HANDLE SYMBOLTABLEHANDLE; +typedef ULONG SYMBOLTABLEVALUE; + +SYMBOLTABLEHANDLE +CreateSymbolTable( + IN ULONG CountHashBuckets, + IN BOOLEAN IsCaseSensitive + ); + +SYMBOLTABLEHANDLE +DestroySymbolTable( + SYMBOLTABLEHANDLE SymbolTableHandle + ); + +typedef enum _SYMBOLTABLEACCESS { + LookupAccess, + InsertAccess, + DeleteAccess, + ModifyAccess +} SYMBOLTABLEACCESS; + +BOOLEAN +AccessSymbolTable( + SYMBOLTABLEHANDLE SymbolTableHandle, + IN PSZ Name, + IN OUT SYMBOLTABLEVALUE *Value, + IN SYMBOLTABLEACCESS Access + ); + +typedef BOOLEAN (*SYMBOLTABLEENUMERATIONFUNCTION)( + IN ULONG EnumerationArgument, + IN PSZ Name, + IN SYMBOLTABLEVALUE Value + ); + +BOOLEAN +EnumerateSymbolTable( + IN SYMBOLTABLEHANDLE SymbolTableHandle, + IN SYMBOLTABLEENUMERATIONFUNCTION EnumerationFunction, + IN ULONG EnumerationArgument + ); + + +#if DBG +VOID +PrintSymbolTable( + IN SYMBOLTABLEHANDLE SymbolTableHandle, + IN FILE *PrintFileHandle OPTIONAL + ); +#endif diff --git a/private/sdktools/doctor/writertf.c b/private/sdktools/doctor/writertf.c new file mode 100644 index 000000000..2c5f33fe5 --- /dev/null +++ b/private/sdktools/doctor/writertf.c @@ -0,0 +1,251 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + writertf.c + +Abstract: + + This module contains the code to output in Rich Text Format (RTF) + +Author: + + Steve Wood (stevewo) 02-Mar-1989 + +Revision History: + +--*/ + +#include "doctor.h" + +#define RTF_TEMPLATE_FILE "DOCTOR.RTF" + +char RtfTemplateFileName[ 256 ]; +FILE *RtfTemplateFileHandle; // File handle of RTF template file + +FILE *RtfFileHandle; // File handle of RTF output file + +#define RtfOut fprintf( RtfFileHandle, + +BOOLEAN +OpenRtfFile( + IN PSZ RtfFileName + ) +{ + PSZ FilePart; + + if (!SearchPath( getenv( "PATH" ), + RTF_TEMPLATE_FILE, + NULL, + sizeof( RtfTemplateFileName ), + RtfTemplateFileName, + &FilePart + ) + ) { + fprintf( stderr, + "DOCTOR: Unable to find %s template file\n", + RTF_TEMPLATE_FILE + ); + + exit( 1 ); + } + + if (!(RtfTemplateFileHandle = fopen( RtfTemplateFileName, "r" ))) { + fprintf( stderr, + "DOCTOR: Unable to open %s template file\n", + RtfTemplateFileName + ); + + exit( 1 ); + } + +#if 0 + RtfFileHandle = stderr; + return( TRUE ); +#else + if (RtfFileHandle = fopen( RtfFileName, "w" )) { + return( TRUE ); + } + else + return( FALSE ); +#endif +} + + +BOOLEAN +CloseRtfFile( VOID ) +{ + int c; + + if (RtfTemplateFileHandle) { + if (RtfFileHandle) { + while ((c = fgetc( RtfTemplateFileHandle )) != EOF) { + fputc( c, RtfFileHandle ); + } + } + + if (!fclose( RtfTemplateFileHandle )) { + RtfTemplateFileHandle = NULL; + } + } + + if (RtfFileHandle) { + if (!fclose( RtfFileHandle )) { + RtfFileHandle = NULL; + return( TRUE ); + } + } + + return( FALSE ); +} + + +char *MonthNames[] = { + NULL, + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December" +}; + +BOOLEAN +RtfTitlePage( + IN PSZ Title, + IN PSZ Author, + IN PSZ Revision, + IN PSZ Creation + ) +{ + int c; + SYSTEMTIME date; + + GetSystemTime( &date ); + + while ((c = fgetc( RtfTemplateFileHandle )) != EOF) { + if (c != '%') { + fputc( c, RtfFileHandle ); + } + else + switch (fgetc( RtfTemplateFileHandle )) { + case 'D': // Day + RtfOut "%02d", date.wDay ); + break; + + case 'M': // Month + RtfOut "%02d", date.wMonth ); + break; + + case 'Y': // Year + RtfOut "%02d", date.wYear ); + break; + + case 'N': // Document Name or Title + RtfOut "%s", Title ); + break; + + case 'A': // Author + RtfOut "%s", Author ); + break; + + case 'C': // Creation + RtfOut "%s", Creation ); + break; + + case 'V': // Version + RtfOut "%s", Revision ); + break; + + case 'R': // Revision + RtfOut "%s, %s %d, %d", + Revision, + MonthNames[ date.wMonth ], + date.wDay, + date.wYear ); + break; + + case 'T': // Text of document + return TRUE; + + default: + fprintf( stderr, "DOCTOR: %s file is invalid\n", + RtfTemplateFileName + ); + return FALSE; + } + } + + return( FALSE ); +} + + +BOOLEAN +RtfHeading( + ULONG HeadingLevel, + PSZ HeadingNumber, + PSZ HeadingTitle + ) +{ + switch( HeadingLevel ) { + case 0: RtfOut "%s%s %s\\par\n", PS_H1, HeadingNumber, HeadingTitle ); break; + case 1: RtfOut "%s%s %s\\par\n", PS_H2, HeadingNumber, HeadingTitle ); break; + case 2: RtfOut "%s%s %s\\par\n", PS_H3, HeadingNumber, HeadingTitle ); break; + case 3: RtfOut "%s%s %s\\par\n", PS_H4, HeadingNumber, HeadingTitle ); break; + case 4: RtfOut "%s%s %s\\par\n", PS_H5, HeadingNumber, HeadingTitle ); break; + default:RtfOut "%s%s %s\\par\n", PS_HN, HeadingNumber, HeadingTitle ); break; + } + return( TRUE ); +} + + +BOOLEAN +RtfParagraph( + PSZ ParagraphStyle, + PSZ CharStyle, + PSZ ParagraphBullet, + PSZ ParagraphText + ) +{ + RtfOut "%s%s%s%s\\par\n", + ParagraphStyle, + CharStyle, + ParagraphBullet, + ParagraphText + ); + return( TRUE ); +} + +BOOLEAN +RtfOpenPara( + PSZ ParagraphStyle, + PSZ LeadingText + ) +{ + RtfOut "%s%s", ParagraphStyle, LeadingText ); + return( TRUE ); +} + +BOOLEAN +RtfClosePara( + PSZ TrailingText + ) +{ + RtfOut "\\plain %s\\par\n", TrailingText ); + return( TRUE ); +} + +BOOLEAN +RtfWord( + PSZ CharStyle, + PSZ LeadingText, + PSZ WordText + ) +{ + if (CharStyle == NULL) { + RtfOut "%s%s", LeadingText, WordText ); + } + else { + RtfOut "%s%s%s\\plain ", LeadingText, CharStyle, WordText ); + } + + return( TRUE ); +} |