Category : C Source Code
Archive   : CXREF2TC.ZIP
Filename : CXREF.C

 
Output of file : CXREF.C contained in archive : CXREF2TC.ZIP
/*
This is the original CXREF source which compiled under the DataLight
C compiler. I have modified it so that it will compile under Turbo
C by Borland.

A few notes are in order. I have attempted to note the places where
I modified the code. You can search for May-1990 to find the
modifications. DO NOT attempt to replace STRICMP with Turbo C's
version of the same!! You will cause the system to lock in the
routine BinarySearch() if you try. I did! I replaced what was
apparently a Datalight C command called index() which returned
whether or not a character was present in a string with strchr().

NOTE: If you attempted to run the old DataLight CXREF on any file
which had nested include files (i.e. an include file which called
another include file) the program would bomb. I corrected that by
adding a test noted in the code. My "fix" involved simply not
allowing the nested include to print which must have been
inadvertantly omitted. If you want to fix the program so that
nested includes print you will need to modify the code further so
that the push of the currently printing file is to an array of the
authors FileDefs rather than a simple push of the currently printing
file to MainFile. Puruse the code and I believe you will
understand.

The program does NOT do a lot of error checking (for null pointer
assignments and the like) so, if you are going to run this on large
source files with includes and all the cross referencing you should
compile it in the large memory model:

tcc -ml cxref

is all that is needed assuming you have your include/lib paths set
in the config file for TC. Also make sure you have enough disk
space since this thing doesn't even check for out of space errors.
The source should compile without error or warning - unless you have
the "no prototypes" warning turned on.

The program will compile and work just fine in the SMALL model as
well, you just won't be able to list large source code with large
cross reference lists using the SMALL model of the program.

Modified May-1990

Roland M. Brown III

This code is in the public domain and remains so with my
modifications.

*/


#include
#include
#include /*May-1990 */
#include /*May-1990 */
#include /*May-1990 */


#define NestMax 10
#define TRUE 1 /*May-1990 */
#define FALSE 0 /*May-1990 */

char CR = 0x0D;
char IDChar[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz_";
char TINCLUDE[] = "#include";
char *Reserved[] = {
"auto",
"break",
"case",
"char",
"continue",
"default",
"do",
"double",
"else",
"entry",
"extern",
"float",
"for",
"goto",
"if",
"int",
"long",
"register",
"return",
"short",
"sizeof",
"static",
"struct",
"switch",
"typedef",
"union",
"unsigned",
"void",
"while"
};


typedef struct {
FILE *ID;
char Name[64];
int Lnno;
char InsertChar;
int EndFile, First, Print;
} FileDef;

typedef struct LR {
struct LR *Next;
int Key;
char Code;
} LineRec;

typedef struct {
LineRec *First, *Current;
} LineQueueRec;

typedef struct {
char *Key;
LineQueueRec *LineList;
} WordRec;

typedef struct TR {
struct TR *Left, *Right;
WordRec *Ref;
} TreeRec;

int PageNum, PageLn;
TreeRec *Root;
FileDef MainFile, IncludeFile, InFile;
FILE *Output;
int TotalLn, ChIndex;
int Listing, StdFlag, IncludeFlag;
int NestUp, NestDn, NestLvl;
int Tabs;
char Token[30], Path[64], IncludePath[64];
int i;
char FDate[9], FTime[9]; /*May-1990 */
char Today[30];
char OutFileName[64];
char Ch;
int UnGetCount = 0;
char UnGot = ' ';
char Line[255];

/*These Prototypes Added you can add more */

int BinarySearch(char *T, char *A[], int Num); /*May-1990 */
TreeRec *BinaryTree (TreeRec *wl); /*May-1990 */
void Concordance (TreeRec *T); /*May-1990 */
void AddQueue (LineQueueRec *Queue); /*May-1990 */
char *FillString (char *Str, int Size, char Char); /*May-1990 */
void UpperCase (char *Str); /*May-1990 */
void GetFileDate(int Handle, char *Date, char *Time); /*May-1990 */


void main (argc, argv)
int argc;
char *argv[];
{
/*Here are some more things for you to prototype*/

void Init(), Header(), GetLiteral(), GetIncludeFile();
void GetCharLiteral(), GetComment(), GetToken(), PrintLine();
void Usage(), GotoXY();

FILE *fopen();
char GetChar();

Init();
if (argc < 2) Usage();
else {
for (i = 1; i < argc; i++) {
strcpy(Token, argv[i]);
if (Token[0] == '-') {
UpperCase(Token);
if (strcmp(Token, "-NL") == 0) Listing = FALSE;
else if (strcmp(Token, "-NS") == 0) StdFlag = FALSE;
else if (strcmp(Token, "-NI") == 0) IncludeFlag = FALSE;
else if (Token[1] == 'T') {
if (i+1 < argc) Tabs = atoi(argv[++i]);
else fprintf(stderr, "Invalid Tab option\n");
}
else if (Token[1] == 'I') {
if (i+1 < argc) {
strcpy(IncludePath, argv[++i]);
if (IncludePath[strlen(IncludePath)-1] != '\\')
strcat(IncludePath, "\\");
}
else fprintf(stderr, "Invalid Include Path option\n");
}
else {
fprintf(stderr, "Invalid option: %s\n", argv[i]);
}
}
else if (strlen(InFile.Name) == 0) strcpy(InFile.Name, argv[i]);
else if (strlen(OutFileName) == 0) strcpy(OutFileName, argv[i]);
else {
fprintf(stderr, "Invalid parameter or too many file names: %s\n", argv[i]);
exit(3);
}
}
}
if (strlen(InFile.Name) == 0) {
fprintf(stderr, "I have nothing to do! No input file specified.\n");
exit(3);
}
if (strchr(InFile.Name, '.') == NULL) strcat(InFile.Name, ".C"); /*May-1990 */
for (i = strlen(InFile.Name); i >= 0; i--) {
if ((InFile.Name[i] == '\\') || (InFile.Name[i] == '/') || (InFile.Name[i] == ':')) break;
}
if (i < 0) strcpy(Path, "");
else {
strncpy(Path, InFile.Name, i+1);
Path[i+1] = '\0';
}
if (strlen(OutFileName) == 0) {
strcpy(OutFileName, InFile.Name);
*strchr(OutFileName, '.') = 0x00; /*May-1990 */
}
if (strchr(OutFileName,'.') == NULL) strcat(OutFileName, ".LST"); /*May-1990 */
if ((InFile.ID = fopen(InFile.Name, "r")) == NULL) {
fprintf(stderr, "I can't find input file: %s\n", InFile.Name);
exit(3);
}
InFile.Lnno = 0; InFile.EndFile = FALSE; InFile.Print = TRUE;
InFile.First = TRUE;
if ((Output = fopen(OutFileName, "w")) == NULL) {
fprintf(stderr, "I can't create output file: %s\n", OutFileName);
exit(3);
}
MainFile = InFile; ChIndex = 0;
GetFileDate(fileno(InFile.ID), FDate, FTime); /*May-1990 */
strcpy(Today," Date: "); /*May-1990 */
strcat(Today, FDate); strcat(Today, " @ "); strcat(Today, FTime); /*May-1990 */

if (Listing) Header();
while (!MainFile.EndFile) {
while (!InFile.EndFile) {
Ch = GetChar();
if (Ch == '"') GetLiteral();

/*May-1990 Added test for InsertChar below*/

else if ((Ch == '#') && IncludeFlag && (InFile.InsertChar==' ')) GetIncludeFile();
else if (Ch == '\'') GetCharLiteral();
else if (Ch == '/') GetComment();
else if (strchr(IDChar, Ch) != NULL) GetToken();
else if (Ch == '{') {
if (NestLvl == NestMax) fprintf(stderr, "---- Too many levels\n");
else {
NestLvl++; NestUp = TRUE;
}
}
else if (Ch == '}') {
if (NestLvl == 0) fprintf(stderr, "---- Nesting Error");
else {
NestLvl--; NestDn = TRUE;
}
}
}
PrintLine();
if (InFile.InsertChar != ' ') {
fclose(InFile.ID);
InFile = MainFile; ChIndex = 0;
}
else MainFile = InFile;
}
Header(); fprintf(stderr, "\n");
fprintf(stderr, "Writing Cross Reference\n");
Concordance(Root);
fclose(Output);
fprintf(stderr, " Total Pages= %d\n", PageNum);
}

void BackCh (Ch)
char Ch;
{
UnGot = Ch; UnGetCount = 1;
}

char GetChar () {
char Ch, InLine[255];
int i, j;

if (UnGetCount) {
UnGetCount = 0; return(UnGot);
}
if (InFile.First) {
InFile.ID = fopen(InFile.Name, "r");
InFile.First = FALSE;
}
if (ChIndex == 0) {
if (!InFile.EndFile) {
if (InFile.Print) {
InFile.Print = FALSE; fprintf(stderr, "\n");
fprintf(stderr, "Line= %4d%c Total Lines= %4d ", InFile.Lnno,
InFile.InsertChar, TotalLn);
if (InFile.InsertChar != ' ') fprintf(stderr, "%13s", "");
fprintf(stderr, "%s", InFile.Name); fputc(CR, stderr);
}
else PrintLine();
fgets(InLine, 255, InFile.ID);
i = j = 0;
while (InLine[i]) {
if (InLine[i] == '\t') {
do Line[j++] = ' ';
while (j % Tabs);
}
else Line[j++] = InLine[i];
++i;
}
Line[j] = 0x00;
if (feof(InFile.ID)) InFile.EndFile = TRUE;
else {
Line[strlen(Line)-1] = 0x00;
InFile.Lnno++; TotalLn++;
GotoXY(6, WhereY()); fprintf(stderr, "%4d%c",
InFile.Lnno, InFile.InsertChar);
GotoXY(25, WhereY()); fprintf(stderr, "%4d", TotalLn);
NestUp = FALSE; NestDn = FALSE;
ChIndex = 1;
}
}
}
if (!InFile.EndFile) {
if (ChIndex <= strlen(Line)) Ch = Line[ChIndex++- 1];
else {
Ch = ' '; ChIndex = 0;
}
}
return(Ch);
}

void Init () {
printf("C Cross Reference: Version 2.00TC May-1990 \n\n");
PageNum = 0; Root = NULL; InFile.InsertChar = ' '; TotalLn = 0;
IncludeFile.InsertChar = '@';
Listing = TRUE; StdFlag = TRUE; IncludeFlag = TRUE;
NestUp = FALSE; NestDn = FALSE; NestLvl = 0; Tabs = 4;
IncludePath[0] = 0x00;
}

void UpperCase (char *Str)

{
int i;

for (i = 0; i < strlen(Str); i++)
if (islower(Str[i])) Str[i] = (char) toupper(Str[i]);
}

void GetFileDate (int Handle, char *Date, char *Time)

{
union REGS regs; /*May-1990 */
/*Modified to use Turbo Reg
Defs*/
regs.x.ax = 0x5700; regs.x.bx = Handle;
intdos(®s, ®s);
sprintf(Date, "%02d-%02d-%02d", ((regs.x.dx >> 5) & 0x0F), (regs.x.dx & 0x1F),((regs.x.dx >> 9)+80));
sprintf(Time, "%02d:%02d:%02d", (regs.x.cx >> 11), ((regs.x.cx >> 5) & 0x3F), (regs.x.cx & 0x1F));
}

void Header () {
PageNum++;
fputc(0x0C, Output); /* Form Feed */
fprintf(Output, "%-48s", MainFile.Name);
fprintf(Output, "Block Structure and Cross Reference");
fprintf(Output, "%29s Page %3d", Today, PageNum);
fprintf(Output, "\n\n\n");
PageLn = 60;
}

void GetLiteral () {
char Ch;

do {
Ch = GetChar();
if (Ch == '\\') {
Ch = GetChar(); Ch = GetChar();
}
}
while ((!InFile.EndFile) && (Ch != '"'));
}

void GetIncludeFile () {

void PrintLine(), GetToken();

int i, OK;
char DeLim;
char Temp[64];

GetToken();
if (STRICMP(Token, TINCLUDE) == 0) {
OK = TRUE;
while ((!InFile.EndFile) && (Ch == ' ')) Ch = GetChar();
switch (Ch) {
case '"': DeLim = Ch;
break;
case '<': DeLim = '>';
break;
default: DeLim = ' ';
}
for (i=0; ((!InFile.EndFile) && ((Ch = GetChar()) != DeLim)); i++) {
Temp[i] = Ch;
}
Temp[i] = 0x00;
if (InFile.InsertChar == 'Z') {
fprintf(stderr, "Too many include files\n");
OK = FALSE;
}
else {
if (DeLim == '"') {
strcpy(IncludeFile.Name, Path); strcat(IncludeFile.Name, Temp);
}
else {
strcpy(IncludeFile.Name, IncludePath);
strcat(IncludeFile.Name, Temp);
}
IncludeFile.InsertChar++;
IncludeFile.Lnno = 0; IncludeFile.EndFile = FALSE;
IncludeFile.Print = TRUE; IncludeFile.First = TRUE;
if ((IncludeFile.ID = fopen(IncludeFile.Name, "r")) == NULL) {
fprintf(stderr, "\nCan't find include file: %s\n", IncludeFile.Name);
OK = FALSE;
}
}
PrintLine();
if (OK) {
MainFile = InFile; MainFile.Print = TRUE;
InFile = IncludeFile;
ChIndex = 0;
}
}
}

void PrintLine () {
void FillLine();

int Column;

if (Listing) {
fprintf(Output, "%4d%c ", InFile.Lnno, InFile.InsertChar);
for (Column=0; Column < NestLvl-1; Column++) fprintf(Output,"| ");
if (NestLvl > 0) {
if (NestUp || NestDn) {
if (NestDn) {
fprintf(Output, "| ");
fprintf(Output, "E--");
for (Column=NestLvl+1; Column < NestMax; Column++)
fprintf(Output, "---");
}
else {
fprintf(Output, "B--");
for (Column=NestLvl; Column < NestMax; Column++)
fprintf(Output, "---");
}
FillLine(Line);
}
else {
fprintf(Output, "| ");
for (Column=NestLvl; Column < NestMax; Column++)
fprintf(Output, " ");
}
}
else if (NestDn) {
fprintf(Output, "E--");
for (Column=1; Column FillLine(Line);
}
else for (Column=0; Column fprintf(Output, "%s\n", Line);
PageLn--;
if (PageLn <= 0) Header();
}
}

void FillLine (Line)
char *Line;
{
int i;

for(i=0; i }


void GetToken () {

int j;

j = 0;
do {
Token[j] = Ch; j++; Ch = GetChar();
}
while ((strchr(IDChar, Ch) != NULL) && (!InFile.EndFile));
Token[j] = 0x00;
if (StdFlag) Root = BinaryTree(Root);
else if (!BinarySearch(Token, Reserved, 29)) Root = BinaryTree(Root);
}

void GetComment () {
char Ch;

if (!InFile.EndFile) Ch = GetChar();
if ((!InFile.EndFile) && (Ch == '*')) {
while ((!InFile.EndFile) && (Ch != '/')) {
while((!InFile.EndFile) && (Ch != '*')) Ch = GetChar();
Ch = GetChar();
}
}
else BackCh(Ch);
}

void GetCharLiteral () {
char Ch;

do {
Ch = GetChar();
if (Ch == '\\') {
Ch = GetChar(); Ch = GetChar();
}
}
while ((!InFile.EndFile) && (Ch != '\''));
}




int BinarySearch(char *T, char *A[], int Num)

{
int i, j, k, Result;

i = 0; j = Num;
do {
k = (i + j) / 2;
Result = STRICMP(A[k], T); /*May-1990 */
switch (Result) {
case -1: i = ++k;
break;
case 1: j = --k;
break;
default: break;
}
}
while ((Result != 0) && (i <= j));
if (Result == 0) return(TRUE);
else return(FALSE);
}


TreeRec *BinaryTree (TreeRec *wl)

{

TreeRec *w;

w = wl;
if (w == NULL) {
w = (TreeRec *) malloc(sizeof(*w));
w->Ref = (WordRec *) malloc(sizeof(*(w->Ref)));
w->Left = w->Right = NULL;
wl = w;
w->Ref->Key = (char *)malloc(strlen(Token)+1); strcpy(w->Ref->Key, Token);
w->Ref->LineList = (LineQueueRec *) malloc(sizeof(*(w->Ref->LineList)));
w->Ref->LineList->First = NULL;
AddQueue(w->Ref->LineList);
}
else {
switch (STRICMP(Token, w->Ref->Key)) { /*May-1990 */
case -1: w->Left = BinaryTree(w->Left);
break;
case 1: w->Right = BinaryTree(w->Right);
break;
case 0: AddQueue(w->Ref->LineList);
break;
}
}
return(w);
}


void AddQueue (LineQueueRec *Queue)

{
LineRec *w;

w = (LineRec *) malloc(sizeof(LineRec));
if (Queue->First == NULL) Queue->First = w;
else Queue->Current->Next = w;
Queue->Current = w;
w->Next = NULL; w->Key = InFile.Lnno; w->Code = InFile.InsertChar;
}

char *FillString (char *Str, int Size, char Char) /*May-1990 */

{
char Temp[255];
int l;

strcpy(Temp, Str);
if (strlen(Temp) < Size) {
strcat(Temp, " ");
l = strlen(Temp);
while (l < Size) Temp[l++] = Char;
Temp[l] = 0x00;
}
return(Temp);
}



void Concordance (TreeRec *T) /*May-1990 */
{

static char OldCh = 'A';
LineRec *P;
int i;

if (T != NULL) {
Concordance(T->Left);
if (toupper(T->Ref->Key[0]) != OldCh) {
fprintf(Output, "\n"); PageLn--;
if (PageLn <= 0) Header();
OldCh = toupper(T->Ref->Key[0]);
}
fprintf(Output, "%s ", FillString(T->Ref->Key, 26, '.'));
if (!BinarySearch(T->Ref->Key, Reserved, 29)) fprintf(Output, "%c", ' ');
else fprintf(Output, "%c", 'R');
P = T->Ref->LineList->First; i = 0;
while (P != NULL) {
if (i >= 17) {
fprintf(Output, "\n"); i = 0;
PageLn--;
if (PageLn <= 0) Header();
fprintf(Output, "%28s", " ");
}
fprintf(Output, "%4d%c", P->Key, P->Code);
i++;
if (i < 17) fprintf(Output, "%s", " ");
P = P->Next;
}
if (i > 0) {
fprintf(Output, "\n");
PageLn--;
if (PageLn <= 0) Header();
}
Concordance(T->Right);
}
}

void Usage () {

fprintf(stderr, "USAGE: cxref input_file_spec [output_file_spec] [options]\n\n");
fprintf(stderr, "\t-NL\tSuppress production of listing\n");
fprintf(stderr, "\t-NS\tSuppress cross reference of C key words\n");
fprintf(stderr, "\t-NI\tSuppress analysis of #include files\n\n");
fprintf(stderr, "\t-I Provide path for #include files\n");
fprintf(stderr, "\t-T Provide the tab stop value for tab expansion\n");
exit(3);
}


/*
Originally these routines were each in a seperate .C file, but I
didn't see the point for turbo c so I just put them here. You can
put them back if you wish.

*/


void GotoXY (x, y)
int x, y;
{
union REGS regs; /*May-1990 * Modifiied to use TC Regs defs*/

regs.x.dx = (y << 8) | (x & 0xFF);
regs.x.bx = 0;
regs.x.ax = 0x200;
int86(0x10, ®s, ®s);
}


int WhereY () {

union REGS regs; /*May-1990 * Modifiied to use TC Regs defs*/

regs.x.ax = 0x0300;
regs.x.bx = 0;
int86(0x10, ®s, ®s);
return(regs.x.dx >> 8);
}


int STRICMP (a, b)
char *a, *b;
{
int Result;

while (((Result = toupper(*a++) - toupper(*b++)) == 0) && (*(a-1) != 0));
if (Result < 0) Result = -1;
if (Result > 0) Result = 1;
return(Result);
}



  3 Responses to “Category : C Source Code
Archive   : CXREF2TC.ZIP
Filename : CXREF.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/