/*

  This is a part of the Project Frontier's Source code.

  Copyright (C) 1997-98 Francis Gastellu
                    aka Lone Runner/Aegis

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

// PowerPPL Compiler - Library utility sources

#include <dir.h>
#include <stdio.h>
#include <alloc.h>
#include "fortify.h"

#define IDENTIFIERINC 32

// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

typedef struct {
    char *name;
    int type;
    char nDim;
    int dim1;
    int dim2;
    int dim3;
    void *data;
    void *paramTypes;
    int external;
    long offset;
	} identListType;

// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

void registerLibVars(char *name, int libNum);
int openLib(char *namel);
void unallocMem(void);
void allocMem(void);
void buildProcMsg(char *d, int var);

// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

char drive[MAXDRIVE];
char dir[MAXDIR];
char name[MAXFILE];
char ext[MAXEXT];
FILE *lib;
char msg[256];

identListType **identList=NULL;
int identListSize=0;
int identListPos=0;

int identHdr, procCount;

char far *Type[18] = {
	  "Boolean",//            =    0x00;
	  "DWord",//              =    0x01;
	  "Date",//               =    0x02;
	  "EDate",//              =    0x03;
	  "Long",//               =    0x04;
	  "Money",//              =    0x05;
	  "Real",//               =    0x06;
	  "String",//             =    0x07;
	  "Time",//               =    0x08;
	  "Byte",//               =    0x09;
	  "Word",//               =    0x0A;
	  "SByte",//              =    0x0B;
	  "Int",//                =    0x0C;
	  "BigStr",//             =    0x0D;
	  "Double",//             =    0x0E;
	  "Function",//           =    0x0F;
	  "Procedure",//          =    0x10;
      "DDate"//               =    0x11;
	  };

// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

void main(int argc, char **argv)
{
int a, b, c;
#ifdef FORTIFY
Fortify_EnterScope();
#endif

printf("PowerPPL Library Viewer v1.02 by Lone Runner\n(C)1996 The AEGiS Corporation.\n\n");

if (argc < 2)
	{
    printf("Usage: pplib filename[.lib]\n");
    exit(-1);
    }

allocMem();

registerLibVars(argv[1], 1);

if (identListPos == 0)
	exit(-1);

printf("Listing contents of library %s\n\n", argv[1]);
printf("Public symbols:\n\n");
c=0;
for (a=0;a<identListPos;a++)
	{
    if (*(identList[a]->name) == 1)
    	continue;
    if (*(char*)(identList[a]->name) >= '0' && *(char*)(identList[a]->name) <= '9')
    	continue;
    if (*(char*)(identList[a]->name) == '\"')
    	continue;
    if (strlen((char*)(identList[a]->name)) > 25)
    	((char*)(identList[a]->name))[26]=0;
	printf("    %-25s    %-12s\n", (char*)(identList[a]->name), Type[identList[a]->type]);
    c++;
    }

if (c==0)
	printf("    (none)\n");

c=0;
printf("\nDetail of functions & procedures parameters:\n\n");
for (a=0;a<identListPos;a++)
	{
    if (identList[a]->type != 0x0F && identList[a]->type != 0x10)
    	continue;

    *msg=0;
    buildProcMsg(msg, a);
	printf("    %s\n", msg);
    c++;
    }

if (c == 0)
	printf("    (none)\n");

unallocMem();

#ifdef FORTIFY
Fortify_LeaveScope();
#endif
}

// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

int openLib(char *namel)
{

fnsplit(namel,drive,dir,name,ext);
if (*ext == 0)
	strcpy(ext, ".lib");
fnmerge(msg, drive, dir, name, ext);

	if ((lib = fopen(msg, "rb")) == NULL)
		{
		printf("library not found (%s%s)\n", name, ext);
        return 0;
        }

	fread(&msg, 25, 1, lib);
	msg[25]=0;
	if (strcmp("Frontier PPL LIB  1.01\r\n\x1A", msg) && strcmp("Frontier PPL LIB  1.02\r\n\x1A", msg))
		{
		if (!strncmp("Frontier PPL LIB  ", msg, 18) && !strncmp("\r\n\x1A", msg+22, 3))
        	printf("incompatible library version, recompile or get an update (%s%s)\n", name, ext);
        else
			printf("invalid library (%s%s)\n", name, ext);
	    fclose(lib);
	    return 0;
	    }
	return 1;

}

// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
// ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

void registerLibVars(char *name, int libNum)
{
identListType *l;
int a,b,d,e,r, nident;
char f;
int H;
unsigned long blockSize=0;
unsigned long varblocklen;
int prevHdr=0;

if (!openLib(name))
	return;

fread(&blockSize, 4, 1, lib);
fread(&varblocklen, 4, 1, lib);
fread(&nident, 2, 1, lib);
H = identListPos;
for (b=1;b<=nident;b++)
	{
	while (identListPos + 1 > identListSize)
		{
	    identListSize += IDENTIFIERINC;
	    identList = realloc(identList, identListSize*sizeof(identListType *));
	    }
    identList[identListPos] = (identListType*) malloc(sizeof(identListType));
    l = identList[identListPos];
    identListPos++;

    fread(&d, 2, 1, lib);
    l->name = malloc(d+1);
    fread(l->name, d, 1, lib); 	// name
    if (*l->name == 1)
    	{
        if (prevHdr != l->name[1])
        	{
			identHdr = ++procCount;
        	prevHdr = l->name[1];
            }
        l->name[1] = identHdr;
        }
    fread(&l->nDim, 1, 1, lib); 	// ndim
    fread(&l->dim1, 2, 1, lib); 	// dim1
    fread(&l->dim2, 2, 1, lib); 	// dim2
    fread(&l->dim3, 2, 1, lib); 	// dim3
    fread(&l->type, 2, 1, lib); 	// vartype
    if (l->type == 7)
    	{
	    fread(&d, 2, 1, lib); 			// len of data
		l->data = malloc(d+1);
	    fread(l->data, d, 1, lib); 		// data
        }
    else
    	{
    	fread(&l->type, 2, 1, lib); 	// vartype
		l->data = malloc(8);
	    fread(l->data, 8, 1, lib); 		// data
        }

    if (l->type == 0xF || l->type == 0x10)
    	{
	    fread(&f, 1, 1, lib);
        l->paramTypes = malloc(f+1);
        fread(l->paramTypes, f, 1, lib);
        fread(&l->offset, 4, 1, lib);
        }
    else
    	l->paramTypes=NULL;
    l->external=libNum;
    }

for (a=H;a<identListPos;a++)
	{
    if (identList[a]->type == 0x10 || identList[a]->type == 0x0F)
    	{
        e = *((int*)(identList[a]->data)+2);
        e += H;
        *((int*)(identList[a]->data)+2) = e;
        if (identList[a]->type == 0x0F)
        	{
	        r = *((int*)(identList[a]->data)+3);
    	    r += H;
	        *((int*)(identList[a]->data)+3) = r;
            }
        }
	}

fclose(lib);
identHdr=0;
}

void allocMem(void)
{
identListSize += IDENTIFIERINC;
identList = calloc(identListSize,sizeof(identListType*));
identListPos=0;
}

void unallocMem(void)
{
int a;

for (a=0;a<identListPos;a++)
	{
    free(identList[a]->name);
	free(identList[a]->data);
    if (identList[a]->paramTypes != NULL)
    	free(identList[a]->paramTypes);
    free(identList[a]);
    }
identListSize=0;
identListPos=0;
if (identList!=NULL) free(identList);
identList=NULL;
}

void buildProcMsg(char *d, int var)
{
int f,a,e;
char *pt;
int bm;

if (identList[var]->type != 0x10 && identList[var]->type != 0x0F)
	printf("internal error building proc/func params\n");

strcat(d, identList[var]->type == 0x10 ? "Procedure " : "Function ");
strcat(d, identList[var]->name);
strcat(d, "(");

f = *(char*)identList[var]->data;
e = *((int*)(identList[var]->data)+2);
bm = *((int*)(identList[var]->data)+3);
pt = identList[var]->paramTypes;

for (a=0;a<f;a++)
	{
    if (a>0)
    	strcat(d, ", ");
    if (identList[var]->type == 0x10 && (bm & (1 << a)))
    	strcat(d, "Var ");
    strcat(d, Type[pt[a]]);
    strcat(d, " ");
    strcat(d, (char *)(identList[e]->name)+2);
    e++;
    }

strcat(d, ")");
if (identList[var]->type == 0x0F)
	{
	strcat(d, " ");
    f = *((int*)identList[var]->data+3);
	strcat(d, Type[identList[f]->type]);
    }
}
